From 7206dff963311ffb583f4fea2d58213f27b12bf6 Mon Sep 17 00:00:00 2001 From: Abderahmane BENALI <46283596+benaliabderrahmane@users.noreply.github.com> Date: Mon, 2 Aug 2021 21:35:38 +0100 Subject: [PATCH 1/5] working code for both x and y axis data type: date time, duration and duration with a specific format --- plotly/plotly_aux/getuserdir.m | 24 +- .../plotly_aux/urlread2/http_createHeader.m | 20 +- .../plotly_aux/urlread2/http_paramsToString.m | 122 +-- plotly/plotly_aux/urlread2/urlread2.m | 742 +++++++++--------- plotly/plotly_aux/urlread2/urlread_notes.txt | 172 ++-- plotly/plotly_aux/urlread2/urlread_todos.txt | 24 +- .../urlread2/urlread_versionInfo.txt | 24 +- plotly/plotlyfig.m | 2 +- plotly/plotlyfig_aux/core/updateAxis.m | 117 ++- plotly/plotlyfig_aux/core/updateData.m | 20 + .../plotlyfig_aux/helpers/convert Duration.m | 26 + plotly/plotlyfig_aux/helpers/convertDate.m | 7 +- 12 files changed, 689 insertions(+), 611 deletions(-) create mode 100644 plotly/plotlyfig_aux/helpers/convert Duration.m diff --git a/plotly/plotly_aux/getuserdir.m b/plotly/plotly_aux/getuserdir.m index 844f0ab3..9ce384b8 100644 --- a/plotly/plotly_aux/getuserdir.m +++ b/plotly/plotly_aux/getuserdir.m @@ -1,13 +1,13 @@ -function userDir = getuserdir -% GETUSERDIR Retrieve the user directory -% - Under Windows returns the %APPDATA% directory -% - For other OSs uses java to retrieve the user.home directory - -if ispc - % userDir = winqueryreg('HKEY_CURRENT_USER',... - % ['Software\Microsoft\Windows\CurrentVersion\' ... - % 'Explorer\Shell Folders'],'Personal'); - userDir = getenv('appdata'); -else - userDir = char(java.lang.System.getProperty('user.home')); +function userDir = getuserdir +% GETUSERDIR Retrieve the user directory +% - Under Windows returns the %APPDATA% directory +% - For other OSs uses java to retrieve the user.home directory + +if ispc + % userDir = winqueryreg('HKEY_CURRENT_USER',... + % ['Software\Microsoft\Windows\CurrentVersion\' ... + % 'Explorer\Shell Folders'],'Personal'); + userDir = getenv('appdata'); +else + userDir = char(java.lang.System.getProperty('user.home')); end \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/http_createHeader.m b/plotly/plotly_aux/urlread2/http_createHeader.m index 457be94f..0e80241f 100755 --- a/plotly/plotly_aux/urlread2/http_createHeader.m +++ b/plotly/plotly_aux/urlread2/http_createHeader.m @@ -1,11 +1,11 @@ -function header = http_createHeader(name,value) -%http_createHeader Simple function for creating input header to urlread2 -% -% header = http_createHeader(name,value) -% -% CODE: header = struct('name',name,'value',value); -% -% See Also: -% urlread2 - +function header = http_createHeader(name,value) +%http_createHeader Simple function for creating input header to urlread2 +% +% header = http_createHeader(name,value) +% +% CODE: header = struct('name',name,'value',value); +% +% See Also: +% urlread2 + header = struct('name',name,'value',value); \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/http_paramsToString.m b/plotly/plotly_aux/urlread2/http_paramsToString.m index f9bc490c..376a0fa1 100755 --- a/plotly/plotly_aux/urlread2/http_paramsToString.m +++ b/plotly/plotly_aux/urlread2/http_paramsToString.m @@ -1,62 +1,62 @@ -function [str,header] = http_paramsToString(params,encodeOption) -%http_paramsToString Creates string for a POST or GET requests -% -% [queryString,header] = http_paramsToString(params, *encodeOption) -% -% INPUTS -% ======================================================================= -% params: cell array of property/value pairs -% NOTE: If the input is in a 2 column matrix, then first column -% entries are properties and the second column entries are -% values, however this is NOT necessary (generally linear) -% encodeOption: (default 1) -% 1 - the typical URL encoding scheme (Java call) -% -% OUTPUTS -% ======================================================================= -% queryString: querystring to add onto URL (LACKS "?", see example) -% header : the header that should be attached for post requests when -% using urlread2 -% -% EXAMPLE: -% ============================================================== -% params = {'cmd' 'search' 'db' 'pubmed' 'term' 'wtf batman'}; -% queryString = http_paramsToString(params); -% queryString => cmd=search&db=pubmed&term=wtf+batman -% -% IMPORTANT: This function does not filter parameters, sort them, -% or remove empty inputs (if necessary), this must be done before hand - -if ~exist('encodeOption','var') - encodeOption = 1; -end - -if size(params,2) == 2 && size(params,1) > 1 - params = params'; - params = params(:); -end - -str = ''; -for i=1:2:length(params) - if (i == 1), separator = ''; else separator = '&'; end - switch encodeOption - case 1 - param = urlencode(params{i}); - value = urlencode(params{i+1}); -% case 2 -% param = oauth.percentEncodeString(params{i}); -% value = oauth.percentEncodeString(params{i+1}); -% header = http_getContentTypeHeader(1); - otherwise - error('Case not used') - end - str = [str separator param '=' value]; %#ok -end - -switch encodeOption - case 1 - header = http_createHeader('Content-Type','application/x-www-form-urlencoded'); -end - - +function [str,header] = http_paramsToString(params,encodeOption) +%http_paramsToString Creates string for a POST or GET requests +% +% [queryString,header] = http_paramsToString(params, *encodeOption) +% +% INPUTS +% ======================================================================= +% params: cell array of property/value pairs +% NOTE: If the input is in a 2 column matrix, then first column +% entries are properties and the second column entries are +% values, however this is NOT necessary (generally linear) +% encodeOption: (default 1) +% 1 - the typical URL encoding scheme (Java call) +% +% OUTPUTS +% ======================================================================= +% queryString: querystring to add onto URL (LACKS "?", see example) +% header : the header that should be attached for post requests when +% using urlread2 +% +% EXAMPLE: +% ============================================================== +% params = {'cmd' 'search' 'db' 'pubmed' 'term' 'wtf batman'}; +% queryString = http_paramsToString(params); +% queryString => cmd=search&db=pubmed&term=wtf+batman +% +% IMPORTANT: This function does not filter parameters, sort them, +% or remove empty inputs (if necessary), this must be done before hand + +if ~exist('encodeOption','var') + encodeOption = 1; +end + +if size(params,2) == 2 && size(params,1) > 1 + params = params'; + params = params(:); +end + +str = ''; +for i=1:2:length(params) + if (i == 1), separator = ''; else separator = '&'; end + switch encodeOption + case 1 + param = urlencode(params{i}); + value = urlencode(params{i+1}); +% case 2 +% param = oauth.percentEncodeString(params{i}); +% value = oauth.percentEncodeString(params{i+1}); +% header = http_getContentTypeHeader(1); + otherwise + error('Case not used') + end + str = [str separator param '=' value]; %#ok +end + +switch encodeOption + case 1 + header = http_createHeader('Content-Type','application/x-www-form-urlencoded'); +end + + end \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/urlread2.m b/plotly/plotly_aux/urlread2/urlread2.m index 53ba8ca6..b552861c 100755 --- a/plotly/plotly_aux/urlread2/urlread2.m +++ b/plotly/plotly_aux/urlread2/urlread2.m @@ -1,371 +1,371 @@ -function [output,extras] = urlread2(urlChar,method,body,headersIn,varargin) -%urlread2 Makes HTTP requests and processes response -% -% [output,extras] = urlread2(urlChar, *method, *body, *headersIn, varargin) -% -% * indicates optional inputs that must be entered in place -% -% UNDOCUMENTED MATLAB VERSION -% -% EXAMPLE CALLING FORMS -% ... = urlread2(urlChar) -% ... = urlread2(urlChar,'GET','',[],prop1,value1,prop2,value2,etc) -% ... = urlread2(urlChar,'POST',body,headers) -% -% FEATURES -% ======================================================================= -% 1) Allows specification of any HTTP method -% 2) Allows specification of any header. Very little is hard-coded -% in for header handling. -% 3) Returns response status and headers -% 4) Should handle unicode properly ... -% -% OUTPUTS -% ======================================================================= -% output : body of the response, either text or binary depending upon -% CAST_OUTPUT property -% extras : (structure) -% .allHeaders - stucture, fields have cellstr values, HTTP headers may -% may be repeated but will have a single field entry, with each -% repeat's value another being another entry in the cellstr, for -% example: -% .Set_Cookie = {'first_value' 'second_value'} -% .firstHeaders - (structure), variable fields, contains the first -% string entry for each field in allHeaders, this -% structure can be used to avoid dereferencing a cell -% for fields you expect not to be repeated ... -% EXAMPLE: -% .Response : 'HTTP/1.1 200 OK'} -% .Server : 'nginx' -% .Date : 'Tue, 29 Nov 2011 02:23:16 GMT' -% .Content_Type : 'text/html; charset=UTF-8' -% .Content_Length : '109155' -% .Connection : 'keep-alive' -% .Vary : 'Accept-Encoding, User-Agent' -% .Cache_Control : 'max-age=60, private' -% .Set_Cookie : 'first_value' -% .status - (structure) -% .value : numeric value of status, ex. 200 -% .msg : message that goes along with status, ex. 'OK' -% .url - eventual url that led to output, this can change from -% the input with redirects, see FOLLOW_REDIRECTS -% .isGood - (logical) I believe this is an indicator of the presence of 400 -% or 500 status codes (see status.value) but more -% testing is needed. In other words, true if status.value < 400. -% In code, set true if the response was obtainable without -% resorting to checking the error stream. -% -% INPUTS -% ======================================================================= -% urlChar : The full url, must include scheme (http, https) -% method : examples: 'GET' 'POST' etc -% body : (vector)(char, uint8 or int8) body to write, generally used -% with POST or PUT, use of uint8 or int8 ensures that the -% body input is not manipulated before sending, char is sent -% via unicode2native function with ENCODING input (see below) -% headersIn : (structure array), use empty [] or '' if no headers are needed -% but varargin property/value pairs are, multiple headers -% may be passed in as a structure array -% .name - (string), name of the header, a name property is used -% instead of a field because the name must match a valid -% header -% .value - (string), value to use -% -% OPTIONAL INPUTS (varargin, property/value pairs) -% ======================================================================= -% CAST_OUTPUT : (default true) output is uint8, useful if the body -% of the response is not text -% ENCODING : (default ''), ENCODING input to function unicode2native -% FOLLOW_REDIRECTS : (default true), if false 3xx status codes will -% be returned and need to be handled by the user, -% note this does not handle javascript or meta tag -% redirects, just server based ones -% READ_TIMEOUT : (default 0), 0 means no timeout, value is in -% milliseconds -% -% EXAMPLES -% ======================================================================= -% GET: -% -------------------------------------------- -% url = 'http://www.mathworks.com/matlabcentral/fileexchange/'; -% query = 'urlread2'; -% params = {'term' query}; -% queryString = http_paramsToString(params,1); -% url = [url '?' queryString]; -% [output,extras] = urlread2(url); -% -% POST: -% -------------------------------------------- -% url = 'http://posttestserver.com/post.php'; -% params = {'testChars' char([2500 30000]) 'new code' '?'}; -% [paramString,header] = http_paramsToString(params,1); -% [output,extras] = urlread2(url,'POST',paramString,header); -% -% From behind a firewall, use the Preferences to set your proxy server. -% -% See Also: -% http_paramsToString -% unicode2native -% native2unicode -% -% Subfunctions: -% fixHeaderCasing - small subfunction to fix case errors encountered in real -% world, requires updating when casing doesn't match expected form, like -% if someone sent the header content-Encoding instead of -% Content-Encoding -% -% Based on original urlread code by Matthew J. Simoneau -% -% VERSION = 1.1 - -in.CAST_OUTPUT = true; -in.FOLLOW_REDIRECTS = true; -in.READ_TIMEOUT = 0; -in.ENCODING = ''; - -%Input handling -%--------------------------------------- -if ~isempty(varargin) - for i = 1:2:numel(varargin) - prop = upper(varargin{i}); - value = varargin{i+1}; - if isfield(in,prop) - in.(prop) = value; - else - error('Unrecognized input to function: %s',prop) - end - end -end - -if ~exist('method','var') || isempty(method), method = 'GET'; end -if ~exist('body','var'), body = ''; end -if ~exist('headersIn','var'), headersIn = []; end - -assert(usejava('jvm'),'Function requires Java') - -import com.mathworks.mlwidgets.io.InterruptibleStreamCopier; -com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings %Proxy settings need to be set - -%Create a urlConnection. -%----------------------------------- -urlConnection = getURLConnection(urlChar); -%For HTTP uses sun.net.www.protocol.http.HttpURLConnection -%Might use ice.net.HttpURLConnection but this has more overhead - -%SETTING PROPERTIES -%------------------------------------------------------- -urlConnection.setRequestMethod(upper(method)); -urlConnection.setFollowRedirects(in.FOLLOW_REDIRECTS); -urlConnection.setReadTimeout(in.READ_TIMEOUT); - -for iHeader = 1:length(headersIn) - curHeader = headersIn(iHeader); - urlConnection.setRequestProperty(curHeader.name,curHeader.value); -end - -if ~isempty(body) - %Ensure vector? - if size(body,1) > 1 - if size(body,2) > 1 - error('Input parameter to function: body, must be a vector') - else - body = body'; - end - end - - if ischar(body) - %NOTE: '' defaults to Matlab's default encoding scheme - body = unicode2native(body,in.ENCODING); - elseif ~(strcmp(class(body),'uint8') || strcmp(class(body),'int8')) - error('Function input: body, should be of class char, uint8, or int8, detected: %s',class(body)) - end - - urlConnection.setRequestProperty('Content-Length',int2str(length(body))); - urlConnection.setDoOutput(true); - outputStream = urlConnection.getOutputStream; - outputStream.write(body); - outputStream.close; -else - urlConnection.setRequestProperty('Content-Length','0'); -end - -%========================================================================== -% Read the data from the connection. -%========================================================================== -%This should be done first because it tells us if things are ok or not -%NOTE: If there is an error, functions below using urlConnection, notably -%getResponseCode, will fail as well -try - inputStream = urlConnection.getInputStream; - isGood = true; -catch ME - isGood = false; -%NOTE: HTTP error codes will throw an error here, we'll allow those for now -%We might also get another error in which case the inputStream will be -%undefined, those we will throw here - inputStream = urlConnection.getErrorStream; - - if isempty(inputStream) - msg = ME.message; - I = strfind(msg,char([13 10 9])); %see example by setting timeout to 1 - %Should remove the barf of the stack, at ... at ... at ... etc - %Likely that this could be improved ... (generate link with full msg) - if ~isempty(I) - msg = msg(1:I(1)-1); - end - fprintf(2,'Response stream is undefined\n below is a Java Error dump (truncated):\n'); - error(msg) - end -end - -%POPULATING HEADERS -%-------------------------------------------------------------------------- -allHeaders = struct; -allHeaders.Response = {char(urlConnection.getHeaderField(0))}; -done = false; -headerIndex = 0; - -while ~done - headerIndex = headerIndex + 1; - headerValue = char(urlConnection.getHeaderField(headerIndex)); - if ~isempty(headerValue) - headerName = char(urlConnection.getHeaderFieldKey(headerIndex)); - headerName = fixHeaderCasing(headerName); %NOT YET FINISHED - - %Important, for name safety all hyphens are replace with underscores - headerName(headerName == '-') = '_'; - if isfield(allHeaders,headerName) - allHeaders.(headerName) = [allHeaders.(headerName) headerValue]; - else - allHeaders.(headerName) = {headerValue}; - end - else - done = true; - end -end - -firstHeaders = struct; -fn = fieldnames(allHeaders); -for iHeader = 1:length(fn) - curField = fn{iHeader}; - firstHeaders.(curField) = allHeaders.(curField){1}; -end - -status = struct(... - 'value', urlConnection.getResponseCode(),... - 'msg', char(urlConnection.getResponseMessage)); - -%PROCESSING OF OUTPUT -%---------------------------------------------------------- -byteArrayOutputStream = java.io.ByteArrayOutputStream; -% This StreamCopier is unsupported and may change at any time. OH GREAT :/ -isc = InterruptibleStreamCopier.getInterruptibleStreamCopier; -isc.copyStream(inputStream,byteArrayOutputStream); -inputStream.close; -byteArrayOutputStream.close; - -if in.CAST_OUTPUT - charset = ''; - - %Extraction of character set from Content-Type header if possible - if isfield(firstHeaders,'Content_Type') - text = firstHeaders.Content_Type; - %Always open to regexp improvements - charset = regexp(text,'(?<=charset=)[^\s]*','match','once'); - end - - if ~isempty(charset) - output = native2unicode(typecast(byteArrayOutputStream.toByteArray','uint8'),charset); - else - output = char(typecast(byteArrayOutputStream.toByteArray','uint8')); - end -else - %uint8 is more useful for later charecter conversions - %uint8 or int8 is somewhat arbitary at this point - output = typecast(byteArrayOutputStream.toByteArray','uint8'); -end - -extras = struct; -extras.allHeaders = allHeaders; -extras.firstHeaders = firstHeaders; -extras.status = status; -%Gets eventual url even with redirection -extras.url = char(urlConnection.getURL); -extras.isGood = isGood; - - - -end - -function headerNameOut = fixHeaderCasing(headerName) -%fixHeaderCasing Forces standard casing of headers -% -% headerNameOut = fixHeaderCasing(headerName) -% -% This is important for field access in a structure which -% is case sensitive -% -% Not yet finished. -% I've been adding to this function as problems come along - - switch lower(headerName) - case 'location' - headerNameOut = 'Location'; - case 'content_type' - headerNameOut = 'Content_Type'; - otherwise - headerNameOut = headerName; - end -end - -%========================================================================== -%========================================================================== -%========================================================================== - -function urlConnection = getURLConnection(urlChar) -%getURLConnection -% -% urlConnection = getURLConnection(urlChar) - -% Determine the protocol (before the ":"). -protocol = urlChar(1:find(urlChar==':',1)-1); - - -% Try to use the native handler, not the ice.* classes. -try - switch protocol - case 'http' - %http://www.docjar.com/docs/api/sun/net/www/protocol/http/HttpURLConnection.html - handler = sun.net.www.protocol.http.Handler; - case 'https' - handler = sun.net.www.protocol.https.Handler; - end -catch ME - handler = []; -end - -% Create the URL object. -try - if isempty(handler) - url = java.net.URL(urlChar); - else - url = java.net.URL([],urlChar,handler); - end -catch ME - error('Failure to parse URL or protocol not supported for:\nURL: %s',urlChar); -end - -% Get the proxy information using MathWorks facilities for unified proxy -% preference settings. -mwtcp = com.mathworks.net.transport.MWTransportClientPropertiesFactory.create(); -proxy = mwtcp.getProxy(); - -% Open a connection to the URL. -if isempty(proxy) - urlConnection = url.openConnection; -else - urlConnection = url.openConnection(proxy); -end - - -end +function [output,extras] = urlread2(urlChar,method,body,headersIn,varargin) +%urlread2 Makes HTTP requests and processes response +% +% [output,extras] = urlread2(urlChar, *method, *body, *headersIn, varargin) +% +% * indicates optional inputs that must be entered in place +% +% UNDOCUMENTED MATLAB VERSION +% +% EXAMPLE CALLING FORMS +% ... = urlread2(urlChar) +% ... = urlread2(urlChar,'GET','',[],prop1,value1,prop2,value2,etc) +% ... = urlread2(urlChar,'POST',body,headers) +% +% FEATURES +% ======================================================================= +% 1) Allows specification of any HTTP method +% 2) Allows specification of any header. Very little is hard-coded +% in for header handling. +% 3) Returns response status and headers +% 4) Should handle unicode properly ... +% +% OUTPUTS +% ======================================================================= +% output : body of the response, either text or binary depending upon +% CAST_OUTPUT property +% extras : (structure) +% .allHeaders - stucture, fields have cellstr values, HTTP headers may +% may be repeated but will have a single field entry, with each +% repeat's value another being another entry in the cellstr, for +% example: +% .Set_Cookie = {'first_value' 'second_value'} +% .firstHeaders - (structure), variable fields, contains the first +% string entry for each field in allHeaders, this +% structure can be used to avoid dereferencing a cell +% for fields you expect not to be repeated ... +% EXAMPLE: +% .Response : 'HTTP/1.1 200 OK'} +% .Server : 'nginx' +% .Date : 'Tue, 29 Nov 2011 02:23:16 GMT' +% .Content_Type : 'text/html; charset=UTF-8' +% .Content_Length : '109155' +% .Connection : 'keep-alive' +% .Vary : 'Accept-Encoding, User-Agent' +% .Cache_Control : 'max-age=60, private' +% .Set_Cookie : 'first_value' +% .status - (structure) +% .value : numeric value of status, ex. 200 +% .msg : message that goes along with status, ex. 'OK' +% .url - eventual url that led to output, this can change from +% the input with redirects, see FOLLOW_REDIRECTS +% .isGood - (logical) I believe this is an indicator of the presence of 400 +% or 500 status codes (see status.value) but more +% testing is needed. In other words, true if status.value < 400. +% In code, set true if the response was obtainable without +% resorting to checking the error stream. +% +% INPUTS +% ======================================================================= +% urlChar : The full url, must include scheme (http, https) +% method : examples: 'GET' 'POST' etc +% body : (vector)(char, uint8 or int8) body to write, generally used +% with POST or PUT, use of uint8 or int8 ensures that the +% body input is not manipulated before sending, char is sent +% via unicode2native function with ENCODING input (see below) +% headersIn : (structure array), use empty [] or '' if no headers are needed +% but varargin property/value pairs are, multiple headers +% may be passed in as a structure array +% .name - (string), name of the header, a name property is used +% instead of a field because the name must match a valid +% header +% .value - (string), value to use +% +% OPTIONAL INPUTS (varargin, property/value pairs) +% ======================================================================= +% CAST_OUTPUT : (default true) output is uint8, useful if the body +% of the response is not text +% ENCODING : (default ''), ENCODING input to function unicode2native +% FOLLOW_REDIRECTS : (default true), if false 3xx status codes will +% be returned and need to be handled by the user, +% note this does not handle javascript or meta tag +% redirects, just server based ones +% READ_TIMEOUT : (default 0), 0 means no timeout, value is in +% milliseconds +% +% EXAMPLES +% ======================================================================= +% GET: +% -------------------------------------------- +% url = 'http://www.mathworks.com/matlabcentral/fileexchange/'; +% query = 'urlread2'; +% params = {'term' query}; +% queryString = http_paramsToString(params,1); +% url = [url '?' queryString]; +% [output,extras] = urlread2(url); +% +% POST: +% -------------------------------------------- +% url = 'http://posttestserver.com/post.php'; +% params = {'testChars' char([2500 30000]) 'new code' '?'}; +% [paramString,header] = http_paramsToString(params,1); +% [output,extras] = urlread2(url,'POST',paramString,header); +% +% From behind a firewall, use the Preferences to set your proxy server. +% +% See Also: +% http_paramsToString +% unicode2native +% native2unicode +% +% Subfunctions: +% fixHeaderCasing - small subfunction to fix case errors encountered in real +% world, requires updating when casing doesn't match expected form, like +% if someone sent the header content-Encoding instead of +% Content-Encoding +% +% Based on original urlread code by Matthew J. Simoneau +% +% VERSION = 1.1 + +in.CAST_OUTPUT = true; +in.FOLLOW_REDIRECTS = true; +in.READ_TIMEOUT = 0; +in.ENCODING = ''; + +%Input handling +%--------------------------------------- +if ~isempty(varargin) + for i = 1:2:numel(varargin) + prop = upper(varargin{i}); + value = varargin{i+1}; + if isfield(in,prop) + in.(prop) = value; + else + error('Unrecognized input to function: %s',prop) + end + end +end + +if ~exist('method','var') || isempty(method), method = 'GET'; end +if ~exist('body','var'), body = ''; end +if ~exist('headersIn','var'), headersIn = []; end + +assert(usejava('jvm'),'Function requires Java') + +import com.mathworks.mlwidgets.io.InterruptibleStreamCopier; +com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings %Proxy settings need to be set + +%Create a urlConnection. +%----------------------------------- +urlConnection = getURLConnection(urlChar); +%For HTTP uses sun.net.www.protocol.http.HttpURLConnection +%Might use ice.net.HttpURLConnection but this has more overhead + +%SETTING PROPERTIES +%------------------------------------------------------- +urlConnection.setRequestMethod(upper(method)); +urlConnection.setFollowRedirects(in.FOLLOW_REDIRECTS); +urlConnection.setReadTimeout(in.READ_TIMEOUT); + +for iHeader = 1:length(headersIn) + curHeader = headersIn(iHeader); + urlConnection.setRequestProperty(curHeader.name,curHeader.value); +end + +if ~isempty(body) + %Ensure vector? + if size(body,1) > 1 + if size(body,2) > 1 + error('Input parameter to function: body, must be a vector') + else + body = body'; + end + end + + if ischar(body) + %NOTE: '' defaults to Matlab's default encoding scheme + body = unicode2native(body,in.ENCODING); + elseif ~(strcmp(class(body),'uint8') || strcmp(class(body),'int8')) + error('Function input: body, should be of class char, uint8, or int8, detected: %s',class(body)) + end + + urlConnection.setRequestProperty('Content-Length',int2str(length(body))); + urlConnection.setDoOutput(true); + outputStream = urlConnection.getOutputStream; + outputStream.write(body); + outputStream.close; +else + urlConnection.setRequestProperty('Content-Length','0'); +end + +%========================================================================== +% Read the data from the connection. +%========================================================================== +%This should be done first because it tells us if things are ok or not +%NOTE: If there is an error, functions below using urlConnection, notably +%getResponseCode, will fail as well +try + inputStream = urlConnection.getInputStream; + isGood = true; +catch ME + isGood = false; +%NOTE: HTTP error codes will throw an error here, we'll allow those for now +%We might also get another error in which case the inputStream will be +%undefined, those we will throw here + inputStream = urlConnection.getErrorStream; + + if isempty(inputStream) + msg = ME.message; + I = strfind(msg,char([13 10 9])); %see example by setting timeout to 1 + %Should remove the barf of the stack, at ... at ... at ... etc + %Likely that this could be improved ... (generate link with full msg) + if ~isempty(I) + msg = msg(1:I(1)-1); + end + fprintf(2,'Response stream is undefined\n below is a Java Error dump (truncated):\n'); + error(msg) + end +end + +%POPULATING HEADERS +%-------------------------------------------------------------------------- +allHeaders = struct; +allHeaders.Response = {char(urlConnection.getHeaderField(0))}; +done = false; +headerIndex = 0; + +while ~done + headerIndex = headerIndex + 1; + headerValue = char(urlConnection.getHeaderField(headerIndex)); + if ~isempty(headerValue) + headerName = char(urlConnection.getHeaderFieldKey(headerIndex)); + headerName = fixHeaderCasing(headerName); %NOT YET FINISHED + + %Important, for name safety all hyphens are replace with underscores + headerName(headerName == '-') = '_'; + if isfield(allHeaders,headerName) + allHeaders.(headerName) = [allHeaders.(headerName) headerValue]; + else + allHeaders.(headerName) = {headerValue}; + end + else + done = true; + end +end + +firstHeaders = struct; +fn = fieldnames(allHeaders); +for iHeader = 1:length(fn) + curField = fn{iHeader}; + firstHeaders.(curField) = allHeaders.(curField){1}; +end + +status = struct(... + 'value', urlConnection.getResponseCode(),... + 'msg', char(urlConnection.getResponseMessage)); + +%PROCESSING OF OUTPUT +%---------------------------------------------------------- +byteArrayOutputStream = java.io.ByteArrayOutputStream; +% This StreamCopier is unsupported and may change at any time. OH GREAT :/ +isc = InterruptibleStreamCopier.getInterruptibleStreamCopier; +isc.copyStream(inputStream,byteArrayOutputStream); +inputStream.close; +byteArrayOutputStream.close; + +if in.CAST_OUTPUT + charset = ''; + + %Extraction of character set from Content-Type header if possible + if isfield(firstHeaders,'Content_Type') + text = firstHeaders.Content_Type; + %Always open to regexp improvements + charset = regexp(text,'(?<=charset=)[^\s]*','match','once'); + end + + if ~isempty(charset) + output = native2unicode(typecast(byteArrayOutputStream.toByteArray','uint8'),charset); + else + output = char(typecast(byteArrayOutputStream.toByteArray','uint8')); + end +else + %uint8 is more useful for later charecter conversions + %uint8 or int8 is somewhat arbitary at this point + output = typecast(byteArrayOutputStream.toByteArray','uint8'); +end + +extras = struct; +extras.allHeaders = allHeaders; +extras.firstHeaders = firstHeaders; +extras.status = status; +%Gets eventual url even with redirection +extras.url = char(urlConnection.getURL); +extras.isGood = isGood; + + + +end + +function headerNameOut = fixHeaderCasing(headerName) +%fixHeaderCasing Forces standard casing of headers +% +% headerNameOut = fixHeaderCasing(headerName) +% +% This is important for field access in a structure which +% is case sensitive +% +% Not yet finished. +% I've been adding to this function as problems come along + + switch lower(headerName) + case 'location' + headerNameOut = 'Location'; + case 'content_type' + headerNameOut = 'Content_Type'; + otherwise + headerNameOut = headerName; + end +end + +%========================================================================== +%========================================================================== +%========================================================================== + +function urlConnection = getURLConnection(urlChar) +%getURLConnection +% +% urlConnection = getURLConnection(urlChar) + +% Determine the protocol (before the ":"). +protocol = urlChar(1:find(urlChar==':',1)-1); + + +% Try to use the native handler, not the ice.* classes. +try + switch protocol + case 'http' + %http://www.docjar.com/docs/api/sun/net/www/protocol/http/HttpURLConnection.html + handler = sun.net.www.protocol.http.Handler; + case 'https' + handler = sun.net.www.protocol.https.Handler; + end +catch ME + handler = []; +end + +% Create the URL object. +try + if isempty(handler) + url = java.net.URL(urlChar); + else + url = java.net.URL([],urlChar,handler); + end +catch ME + error('Failure to parse URL or protocol not supported for:\nURL: %s',urlChar); +end + +% Get the proxy information using MathWorks facilities for unified proxy +% preference settings. +mwtcp = com.mathworks.net.transport.MWTransportClientPropertiesFactory.create(); +proxy = mwtcp.getProxy(); + +% Open a connection to the URL. +if isempty(proxy) + urlConnection = url.openConnection; +else + urlConnection = url.openConnection(proxy); +end + + +end diff --git a/plotly/plotly_aux/urlread2/urlread_notes.txt b/plotly/plotly_aux/urlread2/urlread_notes.txt index 7a2ba14f..8257f092 100755 --- a/plotly/plotly_aux/urlread2/urlread_notes.txt +++ b/plotly/plotly_aux/urlread2/urlread_notes.txt @@ -1,86 +1,86 @@ -========================================================================== - Unicode & Matlab -========================================================================== -native2unicode - works with uint8, fails with char - -Taking a unicode character and encoding as bytes: -unicode2native(char(1002),'UTF-8') -back to the character: -native2unicode(uint8([207 170]),'UTF-8') -this doesn't work: -native2unicode(char([207 170]),'UTF-8') -in documentation: If BYTES is a CHAR vector, it is returned unchanged. - -Java - only supports int8 -Matlab to Java -> uint8 or int8 to bytes -Java to Matlab -> bytes to int8 -char - 16 bit - -Maintenance of underlying bytes: -typecast(java.lang.String(uint8(250)).getBytes,'uint8') = 250 -see documentation: Handling Data Returned from a Java Method - -Command Window difficulty --------------------------------------------------------------------- -The typical font in the Matlab command window will often fail to render -unicode properly. I often can see unicode better in the variable editor -although this may be fixed if you change your font preferences ... -Copying unicode from the command window often results in the -generations of the value 26 (aka substitute) - -More documentation on input/output to urlread2 to follow eventually ... - -small notes to self: -for output -native2unicode(uint8(output),encoding) - -========================================================================== - HTTP Headers -========================================================================== -Handling of repeated http readers is a bit of a tricky situation. Most -headers are not repeated although sometimes http clients will assume this -for too many headers which can result in a problem if you want to see -duplicated headers. I've passed the problem onto the user who can decide -to handle it how they wish instead of providing the right solution, which -after some brief searching, I am not sure exists. - -========================================================================== - PROBLEMS -========================================================================== -1) Page requires following a redirect: -%------------------------------------------- -ref: http://www.mathworks.com/matlabcentral/newsreader/view_thread/302571 -fix: FOLLOW_REDIRECTS is enabled by default, you're fine. - -2) Basic authentication required: -%------------------------------------------ -Create and pass in the following header: -user = 'test'; -password = 'test'; -encoder = sun.misc.BASE64Encoder(); -str = java.lang.String([user ':' password]) %NOTE: format may be -%different for your server -header = http_createHeader('Authorization',char(encoder.encode(str.getBytes()))) -NOTE: Ideally you would make this a function - -3) The text returned doesn't make sense. -%----------------------------------------- -The text may not be encoded correctly. Requires native2unicode function. -See Unicode & Matlab section above. - -4) I get a different result in my web browser than I do in Matlab -%----------------------------------------- -This is generally seen for two reasons. -1 - The easiest and silly reason is user agent filtering. -When you make a request you identify yourself -as being a particular "broswer" or "user agent". Setting a header -with the user agent of the browser may fix the problem. -See: http://en.wikipedia.org/wiki/User_agent -See: http://whatsmyuseragent.com -value = '' -header = http_createHeader('User-Agent',value); -2 - You are not processing cookies and the server is not sending -you information because you haven't sent it cookies (everyone likes em!) -I've implemented cookie support but it requires some extra files that -I need to clean up. Feel free to email me if you'd really like to have them. - +========================================================================== + Unicode & Matlab +========================================================================== +native2unicode - works with uint8, fails with char + +Taking a unicode character and encoding as bytes: +unicode2native(char(1002),'UTF-8') +back to the character: +native2unicode(uint8([207 170]),'UTF-8') +this doesn't work: +native2unicode(char([207 170]),'UTF-8') +in documentation: If BYTES is a CHAR vector, it is returned unchanged. + +Java - only supports int8 +Matlab to Java -> uint8 or int8 to bytes +Java to Matlab -> bytes to int8 +char - 16 bit + +Maintenance of underlying bytes: +typecast(java.lang.String(uint8(250)).getBytes,'uint8') = 250 +see documentation: Handling Data Returned from a Java Method + +Command Window difficulty +-------------------------------------------------------------------- +The typical font in the Matlab command window will often fail to render +unicode properly. I often can see unicode better in the variable editor +although this may be fixed if you change your font preferences ... +Copying unicode from the command window often results in the +generations of the value 26 (aka substitute) + +More documentation on input/output to urlread2 to follow eventually ... + +small notes to self: +for output +native2unicode(uint8(output),encoding) + +========================================================================== + HTTP Headers +========================================================================== +Handling of repeated http readers is a bit of a tricky situation. Most +headers are not repeated although sometimes http clients will assume this +for too many headers which can result in a problem if you want to see +duplicated headers. I've passed the problem onto the user who can decide +to handle it how they wish instead of providing the right solution, which +after some brief searching, I am not sure exists. + +========================================================================== + PROBLEMS +========================================================================== +1) Page requires following a redirect: +%------------------------------------------- +ref: http://www.mathworks.com/matlabcentral/newsreader/view_thread/302571 +fix: FOLLOW_REDIRECTS is enabled by default, you're fine. + +2) Basic authentication required: +%------------------------------------------ +Create and pass in the following header: +user = 'test'; +password = 'test'; +encoder = sun.misc.BASE64Encoder(); +str = java.lang.String([user ':' password]) %NOTE: format may be +%different for your server +header = http_createHeader('Authorization',char(encoder.encode(str.getBytes()))) +NOTE: Ideally you would make this a function + +3) The text returned doesn't make sense. +%----------------------------------------- +The text may not be encoded correctly. Requires native2unicode function. +See Unicode & Matlab section above. + +4) I get a different result in my web browser than I do in Matlab +%----------------------------------------- +This is generally seen for two reasons. +1 - The easiest and silly reason is user agent filtering. +When you make a request you identify yourself +as being a particular "broswer" or "user agent". Setting a header +with the user agent of the browser may fix the problem. +See: http://en.wikipedia.org/wiki/User_agent +See: http://whatsmyuseragent.com +value = '' +header = http_createHeader('User-Agent',value); +2 - You are not processing cookies and the server is not sending +you information because you haven't sent it cookies (everyone likes em!) +I've implemented cookie support but it requires some extra files that +I need to clean up. Feel free to email me if you'd really like to have them. + diff --git a/plotly/plotly_aux/urlread2/urlread_todos.txt b/plotly/plotly_aux/urlread2/urlread_todos.txt index 86dd62d0..0434bcea 100755 --- a/plotly/plotly_aux/urlread2/urlread_todos.txt +++ b/plotly/plotly_aux/urlread2/urlread_todos.txt @@ -1,13 +1,13 @@ -========================================================================== - IMPROVEMENTS -========================================================================== -1) The function could be improved to support file streaming both in sending -and in receiving (saving) to reduce memory usage but this is very low priority - -2) Implement better casing handling - -3) Choose a better function name than urlread2 -> sorry Chris :) - -4) Support multipart/form-data, this ideally would be handled by a helper function - +========================================================================== + IMPROVEMENTS +========================================================================== +1) The function could be improved to support file streaming both in sending +and in receiving (saving) to reduce memory usage but this is very low priority + +2) Implement better casing handling + +3) Choose a better function name than urlread2 -> sorry Chris :) + +4) Support multipart/form-data, this ideally would be handled by a helper function + 5) Allow for throwing an error if the HTTP status code is an error (400) and 500 as well? \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/urlread_versionInfo.txt b/plotly/plotly_aux/urlread2/urlread_versionInfo.txt index 6feb2133..a8448f49 100755 --- a/plotly/plotly_aux/urlread2/urlread_versionInfo.txt +++ b/plotly/plotly_aux/urlread2/urlread_versionInfo.txt @@ -1,13 +1,13 @@ -===================== -Version 1.1 -3/25/2012 - -Summary: Bug fixes related to Matlab throwing errors when it shouldn't have been. Thanks to Shane Lin for pointing out the problems. - -Bug Fix: Modified code so that http status errors wouldn't throw errors in the code, but rather would be passed on to the user to process - -Bug Fix: Provided GET example code apparently doesn't work for all users, changed to a different example. - -===================== -Version 1 +===================== +Version 1.1 +3/25/2012 + +Summary: Bug fixes related to Matlab throwing errors when it shouldn't have been. Thanks to Shane Lin for pointing out the problems. + +Bug Fix: Modified code so that http status errors wouldn't throw errors in the code, but rather would be passed on to the user to process + +Bug Fix: Provided GET example code apparently doesn't work for all users, changed to a different example. + +===================== +Version 1 3/17/2012 \ No newline at end of file diff --git a/plotly/plotlyfig.m b/plotly/plotlyfig.m index 9b740525..19a6fc74 100644 --- a/plotly/plotlyfig.m +++ b/plotly/plotlyfig.m @@ -838,7 +838,7 @@ function delete(obj) fnmod = fn; try - for d = 1:length(fn); + for d = 1:length(fn) % clean up axis keys if any(strfind(fn{d},'xaxis')) || any(strfind(fn{d},'yaxis')) diff --git a/plotly/plotlyfig_aux/core/updateAxis.m b/plotly/plotlyfig_aux/core/updateAxis.m index b6e04d24..cee95c0c 100644 --- a/plotly/plotlyfig_aux/core/updateAxis.m +++ b/plotly/plotlyfig_aux/core/updateAxis.m @@ -253,12 +253,42 @@ %-xaxis range-% xaxis.range = log10(axis_data.XLim); + %-xaxis autotick-% + xaxis.autotick = true; + %-xaxis nticks-% + xaxis.nticks = length(axis_data.XTick) + 1; elseif strcmp(xaxis.type,'linear') if strcmp(axis_data.XTickLabelMode,'auto') %-xaxis range-% - xaxis.range = axis_data.XLim; + if isnumeric(axis_data.XLim) + xaxis.range = axis_data.XLim; + + elseif isduration(axis_data.XLim) + [temp,type] = convertDuration(axis_data.XLim); + + if (~isduration(temp)) + xaxis.range = temp; + xaxis.type = 'duration'; + xaxis.title = type; + else + xaxis.autorange = true; + xaxis.type = 'duration - specified format'; + end + + elseif isdatetime(axis_data.XLim) + xaxis.range = convertDate(axis_data.XLim); + xaxis.type = 'date'; + else + % data is a category type + end + + %-xaxis autotick-% + xaxis.autotick = true; + %-xaxis numticks-% + xaxis.nticks = length(axis_data.XTick)+1; + else %-xaxis show tick labels-% if isempty(axis_data.XTickLabel) @@ -267,45 +297,29 @@ %-xaxis autorange-% xaxis.autorange = true; else - try datevec(axis_data.XTickLabel(1,:),axis_data.UserData.plotly.xdateformat); - %-xaxis type date-% - xaxis.type = 'date'; + try + %find numbers in labels + labelnums = find(~isnan(xlabels)); + %-yaxis type linear-% + xaxis.type = 'linear'; %-range (overwrite)-% - xaxis.range = [convertDate(datenum(axis_data.XTickLabel(1,:),axis_data.UserData.plotly.xdateformat)), ... - convertDate(datenum(axis_data.XTickLabel(end,:),axis_data.UserData.plotly.xdateformat))]; + delta = (xlabels(labelnums(2)) - xlabels(labelnums(1)))/(labelnums(2)-labelnums(1)); + xaxis.range = [xlabels(labelnums(1))-delta*(labelnums(1)-1) xlabels(labelnums(1)) + (length(xlabels)-labelnums(1))*delta]; + %-yaxis autotick-% + xaxis.autotick = true; + %-yaxis numticks-% + xaxis.nticks = length(axis_data.XTick) + 1; catch - %x-axis labels - xlabels = str2double(axis_data.XTickLabel); - try - %find numbers in labels - labelnums = find(~isnan(xlabels)); - %-yaxis type linear-% - xaxis.type = 'linear'; - %-range (overwrite)-% - delta = (xlabels(labelnums(2)) - xlabels(labelnums(1)))/(labelnums(2)-labelnums(1)); - xaxis.range = [xlabels(labelnums(1))-delta*(labelnums(1)-1) xlabels(labelnums(1)) + (length(xlabels)-labelnums(1))*delta]; - %-yaxis autotick-% - xaxis.autotick = true; - %-yaxis numticks-% - xaxis.nticks = length(axis_data.XTick) + 1; - catch - %-yaxis type category-% - xaxis.type = 'category'; - %-range (overwrite)-% - xaxis.autorange = true; - %-yaxis autotick-% - xaxis.autotick = true; - end + %-yaxis type category-% + xaxis.type = 'category'; + %-range (overwrite)-% + xaxis.autorange = true; + %-yaxis autotick-% + xaxis.autotick = true; end end end end - - %-xaxis autotick-% - xaxis.autotick = true; - %-xaxis numticks-% - xaxis.nticks = length(axis_data.XTick) + 1; - end %-------------------------------------------------------------------------% @@ -387,11 +401,6 @@ %-------------------------------------------------------------------------% -%-yaxis range-% -yaxis.range = axis_data.YLim; - -%-------------------------------------------------------------------------% - %-yaxis show tick labels-% yaxis.showticklabels = true; @@ -450,12 +459,34 @@ %-xaxis nticks-% yaxis.nticks = length(axis_data.YTick) + 1; - elseif strcmp(yaxis.type,'linear') - - %-xaxis range-% - yaxis.range = axis_data.YLim; + elseif strcmp(yaxis.type,'linear') if strcmp(axis_data.YTickLabelMode,'auto') + + %-xaxis range-% + if isnumeric(axis_data.YLim) + yaxis.range = axis_data.YLim; + + elseif isduration(axis_data.YLim) + + [temp,type] = convertDuration(axis_data.YLim); + + if (~isduration(temp)) + yaxis.range = temp; + yaxis.type = 'duration'; + yaxis.title = type; + else + yaxis.autorange = true; + yaxis.type = 'duration - specified format'; + end + + elseif isdatetime(axis_data.YLim) + yaxis.range = convertDate(axis_data.YLim); + yaxis.type = 'date'; + else + % data is a category type + end + %-yaxis autotick-% yaxis.autotick = true; %-yaxis numticks-% diff --git a/plotly/plotlyfig_aux/core/updateData.m b/plotly/plotlyfig_aux/core/updateData.m index ce812fb2..d40878db 100644 --- a/plotly/plotlyfig_aux/core/updateData.m +++ b/plotly/plotlyfig_aux/core/updateData.m @@ -99,6 +99,16 @@ obj.data{dataIndex}.x = convertDate(obj.data{dataIndex}.x); end +% check for xaxis duration +if strcmpi(xaxis.type, 'duration') + obj.data{dataIndex}.x = convertDuration(obj.data{dataIndex}.x); +end + +% check for xaxis duration with input format +if strcmpi(xaxis.type, 'duration - specified format') + obj.data{dataIndex}.x = get(obj.State.Plot(dataIndex).AssociatedAxis,'XTickLabel'); +end + % check for xaxis categories if strcmpi(xaxis.type, 'category') && ... ~strcmp(obj.data{dataIndex}.type,'box') @@ -110,6 +120,16 @@ obj.data{dataIndex}.y = convertDate(obj.data{dataIndex}.y); end +% check for yaxis duration +if strcmpi(yaxis.type, 'duration') + obj.data{dataIndex}.y = convertDuration(obj.data{dataIndex}.y); +end + +% check for yaxis duration with input format +if strcmpi(yaxis.type, 'duration - specified format') + obj.data{dataIndex}.y = get(obj.State.Plot(dataIndex).AssociatedAxis,'YTickLabel'); +end + % check for yaxis categories if strcmpi(yaxis.type, 'category') && ... ~strcmp(obj.data{dataIndex}.type,'box') diff --git a/plotly/plotlyfig_aux/helpers/convert Duration.m b/plotly/plotlyfig_aux/helpers/convert Duration.m new file mode 100644 index 00000000..bc390f23 --- /dev/null +++ b/plotly/plotlyfig_aux/helpers/convert Duration.m @@ -0,0 +1,26 @@ +function [converted,type] = convertDuration(duration) +if (strcmpi(duration.Format,'s')) + converted = seconds(duration); + type = 'sec'; + +elseif (strcmpi(duration.Format,'m')) + converted = minutes(duration); + type = 'min'; + +elseif (strcmpi(duration.Format,'h')) + converted = hours(duration); + type = 'hr'; + +elseif (strcmpi(duration.Format,'d')) + converted = days(duration); + type = 'days'; + +elseif (strcmpi(duration.Format,'y')) + converted = years(duration); + type = 'yrs'; +else + %no convertion is applied + converted = duration; + type = ''; +end +end \ No newline at end of file diff --git a/plotly/plotlyfig_aux/helpers/convertDate.m b/plotly/plotlyfig_aux/helpers/convertDate.m index 15b66980..889230b2 100644 --- a/plotly/plotlyfig_aux/helpers/convertDate.m +++ b/plotly/plotlyfig_aux/helpers/convertDate.m @@ -1,3 +1,4 @@ -function converted = convertDate(date) - converted = (date - datenum(1969,12,31,19,00,00))*1000*60*60*24; -end \ No newline at end of file +function convertedDate = convertDate(date) + date.Format = 'yyyy-MM-dd HH:mm:ss'; + convertedDate = char(date); +end \ No newline at end of file From bac9bfa9d4e8ba6b69498eaa31cbe86d3ef3c6c6 Mon Sep 17 00:00:00 2001 From: Abderahmane BENALI <46283596+benaliabderrahmane@users.noreply.github.com> Date: Mon, 2 Aug 2021 21:41:35 +0100 Subject: [PATCH 2/5] convert Duration name changed --- .../plotlyfig_aux/helpers/convertDuration.m | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 plotly/plotlyfig_aux/helpers/convertDuration.m diff --git a/plotly/plotlyfig_aux/helpers/convertDuration.m b/plotly/plotlyfig_aux/helpers/convertDuration.m new file mode 100644 index 00000000..bc390f23 --- /dev/null +++ b/plotly/plotlyfig_aux/helpers/convertDuration.m @@ -0,0 +1,26 @@ +function [converted,type] = convertDuration(duration) +if (strcmpi(duration.Format,'s')) + converted = seconds(duration); + type = 'sec'; + +elseif (strcmpi(duration.Format,'m')) + converted = minutes(duration); + type = 'min'; + +elseif (strcmpi(duration.Format,'h')) + converted = hours(duration); + type = 'hr'; + +elseif (strcmpi(duration.Format,'d')) + converted = days(duration); + type = 'days'; + +elseif (strcmpi(duration.Format,'y')) + converted = years(duration); + type = 'yrs'; +else + %no convertion is applied + converted = duration; + type = ''; +end +end \ No newline at end of file From 803a54a00f39705bb8eabdfa057413169f1ea5f4 Mon Sep 17 00:00:00 2001 From: Abderahmane BENALI <46283596+benaliabderrahmane@users.noreply.github.com> Date: Mon, 2 Aug 2021 21:47:24 +0100 Subject: [PATCH 3/5] delete uncesseray file --- .../plotlyfig_aux/helpers/convert Duration.m | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 plotly/plotlyfig_aux/helpers/convert Duration.m diff --git a/plotly/plotlyfig_aux/helpers/convert Duration.m b/plotly/plotlyfig_aux/helpers/convert Duration.m deleted file mode 100644 index bc390f23..00000000 --- a/plotly/plotlyfig_aux/helpers/convert Duration.m +++ /dev/null @@ -1,26 +0,0 @@ -function [converted,type] = convertDuration(duration) -if (strcmpi(duration.Format,'s')) - converted = seconds(duration); - type = 'sec'; - -elseif (strcmpi(duration.Format,'m')) - converted = minutes(duration); - type = 'min'; - -elseif (strcmpi(duration.Format,'h')) - converted = hours(duration); - type = 'hr'; - -elseif (strcmpi(duration.Format,'d')) - converted = days(duration); - type = 'days'; - -elseif (strcmpi(duration.Format,'y')) - converted = years(duration); - type = 'yrs'; -else - %no convertion is applied - converted = duration; - type = ''; -end -end \ No newline at end of file From cc6740d66fc7869263a82c248c2cbd6bbced6bad Mon Sep 17 00:00:00 2001 From: Abderahmane BENALI <46283596+benaliabderrahmane@users.noreply.github.com> Date: Tue, 3 Aug 2021 15:23:49 +0100 Subject: [PATCH 4/5] Add files via upload delete spacing changes --- plotly/plotly_aux/getuserdir.m | 24 +- .../plotly_aux/urlread2/http_createHeader.m | 20 +- .../plotly_aux/urlread2/http_paramsToString.m | 122 +-- plotly/plotly_aux/urlread2/urlread2.m | 742 +++++++++--------- plotly/plotly_aux/urlread2/urlread_notes.txt | 172 ++-- plotly/plotly_aux/urlread2/urlread_todos.txt | 24 +- .../urlread2/urlread_versionInfo.txt | 24 +- 7 files changed, 564 insertions(+), 564 deletions(-) diff --git a/plotly/plotly_aux/getuserdir.m b/plotly/plotly_aux/getuserdir.m index 9ce384b8..844f0ab3 100644 --- a/plotly/plotly_aux/getuserdir.m +++ b/plotly/plotly_aux/getuserdir.m @@ -1,13 +1,13 @@ -function userDir = getuserdir -% GETUSERDIR Retrieve the user directory -% - Under Windows returns the %APPDATA% directory -% - For other OSs uses java to retrieve the user.home directory - -if ispc - % userDir = winqueryreg('HKEY_CURRENT_USER',... - % ['Software\Microsoft\Windows\CurrentVersion\' ... - % 'Explorer\Shell Folders'],'Personal'); - userDir = getenv('appdata'); -else - userDir = char(java.lang.System.getProperty('user.home')); +function userDir = getuserdir +% GETUSERDIR Retrieve the user directory +% - Under Windows returns the %APPDATA% directory +% - For other OSs uses java to retrieve the user.home directory + +if ispc + % userDir = winqueryreg('HKEY_CURRENT_USER',... + % ['Software\Microsoft\Windows\CurrentVersion\' ... + % 'Explorer\Shell Folders'],'Personal'); + userDir = getenv('appdata'); +else + userDir = char(java.lang.System.getProperty('user.home')); end \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/http_createHeader.m b/plotly/plotly_aux/urlread2/http_createHeader.m index 0e80241f..457be94f 100755 --- a/plotly/plotly_aux/urlread2/http_createHeader.m +++ b/plotly/plotly_aux/urlread2/http_createHeader.m @@ -1,11 +1,11 @@ -function header = http_createHeader(name,value) -%http_createHeader Simple function for creating input header to urlread2 -% -% header = http_createHeader(name,value) -% -% CODE: header = struct('name',name,'value',value); -% -% See Also: -% urlread2 - +function header = http_createHeader(name,value) +%http_createHeader Simple function for creating input header to urlread2 +% +% header = http_createHeader(name,value) +% +% CODE: header = struct('name',name,'value',value); +% +% See Also: +% urlread2 + header = struct('name',name,'value',value); \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/http_paramsToString.m b/plotly/plotly_aux/urlread2/http_paramsToString.m index 376a0fa1..f9bc490c 100755 --- a/plotly/plotly_aux/urlread2/http_paramsToString.m +++ b/plotly/plotly_aux/urlread2/http_paramsToString.m @@ -1,62 +1,62 @@ -function [str,header] = http_paramsToString(params,encodeOption) -%http_paramsToString Creates string for a POST or GET requests -% -% [queryString,header] = http_paramsToString(params, *encodeOption) -% -% INPUTS -% ======================================================================= -% params: cell array of property/value pairs -% NOTE: If the input is in a 2 column matrix, then first column -% entries are properties and the second column entries are -% values, however this is NOT necessary (generally linear) -% encodeOption: (default 1) -% 1 - the typical URL encoding scheme (Java call) -% -% OUTPUTS -% ======================================================================= -% queryString: querystring to add onto URL (LACKS "?", see example) -% header : the header that should be attached for post requests when -% using urlread2 -% -% EXAMPLE: -% ============================================================== -% params = {'cmd' 'search' 'db' 'pubmed' 'term' 'wtf batman'}; -% queryString = http_paramsToString(params); -% queryString => cmd=search&db=pubmed&term=wtf+batman -% -% IMPORTANT: This function does not filter parameters, sort them, -% or remove empty inputs (if necessary), this must be done before hand - -if ~exist('encodeOption','var') - encodeOption = 1; -end - -if size(params,2) == 2 && size(params,1) > 1 - params = params'; - params = params(:); -end - -str = ''; -for i=1:2:length(params) - if (i == 1), separator = ''; else separator = '&'; end - switch encodeOption - case 1 - param = urlencode(params{i}); - value = urlencode(params{i+1}); -% case 2 -% param = oauth.percentEncodeString(params{i}); -% value = oauth.percentEncodeString(params{i+1}); -% header = http_getContentTypeHeader(1); - otherwise - error('Case not used') - end - str = [str separator param '=' value]; %#ok -end - -switch encodeOption - case 1 - header = http_createHeader('Content-Type','application/x-www-form-urlencoded'); -end - - +function [str,header] = http_paramsToString(params,encodeOption) +%http_paramsToString Creates string for a POST or GET requests +% +% [queryString,header] = http_paramsToString(params, *encodeOption) +% +% INPUTS +% ======================================================================= +% params: cell array of property/value pairs +% NOTE: If the input is in a 2 column matrix, then first column +% entries are properties and the second column entries are +% values, however this is NOT necessary (generally linear) +% encodeOption: (default 1) +% 1 - the typical URL encoding scheme (Java call) +% +% OUTPUTS +% ======================================================================= +% queryString: querystring to add onto URL (LACKS "?", see example) +% header : the header that should be attached for post requests when +% using urlread2 +% +% EXAMPLE: +% ============================================================== +% params = {'cmd' 'search' 'db' 'pubmed' 'term' 'wtf batman'}; +% queryString = http_paramsToString(params); +% queryString => cmd=search&db=pubmed&term=wtf+batman +% +% IMPORTANT: This function does not filter parameters, sort them, +% or remove empty inputs (if necessary), this must be done before hand + +if ~exist('encodeOption','var') + encodeOption = 1; +end + +if size(params,2) == 2 && size(params,1) > 1 + params = params'; + params = params(:); +end + +str = ''; +for i=1:2:length(params) + if (i == 1), separator = ''; else separator = '&'; end + switch encodeOption + case 1 + param = urlencode(params{i}); + value = urlencode(params{i+1}); +% case 2 +% param = oauth.percentEncodeString(params{i}); +% value = oauth.percentEncodeString(params{i+1}); +% header = http_getContentTypeHeader(1); + otherwise + error('Case not used') + end + str = [str separator param '=' value]; %#ok +end + +switch encodeOption + case 1 + header = http_createHeader('Content-Type','application/x-www-form-urlencoded'); +end + + end \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/urlread2.m b/plotly/plotly_aux/urlread2/urlread2.m index b552861c..53ba8ca6 100755 --- a/plotly/plotly_aux/urlread2/urlread2.m +++ b/plotly/plotly_aux/urlread2/urlread2.m @@ -1,371 +1,371 @@ -function [output,extras] = urlread2(urlChar,method,body,headersIn,varargin) -%urlread2 Makes HTTP requests and processes response -% -% [output,extras] = urlread2(urlChar, *method, *body, *headersIn, varargin) -% -% * indicates optional inputs that must be entered in place -% -% UNDOCUMENTED MATLAB VERSION -% -% EXAMPLE CALLING FORMS -% ... = urlread2(urlChar) -% ... = urlread2(urlChar,'GET','',[],prop1,value1,prop2,value2,etc) -% ... = urlread2(urlChar,'POST',body,headers) -% -% FEATURES -% ======================================================================= -% 1) Allows specification of any HTTP method -% 2) Allows specification of any header. Very little is hard-coded -% in for header handling. -% 3) Returns response status and headers -% 4) Should handle unicode properly ... -% -% OUTPUTS -% ======================================================================= -% output : body of the response, either text or binary depending upon -% CAST_OUTPUT property -% extras : (structure) -% .allHeaders - stucture, fields have cellstr values, HTTP headers may -% may be repeated but will have a single field entry, with each -% repeat's value another being another entry in the cellstr, for -% example: -% .Set_Cookie = {'first_value' 'second_value'} -% .firstHeaders - (structure), variable fields, contains the first -% string entry for each field in allHeaders, this -% structure can be used to avoid dereferencing a cell -% for fields you expect not to be repeated ... -% EXAMPLE: -% .Response : 'HTTP/1.1 200 OK'} -% .Server : 'nginx' -% .Date : 'Tue, 29 Nov 2011 02:23:16 GMT' -% .Content_Type : 'text/html; charset=UTF-8' -% .Content_Length : '109155' -% .Connection : 'keep-alive' -% .Vary : 'Accept-Encoding, User-Agent' -% .Cache_Control : 'max-age=60, private' -% .Set_Cookie : 'first_value' -% .status - (structure) -% .value : numeric value of status, ex. 200 -% .msg : message that goes along with status, ex. 'OK' -% .url - eventual url that led to output, this can change from -% the input with redirects, see FOLLOW_REDIRECTS -% .isGood - (logical) I believe this is an indicator of the presence of 400 -% or 500 status codes (see status.value) but more -% testing is needed. In other words, true if status.value < 400. -% In code, set true if the response was obtainable without -% resorting to checking the error stream. -% -% INPUTS -% ======================================================================= -% urlChar : The full url, must include scheme (http, https) -% method : examples: 'GET' 'POST' etc -% body : (vector)(char, uint8 or int8) body to write, generally used -% with POST or PUT, use of uint8 or int8 ensures that the -% body input is not manipulated before sending, char is sent -% via unicode2native function with ENCODING input (see below) -% headersIn : (structure array), use empty [] or '' if no headers are needed -% but varargin property/value pairs are, multiple headers -% may be passed in as a structure array -% .name - (string), name of the header, a name property is used -% instead of a field because the name must match a valid -% header -% .value - (string), value to use -% -% OPTIONAL INPUTS (varargin, property/value pairs) -% ======================================================================= -% CAST_OUTPUT : (default true) output is uint8, useful if the body -% of the response is not text -% ENCODING : (default ''), ENCODING input to function unicode2native -% FOLLOW_REDIRECTS : (default true), if false 3xx status codes will -% be returned and need to be handled by the user, -% note this does not handle javascript or meta tag -% redirects, just server based ones -% READ_TIMEOUT : (default 0), 0 means no timeout, value is in -% milliseconds -% -% EXAMPLES -% ======================================================================= -% GET: -% -------------------------------------------- -% url = 'http://www.mathworks.com/matlabcentral/fileexchange/'; -% query = 'urlread2'; -% params = {'term' query}; -% queryString = http_paramsToString(params,1); -% url = [url '?' queryString]; -% [output,extras] = urlread2(url); -% -% POST: -% -------------------------------------------- -% url = 'http://posttestserver.com/post.php'; -% params = {'testChars' char([2500 30000]) 'new code' '?'}; -% [paramString,header] = http_paramsToString(params,1); -% [output,extras] = urlread2(url,'POST',paramString,header); -% -% From behind a firewall, use the Preferences to set your proxy server. -% -% See Also: -% http_paramsToString -% unicode2native -% native2unicode -% -% Subfunctions: -% fixHeaderCasing - small subfunction to fix case errors encountered in real -% world, requires updating when casing doesn't match expected form, like -% if someone sent the header content-Encoding instead of -% Content-Encoding -% -% Based on original urlread code by Matthew J. Simoneau -% -% VERSION = 1.1 - -in.CAST_OUTPUT = true; -in.FOLLOW_REDIRECTS = true; -in.READ_TIMEOUT = 0; -in.ENCODING = ''; - -%Input handling -%--------------------------------------- -if ~isempty(varargin) - for i = 1:2:numel(varargin) - prop = upper(varargin{i}); - value = varargin{i+1}; - if isfield(in,prop) - in.(prop) = value; - else - error('Unrecognized input to function: %s',prop) - end - end -end - -if ~exist('method','var') || isempty(method), method = 'GET'; end -if ~exist('body','var'), body = ''; end -if ~exist('headersIn','var'), headersIn = []; end - -assert(usejava('jvm'),'Function requires Java') - -import com.mathworks.mlwidgets.io.InterruptibleStreamCopier; -com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings %Proxy settings need to be set - -%Create a urlConnection. -%----------------------------------- -urlConnection = getURLConnection(urlChar); -%For HTTP uses sun.net.www.protocol.http.HttpURLConnection -%Might use ice.net.HttpURLConnection but this has more overhead - -%SETTING PROPERTIES -%------------------------------------------------------- -urlConnection.setRequestMethod(upper(method)); -urlConnection.setFollowRedirects(in.FOLLOW_REDIRECTS); -urlConnection.setReadTimeout(in.READ_TIMEOUT); - -for iHeader = 1:length(headersIn) - curHeader = headersIn(iHeader); - urlConnection.setRequestProperty(curHeader.name,curHeader.value); -end - -if ~isempty(body) - %Ensure vector? - if size(body,1) > 1 - if size(body,2) > 1 - error('Input parameter to function: body, must be a vector') - else - body = body'; - end - end - - if ischar(body) - %NOTE: '' defaults to Matlab's default encoding scheme - body = unicode2native(body,in.ENCODING); - elseif ~(strcmp(class(body),'uint8') || strcmp(class(body),'int8')) - error('Function input: body, should be of class char, uint8, or int8, detected: %s',class(body)) - end - - urlConnection.setRequestProperty('Content-Length',int2str(length(body))); - urlConnection.setDoOutput(true); - outputStream = urlConnection.getOutputStream; - outputStream.write(body); - outputStream.close; -else - urlConnection.setRequestProperty('Content-Length','0'); -end - -%========================================================================== -% Read the data from the connection. -%========================================================================== -%This should be done first because it tells us if things are ok or not -%NOTE: If there is an error, functions below using urlConnection, notably -%getResponseCode, will fail as well -try - inputStream = urlConnection.getInputStream; - isGood = true; -catch ME - isGood = false; -%NOTE: HTTP error codes will throw an error here, we'll allow those for now -%We might also get another error in which case the inputStream will be -%undefined, those we will throw here - inputStream = urlConnection.getErrorStream; - - if isempty(inputStream) - msg = ME.message; - I = strfind(msg,char([13 10 9])); %see example by setting timeout to 1 - %Should remove the barf of the stack, at ... at ... at ... etc - %Likely that this could be improved ... (generate link with full msg) - if ~isempty(I) - msg = msg(1:I(1)-1); - end - fprintf(2,'Response stream is undefined\n below is a Java Error dump (truncated):\n'); - error(msg) - end -end - -%POPULATING HEADERS -%-------------------------------------------------------------------------- -allHeaders = struct; -allHeaders.Response = {char(urlConnection.getHeaderField(0))}; -done = false; -headerIndex = 0; - -while ~done - headerIndex = headerIndex + 1; - headerValue = char(urlConnection.getHeaderField(headerIndex)); - if ~isempty(headerValue) - headerName = char(urlConnection.getHeaderFieldKey(headerIndex)); - headerName = fixHeaderCasing(headerName); %NOT YET FINISHED - - %Important, for name safety all hyphens are replace with underscores - headerName(headerName == '-') = '_'; - if isfield(allHeaders,headerName) - allHeaders.(headerName) = [allHeaders.(headerName) headerValue]; - else - allHeaders.(headerName) = {headerValue}; - end - else - done = true; - end -end - -firstHeaders = struct; -fn = fieldnames(allHeaders); -for iHeader = 1:length(fn) - curField = fn{iHeader}; - firstHeaders.(curField) = allHeaders.(curField){1}; -end - -status = struct(... - 'value', urlConnection.getResponseCode(),... - 'msg', char(urlConnection.getResponseMessage)); - -%PROCESSING OF OUTPUT -%---------------------------------------------------------- -byteArrayOutputStream = java.io.ByteArrayOutputStream; -% This StreamCopier is unsupported and may change at any time. OH GREAT :/ -isc = InterruptibleStreamCopier.getInterruptibleStreamCopier; -isc.copyStream(inputStream,byteArrayOutputStream); -inputStream.close; -byteArrayOutputStream.close; - -if in.CAST_OUTPUT - charset = ''; - - %Extraction of character set from Content-Type header if possible - if isfield(firstHeaders,'Content_Type') - text = firstHeaders.Content_Type; - %Always open to regexp improvements - charset = regexp(text,'(?<=charset=)[^\s]*','match','once'); - end - - if ~isempty(charset) - output = native2unicode(typecast(byteArrayOutputStream.toByteArray','uint8'),charset); - else - output = char(typecast(byteArrayOutputStream.toByteArray','uint8')); - end -else - %uint8 is more useful for later charecter conversions - %uint8 or int8 is somewhat arbitary at this point - output = typecast(byteArrayOutputStream.toByteArray','uint8'); -end - -extras = struct; -extras.allHeaders = allHeaders; -extras.firstHeaders = firstHeaders; -extras.status = status; -%Gets eventual url even with redirection -extras.url = char(urlConnection.getURL); -extras.isGood = isGood; - - - -end - -function headerNameOut = fixHeaderCasing(headerName) -%fixHeaderCasing Forces standard casing of headers -% -% headerNameOut = fixHeaderCasing(headerName) -% -% This is important for field access in a structure which -% is case sensitive -% -% Not yet finished. -% I've been adding to this function as problems come along - - switch lower(headerName) - case 'location' - headerNameOut = 'Location'; - case 'content_type' - headerNameOut = 'Content_Type'; - otherwise - headerNameOut = headerName; - end -end - -%========================================================================== -%========================================================================== -%========================================================================== - -function urlConnection = getURLConnection(urlChar) -%getURLConnection -% -% urlConnection = getURLConnection(urlChar) - -% Determine the protocol (before the ":"). -protocol = urlChar(1:find(urlChar==':',1)-1); - - -% Try to use the native handler, not the ice.* classes. -try - switch protocol - case 'http' - %http://www.docjar.com/docs/api/sun/net/www/protocol/http/HttpURLConnection.html - handler = sun.net.www.protocol.http.Handler; - case 'https' - handler = sun.net.www.protocol.https.Handler; - end -catch ME - handler = []; -end - -% Create the URL object. -try - if isempty(handler) - url = java.net.URL(urlChar); - else - url = java.net.URL([],urlChar,handler); - end -catch ME - error('Failure to parse URL or protocol not supported for:\nURL: %s',urlChar); -end - -% Get the proxy information using MathWorks facilities for unified proxy -% preference settings. -mwtcp = com.mathworks.net.transport.MWTransportClientPropertiesFactory.create(); -proxy = mwtcp.getProxy(); - -% Open a connection to the URL. -if isempty(proxy) - urlConnection = url.openConnection; -else - urlConnection = url.openConnection(proxy); -end - - -end +function [output,extras] = urlread2(urlChar,method,body,headersIn,varargin) +%urlread2 Makes HTTP requests and processes response +% +% [output,extras] = urlread2(urlChar, *method, *body, *headersIn, varargin) +% +% * indicates optional inputs that must be entered in place +% +% UNDOCUMENTED MATLAB VERSION +% +% EXAMPLE CALLING FORMS +% ... = urlread2(urlChar) +% ... = urlread2(urlChar,'GET','',[],prop1,value1,prop2,value2,etc) +% ... = urlread2(urlChar,'POST',body,headers) +% +% FEATURES +% ======================================================================= +% 1) Allows specification of any HTTP method +% 2) Allows specification of any header. Very little is hard-coded +% in for header handling. +% 3) Returns response status and headers +% 4) Should handle unicode properly ... +% +% OUTPUTS +% ======================================================================= +% output : body of the response, either text or binary depending upon +% CAST_OUTPUT property +% extras : (structure) +% .allHeaders - stucture, fields have cellstr values, HTTP headers may +% may be repeated but will have a single field entry, with each +% repeat's value another being another entry in the cellstr, for +% example: +% .Set_Cookie = {'first_value' 'second_value'} +% .firstHeaders - (structure), variable fields, contains the first +% string entry for each field in allHeaders, this +% structure can be used to avoid dereferencing a cell +% for fields you expect not to be repeated ... +% EXAMPLE: +% .Response : 'HTTP/1.1 200 OK'} +% .Server : 'nginx' +% .Date : 'Tue, 29 Nov 2011 02:23:16 GMT' +% .Content_Type : 'text/html; charset=UTF-8' +% .Content_Length : '109155' +% .Connection : 'keep-alive' +% .Vary : 'Accept-Encoding, User-Agent' +% .Cache_Control : 'max-age=60, private' +% .Set_Cookie : 'first_value' +% .status - (structure) +% .value : numeric value of status, ex. 200 +% .msg : message that goes along with status, ex. 'OK' +% .url - eventual url that led to output, this can change from +% the input with redirects, see FOLLOW_REDIRECTS +% .isGood - (logical) I believe this is an indicator of the presence of 400 +% or 500 status codes (see status.value) but more +% testing is needed. In other words, true if status.value < 400. +% In code, set true if the response was obtainable without +% resorting to checking the error stream. +% +% INPUTS +% ======================================================================= +% urlChar : The full url, must include scheme (http, https) +% method : examples: 'GET' 'POST' etc +% body : (vector)(char, uint8 or int8) body to write, generally used +% with POST or PUT, use of uint8 or int8 ensures that the +% body input is not manipulated before sending, char is sent +% via unicode2native function with ENCODING input (see below) +% headersIn : (structure array), use empty [] or '' if no headers are needed +% but varargin property/value pairs are, multiple headers +% may be passed in as a structure array +% .name - (string), name of the header, a name property is used +% instead of a field because the name must match a valid +% header +% .value - (string), value to use +% +% OPTIONAL INPUTS (varargin, property/value pairs) +% ======================================================================= +% CAST_OUTPUT : (default true) output is uint8, useful if the body +% of the response is not text +% ENCODING : (default ''), ENCODING input to function unicode2native +% FOLLOW_REDIRECTS : (default true), if false 3xx status codes will +% be returned and need to be handled by the user, +% note this does not handle javascript or meta tag +% redirects, just server based ones +% READ_TIMEOUT : (default 0), 0 means no timeout, value is in +% milliseconds +% +% EXAMPLES +% ======================================================================= +% GET: +% -------------------------------------------- +% url = 'http://www.mathworks.com/matlabcentral/fileexchange/'; +% query = 'urlread2'; +% params = {'term' query}; +% queryString = http_paramsToString(params,1); +% url = [url '?' queryString]; +% [output,extras] = urlread2(url); +% +% POST: +% -------------------------------------------- +% url = 'http://posttestserver.com/post.php'; +% params = {'testChars' char([2500 30000]) 'new code' '?'}; +% [paramString,header] = http_paramsToString(params,1); +% [output,extras] = urlread2(url,'POST',paramString,header); +% +% From behind a firewall, use the Preferences to set your proxy server. +% +% See Also: +% http_paramsToString +% unicode2native +% native2unicode +% +% Subfunctions: +% fixHeaderCasing - small subfunction to fix case errors encountered in real +% world, requires updating when casing doesn't match expected form, like +% if someone sent the header content-Encoding instead of +% Content-Encoding +% +% Based on original urlread code by Matthew J. Simoneau +% +% VERSION = 1.1 + +in.CAST_OUTPUT = true; +in.FOLLOW_REDIRECTS = true; +in.READ_TIMEOUT = 0; +in.ENCODING = ''; + +%Input handling +%--------------------------------------- +if ~isempty(varargin) + for i = 1:2:numel(varargin) + prop = upper(varargin{i}); + value = varargin{i+1}; + if isfield(in,prop) + in.(prop) = value; + else + error('Unrecognized input to function: %s',prop) + end + end +end + +if ~exist('method','var') || isempty(method), method = 'GET'; end +if ~exist('body','var'), body = ''; end +if ~exist('headersIn','var'), headersIn = []; end + +assert(usejava('jvm'),'Function requires Java') + +import com.mathworks.mlwidgets.io.InterruptibleStreamCopier; +com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings %Proxy settings need to be set + +%Create a urlConnection. +%----------------------------------- +urlConnection = getURLConnection(urlChar); +%For HTTP uses sun.net.www.protocol.http.HttpURLConnection +%Might use ice.net.HttpURLConnection but this has more overhead + +%SETTING PROPERTIES +%------------------------------------------------------- +urlConnection.setRequestMethod(upper(method)); +urlConnection.setFollowRedirects(in.FOLLOW_REDIRECTS); +urlConnection.setReadTimeout(in.READ_TIMEOUT); + +for iHeader = 1:length(headersIn) + curHeader = headersIn(iHeader); + urlConnection.setRequestProperty(curHeader.name,curHeader.value); +end + +if ~isempty(body) + %Ensure vector? + if size(body,1) > 1 + if size(body,2) > 1 + error('Input parameter to function: body, must be a vector') + else + body = body'; + end + end + + if ischar(body) + %NOTE: '' defaults to Matlab's default encoding scheme + body = unicode2native(body,in.ENCODING); + elseif ~(strcmp(class(body),'uint8') || strcmp(class(body),'int8')) + error('Function input: body, should be of class char, uint8, or int8, detected: %s',class(body)) + end + + urlConnection.setRequestProperty('Content-Length',int2str(length(body))); + urlConnection.setDoOutput(true); + outputStream = urlConnection.getOutputStream; + outputStream.write(body); + outputStream.close; +else + urlConnection.setRequestProperty('Content-Length','0'); +end + +%========================================================================== +% Read the data from the connection. +%========================================================================== +%This should be done first because it tells us if things are ok or not +%NOTE: If there is an error, functions below using urlConnection, notably +%getResponseCode, will fail as well +try + inputStream = urlConnection.getInputStream; + isGood = true; +catch ME + isGood = false; +%NOTE: HTTP error codes will throw an error here, we'll allow those for now +%We might also get another error in which case the inputStream will be +%undefined, those we will throw here + inputStream = urlConnection.getErrorStream; + + if isempty(inputStream) + msg = ME.message; + I = strfind(msg,char([13 10 9])); %see example by setting timeout to 1 + %Should remove the barf of the stack, at ... at ... at ... etc + %Likely that this could be improved ... (generate link with full msg) + if ~isempty(I) + msg = msg(1:I(1)-1); + end + fprintf(2,'Response stream is undefined\n below is a Java Error dump (truncated):\n'); + error(msg) + end +end + +%POPULATING HEADERS +%-------------------------------------------------------------------------- +allHeaders = struct; +allHeaders.Response = {char(urlConnection.getHeaderField(0))}; +done = false; +headerIndex = 0; + +while ~done + headerIndex = headerIndex + 1; + headerValue = char(urlConnection.getHeaderField(headerIndex)); + if ~isempty(headerValue) + headerName = char(urlConnection.getHeaderFieldKey(headerIndex)); + headerName = fixHeaderCasing(headerName); %NOT YET FINISHED + + %Important, for name safety all hyphens are replace with underscores + headerName(headerName == '-') = '_'; + if isfield(allHeaders,headerName) + allHeaders.(headerName) = [allHeaders.(headerName) headerValue]; + else + allHeaders.(headerName) = {headerValue}; + end + else + done = true; + end +end + +firstHeaders = struct; +fn = fieldnames(allHeaders); +for iHeader = 1:length(fn) + curField = fn{iHeader}; + firstHeaders.(curField) = allHeaders.(curField){1}; +end + +status = struct(... + 'value', urlConnection.getResponseCode(),... + 'msg', char(urlConnection.getResponseMessage)); + +%PROCESSING OF OUTPUT +%---------------------------------------------------------- +byteArrayOutputStream = java.io.ByteArrayOutputStream; +% This StreamCopier is unsupported and may change at any time. OH GREAT :/ +isc = InterruptibleStreamCopier.getInterruptibleStreamCopier; +isc.copyStream(inputStream,byteArrayOutputStream); +inputStream.close; +byteArrayOutputStream.close; + +if in.CAST_OUTPUT + charset = ''; + + %Extraction of character set from Content-Type header if possible + if isfield(firstHeaders,'Content_Type') + text = firstHeaders.Content_Type; + %Always open to regexp improvements + charset = regexp(text,'(?<=charset=)[^\s]*','match','once'); + end + + if ~isempty(charset) + output = native2unicode(typecast(byteArrayOutputStream.toByteArray','uint8'),charset); + else + output = char(typecast(byteArrayOutputStream.toByteArray','uint8')); + end +else + %uint8 is more useful for later charecter conversions + %uint8 or int8 is somewhat arbitary at this point + output = typecast(byteArrayOutputStream.toByteArray','uint8'); +end + +extras = struct; +extras.allHeaders = allHeaders; +extras.firstHeaders = firstHeaders; +extras.status = status; +%Gets eventual url even with redirection +extras.url = char(urlConnection.getURL); +extras.isGood = isGood; + + + +end + +function headerNameOut = fixHeaderCasing(headerName) +%fixHeaderCasing Forces standard casing of headers +% +% headerNameOut = fixHeaderCasing(headerName) +% +% This is important for field access in a structure which +% is case sensitive +% +% Not yet finished. +% I've been adding to this function as problems come along + + switch lower(headerName) + case 'location' + headerNameOut = 'Location'; + case 'content_type' + headerNameOut = 'Content_Type'; + otherwise + headerNameOut = headerName; + end +end + +%========================================================================== +%========================================================================== +%========================================================================== + +function urlConnection = getURLConnection(urlChar) +%getURLConnection +% +% urlConnection = getURLConnection(urlChar) + +% Determine the protocol (before the ":"). +protocol = urlChar(1:find(urlChar==':',1)-1); + + +% Try to use the native handler, not the ice.* classes. +try + switch protocol + case 'http' + %http://www.docjar.com/docs/api/sun/net/www/protocol/http/HttpURLConnection.html + handler = sun.net.www.protocol.http.Handler; + case 'https' + handler = sun.net.www.protocol.https.Handler; + end +catch ME + handler = []; +end + +% Create the URL object. +try + if isempty(handler) + url = java.net.URL(urlChar); + else + url = java.net.URL([],urlChar,handler); + end +catch ME + error('Failure to parse URL or protocol not supported for:\nURL: %s',urlChar); +end + +% Get the proxy information using MathWorks facilities for unified proxy +% preference settings. +mwtcp = com.mathworks.net.transport.MWTransportClientPropertiesFactory.create(); +proxy = mwtcp.getProxy(); + +% Open a connection to the URL. +if isempty(proxy) + urlConnection = url.openConnection; +else + urlConnection = url.openConnection(proxy); +end + + +end diff --git a/plotly/plotly_aux/urlread2/urlread_notes.txt b/plotly/plotly_aux/urlread2/urlread_notes.txt index 8257f092..7a2ba14f 100755 --- a/plotly/plotly_aux/urlread2/urlread_notes.txt +++ b/plotly/plotly_aux/urlread2/urlread_notes.txt @@ -1,86 +1,86 @@ -========================================================================== - Unicode & Matlab -========================================================================== -native2unicode - works with uint8, fails with char - -Taking a unicode character and encoding as bytes: -unicode2native(char(1002),'UTF-8') -back to the character: -native2unicode(uint8([207 170]),'UTF-8') -this doesn't work: -native2unicode(char([207 170]),'UTF-8') -in documentation: If BYTES is a CHAR vector, it is returned unchanged. - -Java - only supports int8 -Matlab to Java -> uint8 or int8 to bytes -Java to Matlab -> bytes to int8 -char - 16 bit - -Maintenance of underlying bytes: -typecast(java.lang.String(uint8(250)).getBytes,'uint8') = 250 -see documentation: Handling Data Returned from a Java Method - -Command Window difficulty --------------------------------------------------------------------- -The typical font in the Matlab command window will often fail to render -unicode properly. I often can see unicode better in the variable editor -although this may be fixed if you change your font preferences ... -Copying unicode from the command window often results in the -generations of the value 26 (aka substitute) - -More documentation on input/output to urlread2 to follow eventually ... - -small notes to self: -for output -native2unicode(uint8(output),encoding) - -========================================================================== - HTTP Headers -========================================================================== -Handling of repeated http readers is a bit of a tricky situation. Most -headers are not repeated although sometimes http clients will assume this -for too many headers which can result in a problem if you want to see -duplicated headers. I've passed the problem onto the user who can decide -to handle it how they wish instead of providing the right solution, which -after some brief searching, I am not sure exists. - -========================================================================== - PROBLEMS -========================================================================== -1) Page requires following a redirect: -%------------------------------------------- -ref: http://www.mathworks.com/matlabcentral/newsreader/view_thread/302571 -fix: FOLLOW_REDIRECTS is enabled by default, you're fine. - -2) Basic authentication required: -%------------------------------------------ -Create and pass in the following header: -user = 'test'; -password = 'test'; -encoder = sun.misc.BASE64Encoder(); -str = java.lang.String([user ':' password]) %NOTE: format may be -%different for your server -header = http_createHeader('Authorization',char(encoder.encode(str.getBytes()))) -NOTE: Ideally you would make this a function - -3) The text returned doesn't make sense. -%----------------------------------------- -The text may not be encoded correctly. Requires native2unicode function. -See Unicode & Matlab section above. - -4) I get a different result in my web browser than I do in Matlab -%----------------------------------------- -This is generally seen for two reasons. -1 - The easiest and silly reason is user agent filtering. -When you make a request you identify yourself -as being a particular "broswer" or "user agent". Setting a header -with the user agent of the browser may fix the problem. -See: http://en.wikipedia.org/wiki/User_agent -See: http://whatsmyuseragent.com -value = '' -header = http_createHeader('User-Agent',value); -2 - You are not processing cookies and the server is not sending -you information because you haven't sent it cookies (everyone likes em!) -I've implemented cookie support but it requires some extra files that -I need to clean up. Feel free to email me if you'd really like to have them. - +========================================================================== + Unicode & Matlab +========================================================================== +native2unicode - works with uint8, fails with char + +Taking a unicode character and encoding as bytes: +unicode2native(char(1002),'UTF-8') +back to the character: +native2unicode(uint8([207 170]),'UTF-8') +this doesn't work: +native2unicode(char([207 170]),'UTF-8') +in documentation: If BYTES is a CHAR vector, it is returned unchanged. + +Java - only supports int8 +Matlab to Java -> uint8 or int8 to bytes +Java to Matlab -> bytes to int8 +char - 16 bit + +Maintenance of underlying bytes: +typecast(java.lang.String(uint8(250)).getBytes,'uint8') = 250 +see documentation: Handling Data Returned from a Java Method + +Command Window difficulty +-------------------------------------------------------------------- +The typical font in the Matlab command window will often fail to render +unicode properly. I often can see unicode better in the variable editor +although this may be fixed if you change your font preferences ... +Copying unicode from the command window often results in the +generations of the value 26 (aka substitute) + +More documentation on input/output to urlread2 to follow eventually ... + +small notes to self: +for output +native2unicode(uint8(output),encoding) + +========================================================================== + HTTP Headers +========================================================================== +Handling of repeated http readers is a bit of a tricky situation. Most +headers are not repeated although sometimes http clients will assume this +for too many headers which can result in a problem if you want to see +duplicated headers. I've passed the problem onto the user who can decide +to handle it how they wish instead of providing the right solution, which +after some brief searching, I am not sure exists. + +========================================================================== + PROBLEMS +========================================================================== +1) Page requires following a redirect: +%------------------------------------------- +ref: http://www.mathworks.com/matlabcentral/newsreader/view_thread/302571 +fix: FOLLOW_REDIRECTS is enabled by default, you're fine. + +2) Basic authentication required: +%------------------------------------------ +Create and pass in the following header: +user = 'test'; +password = 'test'; +encoder = sun.misc.BASE64Encoder(); +str = java.lang.String([user ':' password]) %NOTE: format may be +%different for your server +header = http_createHeader('Authorization',char(encoder.encode(str.getBytes()))) +NOTE: Ideally you would make this a function + +3) The text returned doesn't make sense. +%----------------------------------------- +The text may not be encoded correctly. Requires native2unicode function. +See Unicode & Matlab section above. + +4) I get a different result in my web browser than I do in Matlab +%----------------------------------------- +This is generally seen for two reasons. +1 - The easiest and silly reason is user agent filtering. +When you make a request you identify yourself +as being a particular "broswer" or "user agent". Setting a header +with the user agent of the browser may fix the problem. +See: http://en.wikipedia.org/wiki/User_agent +See: http://whatsmyuseragent.com +value = '' +header = http_createHeader('User-Agent',value); +2 - You are not processing cookies and the server is not sending +you information because you haven't sent it cookies (everyone likes em!) +I've implemented cookie support but it requires some extra files that +I need to clean up. Feel free to email me if you'd really like to have them. + diff --git a/plotly/plotly_aux/urlread2/urlread_todos.txt b/plotly/plotly_aux/urlread2/urlread_todos.txt index 0434bcea..86dd62d0 100755 --- a/plotly/plotly_aux/urlread2/urlread_todos.txt +++ b/plotly/plotly_aux/urlread2/urlread_todos.txt @@ -1,13 +1,13 @@ -========================================================================== - IMPROVEMENTS -========================================================================== -1) The function could be improved to support file streaming both in sending -and in receiving (saving) to reduce memory usage but this is very low priority - -2) Implement better casing handling - -3) Choose a better function name than urlread2 -> sorry Chris :) - -4) Support multipart/form-data, this ideally would be handled by a helper function - +========================================================================== + IMPROVEMENTS +========================================================================== +1) The function could be improved to support file streaming both in sending +and in receiving (saving) to reduce memory usage but this is very low priority + +2) Implement better casing handling + +3) Choose a better function name than urlread2 -> sorry Chris :) + +4) Support multipart/form-data, this ideally would be handled by a helper function + 5) Allow for throwing an error if the HTTP status code is an error (400) and 500 as well? \ No newline at end of file diff --git a/plotly/plotly_aux/urlread2/urlread_versionInfo.txt b/plotly/plotly_aux/urlread2/urlread_versionInfo.txt index a8448f49..6feb2133 100755 --- a/plotly/plotly_aux/urlread2/urlread_versionInfo.txt +++ b/plotly/plotly_aux/urlread2/urlread_versionInfo.txt @@ -1,13 +1,13 @@ -===================== -Version 1.1 -3/25/2012 - -Summary: Bug fixes related to Matlab throwing errors when it shouldn't have been. Thanks to Shane Lin for pointing out the problems. - -Bug Fix: Modified code so that http status errors wouldn't throw errors in the code, but rather would be passed on to the user to process - -Bug Fix: Provided GET example code apparently doesn't work for all users, changed to a different example. - -===================== -Version 1 +===================== +Version 1.1 +3/25/2012 + +Summary: Bug fixes related to Matlab throwing errors when it shouldn't have been. Thanks to Shane Lin for pointing out the problems. + +Bug Fix: Modified code so that http status errors wouldn't throw errors in the code, but rather would be passed on to the user to process + +Bug Fix: Provided GET example code apparently doesn't work for all users, changed to a different example. + +===================== +Version 1 3/17/2012 \ No newline at end of file From 17c6471637d428a907a85b65146576c1f14878dd Mon Sep 17 00:00:00 2001 From: Abderahmane BENALI <46283596+benaliabderrahmane@users.noreply.github.com> Date: Tue, 3 Aug 2021 15:36:24 +0100 Subject: [PATCH 5/5] changed if statements with switchs --- .../plotlyfig_aux/helpers/convertDuration.m | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/plotly/plotlyfig_aux/helpers/convertDuration.m b/plotly/plotlyfig_aux/helpers/convertDuration.m index bc390f23..bbffae35 100644 --- a/plotly/plotlyfig_aux/helpers/convertDuration.m +++ b/plotly/plotlyfig_aux/helpers/convertDuration.m @@ -1,26 +1,24 @@ function [converted,type] = convertDuration(duration) -if (strcmpi(duration.Format,'s')) - converted = seconds(duration); - type = 'sec'; - -elseif (strcmpi(duration.Format,'m')) - converted = minutes(duration); - type = 'min'; - -elseif (strcmpi(duration.Format,'h')) - converted = hours(duration); - type = 'hr'; - -elseif (strcmpi(duration.Format,'d')) - converted = days(duration); - type = 'days'; - -elseif (strcmpi(duration.Format,'y')) - converted = years(duration); - type = 'yrs'; -else +switch (duration.Format) + case 's' + converted = seconds(duration); + type = 'sec'; + case 'm' + converted = minutes(duration); + type = 'min'; + case 'h' + converted = hours(duration); + type = 'hr'; + case 'd' + converted = days(duration); + type = 'days'; + case 'y' + converted = years(duration); + type = 'yrs'; + otherwise %no convertion is applied converted = duration; type = ''; + end end \ No newline at end of file