1########################################################################
2##
3## Copyright (C) 2018-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26classdef weboptions < handle
27
28  ## -*- texinfo -*-
29  ## @deftypefn  {} {@var{output} =} weboptions ()
30  ## @deftypefnx {} {@var{output} =} weboptions (@var{name1}, @var{value1}, @dots{})
31  ##
32  ## Specify parameters for RESTful web services.
33  ##
34  ## @code{weboptions} with no inputs returns a default @code{weboptions} object
35  ## to specify parameters for a request to a web service.  A @code{weboptions}
36  ## object can be an optional input argument to the @code{webread} and
37  ## @code{webwrite} functions.
38  ##
39  ## Multiple name and value pair arguments may be specified in any order as
40  ## @var{name1}, @var{value1}, @var{name2}, @var{value2}, etc.
41  ##
42  ## The option names must match @strong{exactly} one of those specified in the
43  ## table below.
44  ##
45  ## The following options are available:
46  ##
47  ## @itemize @bullet
48  ## @item
49  ## @samp{CharacterEncoding} --- Specify the character encoding of the data:
50  ##
51  ## @samp{auto} (default), @samp{UTF-8}, @samp{US-ASCII}
52  ## @samp{auto} chooses an encoding based on the content-type of the data.
53  ##
54  ## @item
55  ## @samp{UserAgent} --- Specify the User Agent for the connection.
56  ##
57  ## Default value is @samp{GNU Octave/version}, where @samp{version} is the
58  ## current version of Octave as returned by @code{version}.
59  ##
60  ## @item
61  ## @samp{Timeout} --- Specify the timeout value for the connection in seconds.
62  ##
63  ## Default is 10 seconds.  @samp{Inf} is not currently supported.
64  ##
65  ## @item
66  ## @samp{Username} --- User identifier for a basic HTTP connection.
67  ##
68  ## Default is NULL@.  It must be a string.
69  ##
70  ## @item
71  ## @samp{Password} --- User authentication password for HTTP connection.
72  ##
73  ## Default is NULL@.  It must be a string or character vector.
74  ## Programming Note: If you display a @code{weboption} object with the Password
75  ## property set, the value is displayed as a string containing
76  ## @qcode{'*'}.  However, the object stores the value of the Password
77  ## property as plain text.
78  ##
79  ## @item
80  ## @samp{KeyName} --- Specify the name of an additional key to be added to
81  ## the HTTP request header.  It should be coupled with @samp{KeyValue}.  It
82  ## must be a string or character vector.
83  ##
84  ## @item
85  ## @samp{KeyValue} --- Specify the value of the key @samp{KeyName}.
86  ##
87  ## @samp{KeyName} must be present in order to assign to this field.
88  ##
89  ## @item
90  ## @samp{@nospell{HeaderFields}} --- Specify the header fields for the
91  ## connection.
92  ##
93  ## Names and values of header fields, specified as an m-by-2 array of strings
94  ## or cell array of character vectors to add to the HTTP request header.
95  ## @nospell{HeaderFields}@{i,1@} is the name of a field and
96  ## @nospell{HeaderFields}@{i,2@} is its value.
97  ##
98  ## @example
99  ## @group
100  ## weboptions ("HeaderFields", @{"Content-Length" "78";"Content-Type" "application/json"@})
101  ## Creates a weboptions object that contains two header fields: Content-Length
102  ## with value 78 and Content-Type with value application/json.
103  ## @end group
104  ## @end example
105  ##
106  ## @item
107  ## @samp{ContentType} --- Specify the content type of the data.
108  ##
109  ## The following values are available:
110  ## @samp{auto}, @samp{text}, @samp{json}
111  ##
112  ## Default is @samp{auto}.  It automatically determines the content type.
113  ## All other formats like @samp{audio}, @samp{binary}, etc.@: available in
114  ## @sc{matlab} are not currently supported.
115  ##
116  ## @item
117  ## @samp{ContentReader} --- Not yet implemented.  Only for @sc{matlab}
118  ## compatibility.
119  ##
120  ## @item
121  ## @samp{MediaType} --- Not yet implemented.  Only for @sc{matlab}
122  ## compatibility.
123  ##
124  ## @item
125  ## @samp{RequestMethod} --- Specifies the type of request to be made.
126  ##
127  ## The following methods are available:
128  ## @samp{get}, @samp{put}, @samp{post}, @samp{delete}, @samp{patch}
129  ##
130  ## @code{webread} uses the HTTP GET method.  @code{webwrite} uses the HTTP POST
131  ## method as default.
132  ##
133  ## @item
134  ## @samp{ArrayFormat} -- Not yet implemented.  Only for @sc{matlab}
135  ## compatibility.
136  ##
137  ## @item
138  ## @samp{CertificateFilename} --- Not yet implemented.  Only for @sc{matlab}
139  ## compatibility.
140  ## @end itemize
141  ##
142  ## @seealso{webread, webwrite}
143  ## @end deftypefn
144
145  properties
146    CharacterEncoding = "auto";
147    UserAgent = ["GNU Octave/", version()];
148    Timeout = 10;
149    Username = "";
150    Password = "";
151    KeyName = "";
152    KeyValue = "";
153    HeaderFields = {};
154    ContentType = "auto";
155    ContentReader = "";
156    MediaType = "auto";
157    RequestMethod = "auto";
158    ArrayFormat = "csv";
159    CertificateFilename = "";
160  endproperties
161
162  methods
163    function f = weboptions (varargin)
164      if (rem (numel (varargin), 2) != 0)
165        error ("weboptions: invalid number of arguments");
166      else
167        h = cell2struct (varargin(2:2:end), varargin(1:2:end), 2);
168        if (numfields (h) > 14)
169          error ("weboptions: invalid number of arguments");
170        endif
171
172        if (isfield (h, "CharacterEncoding"))
173          f.CharacterEncoding = h.CharacterEncoding;
174          h = rmfield (h, "CharacterEncoding");
175        endif
176
177        if (isfield (h, "UserAgent"))
178          f.UserAgent = h.UserAgent;
179          h = rmfield (h, "UserAgent");
180        endif
181
182        if (isfield (h, "Timeout"))
183          f.Timeout = h.Timeout;
184          h = rmfield (h, "Timeout");
185        endif
186
187        if (isfield (h, "Username"))
188          f.Username = h.Username;
189          h = rmfield (h, "Username");
190        endif
191
192        if (isfield (h, "Password"))
193          f.Password = h.Password;
194          h = rmfield (h, "Password");
195        endif
196
197        if (isfield (h, "KeyName"))
198          f.KeyName = h.KeyName;
199          h = rmfield (h, "KeyName");
200        endif
201
202        if (isfield (h, "KeyValue"))
203          f.KeyValue = h.KeyValue;
204          h = rmfield (h, "KeyValue");
205        endif
206
207        if (isfield (h, "HeaderFields"))
208          f.HeaderFields = h.HeaderFields;
209          h = rmfield (h, "HeaderFields");
210        endif
211
212        if (isfield (h, "ContentType"))
213          f.ContentType = h.ContentType;
214          h = rmfield (h, "ContentType");
215        endif
216
217        if (isfield (h, "ContentReader"))
218          f.ContentReader = h.ContentReader;
219          h = rmfield (h, "ContentReader");
220        endif
221
222        if (isfield (h, "MediaType"))
223          f.MediaType = h.MediaType;
224          h = rmfield (h, "MediaType");
225        endif
226
227        if (isfield (h, "RequestMethod"))
228          f.RequestMethod = h.RequestMethod;
229          h = rmfield (h, "RequestMethod");
230        endif
231
232        if (isfield (h, "ArrayFormat"))
233          f.ArrayFormat = h.ArrayFormat;
234          h = rmfield (h, "ArrayFormat");
235        endif
236
237        if (isfield (h, "CertificateFilename"))
238          f.CertificateFilename = h.CertificateFilename;
239          h = rmfield (h, "CertificateFilename");
240        endif
241
242        if (! isempty (fieldnames (h)))
243          field = fieldnames (h){1};
244          error (["weboptions: Undefined field " field]);
245        endif
246      endif
247    endfunction
248
249    function f = set.CharacterEncoding (f, value)
250      if (! any (strcmpi (value, {"UTF-8", 'US-ASCII', "auto"})));
251        error ("weboptions: Invalid CharacterEncoding value");
252      else
253        f.CharacterEncoding = value;
254      endif
255    endfunction
256
257    function f = set.UserAgent (f, value)
258      if (! ischar (value) && ! isrow (value));
259        error ("weboptions: UserAgent must be a string");
260      else
261        f.UserAgent = value;
262      endif
263    endfunction
264
265    function f = set.Timeout (f, value)
266      if (! isreal (value) || ! isscalar (value)
267          || floor(value) != value || value < 0)
268        error ("weboptions: invalid Timeout value");
269      else
270        f.Timeout = value;
271      endif
272    endfunction
273
274    function f = set.Username (f, value)
275      if (! ischar (value) && ! isrow (value))
276        error ("weboptions: Username must be a string");
277      else
278        f.Username = value;
279      endif
280    endfunction
281
282    function f = set.Password (f, value)
283      if (! ischar (value) && ! isrow (value))
284        error ("weboptions: Password must be a string");
285      else
286        f.Password = value;
287      endif
288    endfunction
289
290    function f = set.KeyName (f, value)
291      if (! ischar (value) && ! isrow (value))
292        error ("weboptions: invalid KeyName value");
293      else
294        f.KeyName = value;
295      endif
296    endfunction
297
298    function f = set.KeyValue (f, value)
299      if (isempty (f.KeyName) && ! isempty (value))
300        error ("weboptions: field KeyName empty.  Cannot set KeyValue.");
301      else
302        f.KeyValue = value;
303      endif
304    endfunction
305
306    function f = set.HeaderFields (f, value)
307      if (! isempty (value))
308        if (! iscellstr (value) || ! ismatrix (value))
309          error ("weboptions: HeaderFields must be array of strings or a cell array");
310        elseif (columns (value) != 2)
311          error ("weboptions: HeaderFields must be of size m-by-2");
312        endif
313      endif
314      f.HeaderFields = value;
315    endfunction
316
317    function f = set.ContentType (f, value)
318      if (! isempty (value))
319        if (! any (strcmpi (value, {"auto", "json", "text"})))
320          error ("weboptions: invalid ContentType value");
321        endif
322      endif
323      f.ContentType = value;
324    endfunction
325
326    function f = set.ContentReader (f, value)
327      f.ContentReader = value;
328    endfunction
329
330    function f = set.MediaType (f, value)
331      f.MediaType = value;
332    endfunction
333
334    function f = set.RequestMethod (f, value)
335      if (! isempty (value))
336        if (! any (strcmpi (value, {"auto", "get", "put", "post",...
337                                    "delete", "patch"})))
338          error ("weboptions: invalid RequestMethod value");
339        endif
340      endif
341      f.RequestMethod = value;
342    endfunction
343
344    function f = set.ArrayFormat (f, value)
345      if (! isempty (value))
346        if (! any (strcmpi (value, {"csv", "json", "php", "repeating"})))
347          error ("weboptions: invalid ArrayFormat value");
348        endif
349      endif
350      f.ArrayFormat = value;
351    endfunction
352
353    function f = set.CertificateFilename (f, value)
354      f.CertificateFilename = value;
355    endfunction
356
357    function display (f)
358      Timeout = int2str (f.Timeout);
359      Password = repmat ("*", 1, numel (num2str (f.Password)));
360
361      if (! isempty (f.ContentReader))
362        ContentReader = ['["', strjoin(f.ContentReader, '", "'), '"]'];
363      else
364        ContentReader = "[]";
365      endif
366
367      if (! isempty (f.HeaderFields))
368        HeaderFields = ['{"', strjoin(f.HeaderFields, '", "'), '"}'];
369      else
370        HeaderFields = "{}";
371      endif
372
373      if (! isempty (f.KeyValue))
374        KeyValue = num2str (f.KeyValue);
375      else
376        KeyValue = "''";
377      endif
378
379      printf ("%s =", inputname (1));
380      output = ["\n\n   weboptions with properties:     \n",...
381                "\n      CharacterEncoding: '", f.CharacterEncoding, "'",...
382                "\n              UserAgent: '", f.UserAgent, "'",...
383                "\n                Timeout: " , Timeout, "",...
384                "\n               Username: '", f.Username, "'",...
385                "\n               Password: '", Password, "'",...
386                "\n                KeyName: '", f.KeyName, "'",...
387                "\n               KeyValue: " , KeyValue,...
388                "\n            ContentType: '", f.ContentType, "'",...
389                "\n          ContentReader: " , ContentReader,...
390                "\n              MediaType: '", f.MediaType, "'",...
391                "\n          RequestMethod: '", f.RequestMethod, "'",...
392                "\n            ArrayFormat: '", f.ArrayFormat, "'",...
393                "\n           HeaderFields: " , HeaderFields,...
394                "\n    CertificateFilename: '", f.CertificateFilename, "'\n"];
395      disp (output);
396    endfunction
397
398  endmethods
399
400endclassdef
401
402