Source for file squirrelmail_rpc.php

Documentation is available at squirrelmail_rpc.php

  1. <?php
  2.  
  3. /**
  4.   * squirrelmail_rpc.php
  5.   *
  6.   * This file contains the entry point to the "SquirrelMail API" -- the
  7.   * remote procedure call request receiver.
  8.   *
  9.   * RPC requests are currently understood as simple HTTP GET or POST
  10.   * requests.  The SquirrelMail default_rpc template set responds in a
  11.   * SOAP (currently v1.2) compliant manner, but this interface does not
  12.   * (yet?) understand SOAP requests.  The format of responses can be
  13.   * changed by creating a different RPC template set and pointing to it
  14.   * with $rpc_templateset in the main SquirrelMail configuration file.
  15.   * 
  16.   * @copyright 1999-2014 The SquirrelMail Project Team
  17.   * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  18.   * @version $Id: squirrelmail_rpc.php 14420 2014-01-01 20:33:20Z pdontthink $
  19.   * @package squirrelmail
  20.   * @since 1.5.2
  21.   *
  22.   */
  23.  
  24. /** This is the squirrelmail_rpc page */
  25. define('PAGE_NAME''squirrelmail_rpc');
  26.  
  27. //FIXME: If we decide to route ALL requests, even normal page
  28. //       requests through this file, need to change page requests
  29. //       to something like this
  30. //http://example.org/squirrelmail/src/squirrelmail_rpc.php?page=read_body&passed_id=47633...
  31. //       This file would then add ".php" to the "page" variable
  32. //       and pass the request on to that page by simply require()ing
  33. //       that page and exiting.
  34. //       Does this present problems, security or otherwise?  What
  35. //       problems are created by the fact that the page request
  36. //       is always the same thing (some parts of the code and some
  37. //       plugins switch functionality based on $PHP_SELF and other
  38. //       $_SERVER variables that look for specific page names -- those
  39. //       can be fixed by looking at the "page" GET argument, but what
  40. //       other issues are created)?  What about plugins?  How would
  41. //       they work in this scheme?  Would they be a lot more difficult 
  42. //       to develop?
  43. //NOTE:  It is not entirely clear if doing the above is even desirable.
  44. //       Initial conversations on the squirrelmail-devel list were 
  45. //       inconclusive.  On one hand, doing so would give us one master
  46. //       file that handles any and all incoming requests, no matter 
  47. //       where they came from or what format/type they are.  On the
  48. //       other, keeping page requests out of this file keeps this file
  49. //       lean and specific to one technology: our RPC interface.
  50.  
  51.  
  52. /**
  53.  * Include the SquirrelMail initialization file.
  54.  */
  55. //FIXME: init.php assumes it is being called by a browser, so some error 
  56. //       conditions are handled by immediately calling error_box() or 
  57. //       otherwise trying to push something to the browser, which should 
  58. //       be avoided at all costs.  This is also pervasive in the whole 
  59. //       core and must be cleaned up entirely before this can be a very
  60. //       functional RPC interface
  61. require('../include/init.php');
  62.  
  63.  
  64.  
  65. //FIXME: do we need to put this list somewhere else?
  66. //FIXME: do we want to use constants instead?  probably not a bad idea, although plugins probably won't, so we still want to try to keep track of the plugin error codes too if possible (new plugin website should help)
  67. /**
  68.   * Known core error codes:
  69.   *
  70.   * 1    - No RPC action was given in request (please use "rpc_action")
  71.   * 2    - RPC action was not understood (perhaps a needed plugin is
  72.   *        not installed and activated?)
  73.   *
  74.   * Known plugin error codes:
  75.   *
  76.   * 500  - Empty Folders plugin empty_folders_purge_trash action failed
  77.   * 501  - Empty Folders plugin empty_folders_purge_all action failed
  78.   * 502  - Empty Folders plugin empty_folders_delete_all action failed
  79.   * 503  - Mark Read plugin mark_read_read_all action failed
  80.   * 504  - Mark Read plugin mark_read_unread_all action failed
  81.   *
  82.   */
  83.  
  84.  
  85.  
  86. /**
  87.   * Get RPC Action (can be in either GET or POST)
  88.   *
  89.   */
  90. if (!sqGetGlobalVar('rpc_action'$rpc_actionSQ_FORM)) {
  91.     sm_rpc_return_error(''1_("No RPC action given")'client'400'Bad Request');
  92. }
  93.  
  94.  
  95.  
  96. /**
  97.   * No matter what our response is, the headers
  98.   * will not change.
  99.   *
  100.   */
  101. $oTemplate->header('Content-Type: text/xml');
  102. $oTemplate->header('Content-Type: application/xml')// required by IE
  103. $oTemplate->header('Pragma: no-cache');
  104. $oTemplate->header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0');
  105. $oTemplate->header('Expires: Sat, 1 Jan 2000 00:00:00 GMT');
  106. //TODO: is this needed? $oTemplate->header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
  107.  
  108.  
  109.  
  110. /**
  111.   * Allow plugins to add their own RPC action
  112.   * or modify behavior of SM core RPC actions...
  113.   *
  114.   * A plugin that handles a custom RPC action must
  115.   * return TRUE to the hook so that it knows that
  116.   * the action was handled and was not an unknown
  117.   * action.  If the action was not handled, the plugin
  118.   * should return FALSE to the hook.
  119.   *
  120.   * Developer note: the $rpc_action parameter is passed
  121.   * in an array in case we can think of more parameters
  122.   * to add in the future.
  123.   *
  124.   * Known users of this hook:
  125.   *    empty_folders
  126.   *    mark_read
  127.   *
  128.   */
  129. $temp array(&$rpc_action);
  130. $handled_by_plugin boolean_hook_function('squirrelmail_rpc'$temp1);
  131.  
  132.  
  133.  
  134. /**
  135.   * Go take care of each RPC action (unless plugin already did)
  136.   *
  137.   */
  138. if (!$handled_by_pluginswitch (strtolower($rpc_action)) {
  139.  
  140.     /**
  141.       * Delete Messages
  142.       *
  143.       */
  144.     case 'delete_messages':
  145.  
  146.         require_once(SM_PATH 'functions/mailbox_display.php');
  147.         require_once(SM_PATH 'functions/imap.php');
  148.  
  149.         if (!sqGetGlobalVar('delete_ids'$delete_idsSQ_FORM)) {
  150.             sm_rpc_return_error($rpc_action99_("No deletion ID given")'client'400'Bad Request');
  151.         }
  152.         $delete_ids explode(','$delete_ids);
  153.         if (!sqGetGlobalVar('mailbox'$mailboxSQ_FORM)) {
  154.             sm_rpc_return_error($rpc_action99_("No mailbox given")'client'400'Bad Request');
  155.         }
  156.         if (sqGetGlobalVar('startMessage'$startMessageSQ_INORDER1)) {
  157.             $startMessage = (int) $startMessage;
  158.         }
  159.         sqGetGlobalVar('what'$whatSQ_FORM0);
  160.         if (sqGetGlobalVar('account'$iAccount,  SQ_GET0)) {
  161.             $iAccount = (int) $iAccount;
  162.         }
  163. //FIXME: need to grab the bypass trash variable here too!  probably other vars...
  164.  
  165. /* FIXME: --- The following code was just experimental/proof-of-concept; the rest 
  166.               of the implementation of this functionality still needs to be done "for real"
  167.         $oImapMessage = new IMAP_Message(0, $mailbox, $startMessage, $what, $iAccount);
  168.         foreach ($delete_ids as $id) {
  169.             $oImapMessage->setUid($id);
  170.             //FIXME: establish constants for $hide values (the 3 below indicates not to show errors, but to return any error string)
  171.             $result = $oImapMessage->deleteMessage(3);
  172.             if ($result !== TRUE) {
  173.                 sm_rpc_return_error($rpc_action, 99, $result, 'server', 500, 'Server Error');
  174.             }
  175.         }
  176. --- */
  177.  
  178.         sm_rpc_return_success();
  179.         //FIXME: Just for testing the line above can be changed to something like this:
  180.         //sm_rpc_return_success($rpc_action, 0, 'Hooray!  Message(s) deleted.  Refresh your message list and make sure.');
  181.         break;
  182.  
  183.  
  184.     /**
  185.       * Default: error out
  186.       *
  187.       */
  188.     default:
  189.         sm_rpc_return_error($rpc_action2_("RPC action not understood")'client'400'Bad Request');
  190.         break;
  191.  
  192. }
  193.  
  194.  
  195.  
  196. /**
  197.   * Returns an error message to the RPC caller and exits
  198.   *
  199.   * NOTE that this function exits and will never return
  200.   *
  201.   * @param string $rpc_action   The RPC action that is being handled
  202.   *                              (OPTIONAL; default attempt to grab from GET/POST)
  203.   * @param int    $error_code   The (application-level) error code for the current
  204.   *                              error condition
  205.   * @param string $error_text   Any error message associated with the error
  206.   *                              condition (OPTIONAL; default empty string)
  207.   * @param string $guilty_party A string indicating the party who caused the
  208.   *                              error: either "client" or "server" (OPTIONAL;
  209.   *                              default unspecified)
  210.   * @param int    $http_status_code When non-zero, this value will be sent to
  211.   *                                  the browser in the HTTP headers as the request
  212.   *                                  status code (OPTIONAL; default not used)
  213.   * @param string $http_status_text A string naming the HTTP status, usually the
  214.   *                                  title of the corresponding status code as
  215.   *                                  found on:
  216.   *                                  http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  217.   *                                  (OPTIONAL; default not used; $http_status_code
  218.   *                                  must also be provided).
  219.   *
  220.   */
  221. function sm_rpc_return_error($rpc_action=NULL$error_code,
  222.                              $error_text=''$guilty_party='',
  223.                              $http_status_code=0$http_status_text=''{
  224.  
  225.     global $oTemplate;
  226.  
  227.     if (is_null($rpc_action)) sqGetGlobalVar('rpc_action'$rpc_actionSQ_FORM);
  228.  
  229.     if ($http_status_code{
  230.        $oTemplate->header('HTTP/1.1 ' $http_status_code ' ' $http_status_text);
  231.        $oTemplate->header('Status: ' $http_status_code ' ' $http_status_text);
  232.     }
  233.  
  234.     $oTemplate->assign('rpc_action',   $rpc_action);
  235.     $oTemplate->assign('error_code',   $error_code);
  236.     $oTemplate->assign('error_text',   $error_text);
  237.     $oTemplate->assign('guilty_party'$guilty_party);
  238.  
  239.     $oTemplate->display('rpc_response_error.tpl');
  240.  
  241.     exit;
  242.  
  243. }
  244.  
  245.  
  246.  
  247. /**
  248.   * Returns a standard success result to the RPC caller and exits
  249.   *
  250.   * NOTE that this function exits and will never return
  251.   *
  252.   * @param string $rpc_action  The RPC action that is being handled
  253.   *                             (OPTIONAL; default attempt to grab from GET/POST)
  254.   * @param int    $result_code The result code (OPTIONAL; default 0)
  255.   * @param string $result_text Any result message (OPTIONAL; default
  256.   *                             empty string)
  257.   *
  258.   */
  259. function sm_rpc_return_success($rpc_action=NULL$result_code=0$result_text=''{
  260.  
  261.     if (is_null($rpc_action)) sqGetGlobalVar('rpc_action'$rpc_actionSQ_FORM);
  262.  
  263.     global $oTemplate;
  264.     $oTemplate->assign('rpc_action'$rpc_action);
  265.     $oTemplate->assign('result_code'$result_code);
  266.     $oTemplate->assign('result_text'$result_text);
  267.  
  268.     $oTemplate->display('rpc_response_success.tpl');
  269.  
  270.     exit;
  271.  
  272. }

Documentation generated on Wed, 30 Jul 2014 04:19:29 +0200 by phpDocumentor 1.4.3