# HG changeset patch
# User Sahil Yadav <yadavsahil5198@gmail.com>
# Date 1555171576 -32400
#      Sun Apr 14 01:06:16 2019 +0900
# Node ID 0b2690400b26f0dd887b8669d251775ac4a3b12f
# Parent  63f37a9955fd67e2ae3e75aafc39bb25e77665b6
MediaWiki related part of the GSoC 2018 project by Sahil Yadav.

diff -r 63f37a9955fd -r 0b2690400b26 libinterp/corefcn/urlwrite.cc
--- a/libinterp/corefcn/urlwrite.cc	Sun Apr 14 00:56:16 2019 +0900
+++ b/libinterp/corefcn/urlwrite.cc	Sun Apr 14 01:06:16 2019 +0900
@@ -830,3 +830,96 @@ Undocumented internal function.
 
   return ovl (content.str ());
 }
+
+DEFUN (__wiki_login__, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {@var{content} =} __wiki_login__ (@var{url}, @var{cookie_file})
+@deftypefnx {} {@var{content} =} __wiki_login__ (@var{url}, @var{cookie_file}, @var{param})
+Logs into @var{url}, keeping the cookies in file @var{cookie_file} intact.
+@var{param} denote the POST parameters for the transfer.
+@end deftypefn */)
+{
+
+  if (args.length () < 2 || args.length () > 3)
+    print_usage ();
+
+  std::string url = args(0).xstring_value ("__wiki_login__: URL must be a string");
+
+  std::string filename = args(1).string_value ();
+
+  std::ostringstream content;
+
+  octave::url_transfer url_xfer (url, content);
+
+  url_xfer.cookie_jar (filename);
+
+  if (! url_xfer.is_valid ())
+    error ("support for URL transfers was disabled when Octave was built");
+
+  octave_value_list retval;
+
+  Array<std::string> param;
+
+  std::string method;
+
+  // Add the POST parameters, if available, to the transfer.
+  if (args.length () == 3)
+    {
+      param = args(2).cellstr_value ();
+
+      method = "post";
+    }
+
+  url_xfer.http_action (param, method);
+
+  retval = ovl (content.str ());
+
+  if (nargout < 2 && ! url_xfer.good ())
+    error ("__wiki_login__: %s", url_xfer.lasterror ().c_str ());
+
+  return retval;
+}
+
+DEFUN (__file_upload__, args, nargout,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {@var{content} =} __file_upload__ (@var{url}, @var{cookie_file}, @var{form_data})
+Performs the transfer of @var{form_data} on the connection specified by
+@var{url} and @var{cookie_file}.
+
+It is different from __wiki_login__ in the
+fact that it uses CURLOPT_HTTPPOST rather than CURLOPT_POSTFIELDS macro used
+by the its counterpart.
+@end deftypefn */)
+{
+
+  if (args.length () != 3)
+    print_usage ();
+
+  std::ostringstream content;
+
+  std::string url = args(0).xstring_value ("file_upload: URL must be a string");
+
+  octave::url_transfer url_xfer (url, content);
+
+  std::string filename = args(1).string_value ();
+
+  url_xfer.cookie_jar (filename);
+
+  if (! url_xfer.is_valid ())
+    error ("support for URL transfers was disabled when Octave was built");
+
+  octave_value_list retval;
+
+  Array<std::string> form_data;
+
+  form_data = args(2).cellstr_value ();
+
+  url_xfer.form_data_post (form_data);
+
+  retval = ovl (content.str ());
+
+  if (nargout < 2 && ! url_xfer.good ())
+    error ("__file_upload__: %s", url_xfer.lasterror ().c_str ());
+
+  return retval;
+}
diff -r 63f37a9955fd -r 0b2690400b26 scripts/miscellaneous/module.mk
--- a/scripts/miscellaneous/module.mk	Sun Apr 14 00:56:16 2019 +0900
+++ b/scripts/miscellaneous/module.mk	Sun Apr 14 01:06:16 2019 +0900
@@ -4,6 +4,7 @@ FCN_FILE_DIRS += \
 
 %canon_reldir%_PRIVATE_FCN_FILES = \
   %reldir%/private/__publish_html_output__.m \
+  %reldir%/private/__publish_wiki_output__.m \
   %reldir%/private/__publish_latex_output__.m \
   %reldir%/private/__w2mpth__.m \
   %reldir%/private/display_info_file.m
@@ -63,6 +64,7 @@ FCN_FILE_DIRS += \
   %reldir%/parseparams.m \
   %reldir%/perl.m \
   %reldir%/publish.m \
+  %reldir%/publish_to_wiki.m \
   %reldir%/python.m \
   %reldir%/recycle.m \
   %reldir%/run.m \
@@ -82,6 +84,7 @@ FCN_FILE_DIRS += \
   %reldir%/verLessThan.m \
   %reldir%/version.m \
   %reldir%/what.m \
+  %reldir%/wiki_upload.m \
   %reldir%/zip.m
 
 %canon_reldir%dir = $(fcnfiledir)/miscellaneous
diff -r 63f37a9955fd -r 0b2690400b26 scripts/miscellaneous/private/__publish_wiki_output__.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/private/__publish_wiki_output__.m	Sun Apr 14 01:06:16 2019 +0900
@@ -0,0 +1,213 @@
+## Copyright (C) 2016-2018 Kai T. Ohlhus
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{outstr} =} __publish_wiki_output__ (@var{type}, @var{varargin})
+##
+## Internal function.
+##
+## The first input argument @var{type} defines the required strings
+## (@samp{str}) or cell-strings (@samp{cstr}) in @var{varargin} in order
+## to produce wiki output, processible by WikiMedia installation.
+##
+## @var{type} is one of
+##
+## @itemize @bullet
+## @item
+## @samp{output_file_extension} ()
+##
+## @item
+## @samp{header} (title_str, intro_str, toc_cstr)
+##
+## @item
+## @samp{footer} ()
+##
+## @item
+## @samp{code} (str)
+##
+## @item
+## @samp{code_output} (str)
+##
+## @item
+## @samp{section} (str)
+##
+## @item
+## @samp{preformatted_code} (str)
+##
+## @item
+## @samp{preformatted_text} (str)
+##
+## @item
+## @samp{bulleted_list} (cstr)
+##
+## @item
+## @samp{numbered_list} (cstr)
+##
+## @item
+## @samp{graphic} (str)
+##
+## @item
+## @samp{html} (str)
+##
+## @item
+## @samp{latex} (str)
+##
+## @item
+## @samp{text} (str)
+##
+## @item
+## @samp{blockmath} (str)
+##
+## @item
+## @samp{inlinemath} (str)
+##
+## @item
+## @samp{bold} (str)
+##
+## @item
+## @samp{italic} (str)
+##
+## @item
+## @samp{monospaced} (str)
+##
+## @item
+## @samp{link} (url_str, url_str, str)
+##
+## @item
+## @samp{TM} ()
+##
+## @item
+## @samp{R} ()
+##
+## @item
+## @samp{escape_special_chars} (str)
+## @end itemize
+## @end deftypefn
+
+function outstr = __publish_wiki_output__ (type, varargin)
+  outstr = feval (["do_" type], varargin{:});
+endfunction
+
+function outstr = do_output_file_extension ()
+  outstr = ".wiki";
+endfunction
+
+function outstr = do_header (title_str, intro_str, toc_cstr)
+  outstr = ["__TOC__\n" intro_str];
+endfunction
+
+function outstr = do_footer (m_source_str)
+  outstr = ['<div class="toccolours mw-collapsible mw-collapsed">', ...
+    "\nOctave source for grabcode, published with GNU Octave ", ...
+    version(), "\n", ...
+    '<div class="mw-collapsible-content">', ...
+    do_code_output(["##### SOURCE BEGIN #####\n", m_source_str, ...
+    "\n##### SOURCE END #####"]), ...
+    "\n</div>\n</div>\n[[Category:Agora]]"];
+endfunction
+
+function outstr = do_code (str)
+  outstr = ["\n<syntaxhighlight lang=\"octave\">", str, "</syntaxhighlight>\n"];
+endfunction
+
+function outstr = do_code_output (str)
+  outstr = ["\n<syntaxhighlight lang=\"text\">", str, "</syntaxhighlight>\n"];
+endfunction
+
+function outstr = do_section (varargin)
+  outstr = ["\n= ", varargin{1}, " =\n"];
+endfunction
+
+function outstr = do_preformatted_code (str)
+  outstr = do_code (str);
+endfunction
+
+function outstr = do_preformatted_text (str)
+  outstr = ["\n <nowiki>\n", str, "</nowiki>\n"];
+endfunction
+
+function outstr = do_bulleted_list (cstr)
+  outstr = "\n";
+  for i = 1:length(cstr)
+    outstr = [outstr, "* ", cstr{i}, "\n"];
+  endfor
+  outstr = [outstr, "\n"];
+endfunction
+
+function outstr = do_numbered_list (cstr)
+  outstr = "\n";
+  for i = 1:length(cstr)
+    outstr = [outstr, "# ", cstr{i}, "\n"];
+  endfor
+  outstr = [outstr, "\n"];
+endfunction
+
+function outstr = do_graphic (str)
+  outstr = ["[[File:", str, "|thumb|center]]"];
+endfunction
+
+function outstr = do_html (str)
+  outstr = str;
+endfunction
+
+function outstr = do_latex (str)
+  outstr = "";
+endfunction
+
+function outstr = do_link (url_str, str)
+  outstr = ["[", url_str," ", str, "]"];
+endfunction
+
+function outstr = do_text (str)
+  outstr = ["\n", str, "\n"];
+endfunction
+
+function outstr = do_blockmath (str)
+  outstr = ["<math display='block'>" str "</math>"];
+endfunction
+
+function outstr = do_inlinemath (str)
+  outstr = ["<math display='inline'>" str "</math>"];
+endfunction
+
+function outstr = do_bold (str)
+  outstr = ["'''", str, "'''"];
+endfunction
+
+function outstr = do_italic (str)
+  outstr = ["''", str, "''"];
+endfunction
+
+function outstr = do_monospaced (str)
+  outstr = ["<code>", str, "</code>"];
+endfunction
+
+function outstr = do_TM ()
+  outstr = "&trade;";
+endfunction
+
+function outstr = do_R ()
+  outstr = "&reg;";
+endfunction
+
+function str = do_escape_special_chars (str)
+  str = regexprep (str, '&', '&amp;');
+  str = regexprep (str, '<', '&lt;');
+  str = regexprep (str, '>', '&gt;');
+  ## str = regexprep (str, '"', '&quot;'); ## MATLAB R2017a compatibility.
+endfunction
\ No newline at end of file
diff -r 63f37a9955fd -r 0b2690400b26 scripts/miscellaneous/publish.m
--- a/scripts/miscellaneous/publish.m	Sun Apr 14 00:56:16 2019 +0900
+++ b/scripts/miscellaneous/publish.m	Sun Apr 14 01:06:16 2019 +0900
@@ -90,7 +90,7 @@
 ## @samp{format} --- Output format of the published script file, one of
 ##
 ## @samp{html} (default), @samp{doc}, @samp{latex}, @samp{ppt},
-## @samp{pdf}, or @samp{xml}.
+## @samp{pdf}, @samp{wiki}, or @samp{xml}.
 ##
 ## The output formats @samp{doc}, @samp{ppt}, and @samp{xml} are not currently
 ## supported.  To generate a @samp{doc} report, open a generated @samp{html}
@@ -250,7 +250,7 @@ function output_file = publish (file, va
              options.format);
     endif
     ## Supported or custom output format
-    supported_formats = {"html", "doc", "latex", "ppt", "xml", "pdf"};
+    supported_formats = {"html", "doc", "latex", "ppt", "xml", "pdf", "wiki"};
     if (! any (strcmpi (options.format, supported_formats)))
       ## Check existence of custom formatter
       custom_formatter = ["__publish_", options.format, "_output__"];
@@ -991,6 +991,7 @@ function doc = eval_code (doc, options)
         if (isempty (get (fig_ids_new(j), "children")))
           continue;
         endif
+        fig_name(1) = toupper (fig_name(1));
         fname = [fig_name, "-", sprintf("%d", fig_num)];
         if (strncmp (options.imageFormat, "eps", 3))
           fname = [fname ".eps"];
diff -r 63f37a9955fd -r 0b2690400b26 scripts/miscellaneous/publish_to_wiki.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/publish_to_wiki.m	Sun Apr 14 01:06:16 2019 +0900
@@ -0,0 +1,70 @@
+## Copyright (C) 2017-2018 Kai T. Ohlhus <k.ohlhus@gmail.com>
+## Copyright (C) 2018 Sahil Yadav <yadavsahil5198@gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {} publish_to_wiki (@var{script_file}, @var{username}, @var{password})
+## Publishes a user's Octave script @var{script_file} to Octave's wiki, using
+## the user credentials @var{username} and @var{password}.
+##
+## The @var{username} and @var{password} are NOT stored anywhere after the
+## operation has been completed. All the three arguments should be strings with
+## @var{script_file} being without the extension ".m".
+##
+## Note that it can only publish script files. To know more about how to best
+## publish your script, refer to the help text of @code{publish} function.
+##
+## It uses @code{publish} internally to generate a wiki output.
+## @seealso{webread, webwrite, weboptions}
+## @end deftypefn
+
+function publish_to_wiki (script_file, username, password)
+
+  if (nargin != 3)
+    print_usage ();
+  endif
+
+  wiki_api = "https://wiki.octave.org/api.php";
+
+  output_file = publish (script_file, "wiki");
+
+  [~,filename] = fileparts (script_file);
+
+  ## Capitalize the first character of the script file's name because that's
+  ## how the pages are stored on the wiki.
+  filename(1) = toupper (filename(1));
+
+  # Extract images from the generated .wiki file
+  directory = fileparts (output_file);
+
+  images = fileread (output_file);
+  images = regexp (images, '\[\[File:([^|]*)', "tokens");
+  images = fullfile (directory, [images{:}]);
+
+  ## Empty the indexes of images that couldn't be found.
+  del_idx = [];
+  for i = 1:length (images)
+    if (! exist (images{i}, "file"))
+      del_idx = [del_idx, i];
+      warning ("publish_to_wiki: cannot find %s", images{i});
+    endif
+  endfor
+  images(del_idx) = [];
+
+  wiki_upload (wiki_api, username, password, filename, output_file, images);
+endfunction
diff -r 63f37a9955fd -r 0b2690400b26 scripts/miscellaneous/wiki_upload.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/miscellaneous/wiki_upload.m	Sun Apr 14 01:06:16 2019 +0900
@@ -0,0 +1,146 @@
+## Copyright (C) 2017-2018 Kai T. Ohlhus <k.ohlhus@gmail.com>
+## Copyright (C) 2018 Sahil Yadav <yadavsahil5198@gmail.com>
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {} {} wiki_upload (@var{wiki_api}, @var{username}, @var{password}, @var{filename}, @var{output_file}, @var{images})
+## Undocumented Internal Function.
+## @end deftypefn
+
+function wiki_upload (wiki_api, username, password, filename, output_file, images)
+
+  if (nargin != 6)
+    print_usage ();
+  endif
+
+  cookie_jar = tempname;                         # Temporary cookie file
+
+  ## URL for getting login token from the wiki.
+  login_token = [wiki_api, "?action=query&meta=tokens&type=login&format=json"];
+
+  token = __wiki_login__ (login_token, cookie_jar);
+
+  if (! isempty (token))
+    logintoken = regexp (token, '.*"logintoken":"(\S+)+".*', "tokens");
+
+    if (! isempty (logintoken))
+      logintoken = logintoken{1};
+      logintoken = logintoken{1};
+      logintoken = logintoken(1:end-1);          # remove the trailing "\"
+    else
+      error ("wiki_upload: Could not retrieve login token.");
+    endif
+  endif
+
+  disp ("Login:");
+
+  ## URL for logging into the wiki account
+  login_url = [wiki_api, "?action=clientlogin&format=json"];
+
+  ## Cookies that will be saved in the temporary file and will be sent over
+  ## POST request to the server.
+  cookies = {"username", username, "password", password, "rememberMe", "1", ...
+        "logintoken", logintoken, "loginreturnurl", wiki_api};
+
+  content = __wiki_login__ (login_url, cookie_jar, cookies);
+
+  ## Retrieve the status and username from the response.
+  if (! isempty (content))
+    username = regexp (content, '.*"username":"([^"]*).*', "tokens");
+    status = regexp (content, '.*"status":"([^"]*).*', "tokens");
+    if (! isempty (username))
+      username = username{1};
+      username = username{1};
+      disp (["    Logged in as ", username]);
+    elseif (! isempty (status))
+      status = status{1};
+      error ("wiki_upload: Failure: Status %s", status{1});
+    else
+      error ("wiki_upload: Could not login to wiki.");
+    endif
+  endif
+
+  ## URL for getting edit token.
+  edit_token = [wiki_api, "?action=query&meta=tokens&format=json"];
+
+  content = __wiki_login__ (edit_token, cookie_jar);
+
+  if (! isempty (content))
+    csrftoken = regexp (content, '.*"csrftoken":"(\S+)+".*', "tokens");
+    if (! isempty (csrftoken))
+      csrftoken = csrftoken{1};
+      csrftoken = csrftoken{1};
+      csrftoken = csrftoken(1:end-1);
+    else
+      error ("wiki_upload: Could not retrieve edit token.");
+    endif
+  endif
+
+  printf ("Updating page %s:\n", filename);
+
+  ## URL for editing the page using the CSRF token retrieved in the above step
+  edit_url = [wiki_api, "?action=edit&format=json"];
+
+  output_file = fileread (output_file);
+
+  cookies = {"title", filename, "text", output_file, "token", csrftoken};
+
+  content = __wiki_login__ (edit_url, cookie_jar, cookies);
+
+  result = regexp (content, '.*"result":"([^"]*).*', "tokens");
+
+  if (!isempty (result))
+    disp (["    SUCCESS: Updated page ", filename]);
+  else
+    error (["wiki_upload: Couldn't update page ", filename]);
+  endif
+
+  for i = 1:numel (images)
+    printf ("Updating images of %s:\n", filename);
+
+    if (exist (images{i}, "file"))
+      [~, fname] = fileparts (images{i});
+
+      form_data = {"filename", fname, "file", images{i},...
+                  "ignorewarnings", "1", "token", csrftoken};
+
+      url = [wiki_api, "?action=upload&format=json"];
+
+      content = __file_upload__ (url, cookie_jar, form_data);
+
+      if (! isempty (content))
+        result = regexp (content, '.*"result":"([^"]*).*', "tokens");
+        warnings = regexp (content, '.*"warnings":{"([^"]*).*', "tokens")
+        code = regexp (content, '.*"code":"([^"]*).*', "tokens");
+
+        if (strcmp (result, "Success") && strcmp (warnings, "badfilename"))
+          disp (["    A file with the name as ",fname, " already exists.",...
+                  " A newer version of the file will be uploaded."]);
+        elseif (strcmp (result, "Success"))
+          disp (["    SUCCESS: Uploaded image ", fname]);
+        else
+          disp (["    Not uploading the file: ", fname,...
+                 ". An exact duplicate already exists."]);
+        endif
+      endif
+    endif
+  endfor
+
+  delete (cookie_jar);                           # Delete the temp file
+
+endfunction
\ No newline at end of file
