. * */ class OC_API { /** * API authentication levels */ const GUEST_AUTH = 0; const USER_AUTH = 1; const SUBADMIN_AUTH = 2; const ADMIN_AUTH = 3; /** * API Response Codes */ const RESPOND_UNAUTHORISED = 997; const RESPOND_SERVER_ERROR = 996; const RESPOND_NOT_FOUND = 998; const RESPOND_UNKNOWN_ERROR = 999; /** * api actions */ protected static $actions = array(); /** * registers an api call * @param string $method the http method * @param string $url the url to match * @param callable $action the function to run * @param string $app the id of the app registering the call * @param int $authLevel the level of authentication required for the call * @param array $defaults * @param array $requirements */ public static function register($method, $url, $action, $app, $authLevel = OC_API::USER_AUTH, $defaults = array(), $requirements = array()) { $name = strtolower($method).$url; $name = str_replace(array('/', '{', '}'), '_', $name); if(!isset(self::$actions[$name])) { OC::getRouter()->useCollection('ocs'); OC::getRouter()->create($name, $url) ->method($method) ->defaults($defaults) ->requirements($requirements) ->action('OC_API', 'call'); self::$actions[$name] = array(); } self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel); } /** * handles an api call * @param array $parameters */ public static function call($parameters) { // Prepare the request variables if($_SERVER['REQUEST_METHOD'] == 'PUT') { parse_str(file_get_contents("php://input"), $parameters['_put']); } else if($_SERVER['REQUEST_METHOD'] == 'DELETE') { parse_str(file_get_contents("php://input"), $parameters['_delete']); } $name = $parameters['_route']; // Foreach registered action $responses = array(); foreach(self::$actions[$name] as $action) { // Check authentication and availability if(!self::isAuthorised($action)) { $responses[] = array( 'app' => $action['app'], 'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'), ); continue; } if(!is_callable($action['action'])) { $responses[] = array( 'app' => $action['app'], 'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'), ); continue; } // Run the action $responses[] = array( 'app' => $action['app'], 'response' => call_user_func($action['action'], $parameters), ); } $response = self::mergeResponses($responses); $formats = array('json', 'xml'); $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml'; OC_User::logout(); self::respond($response, $format); } /** * merge the returned result objects into one response * @param array $responses */ private static function mergeResponses($responses) { $response = array(); // Sort into shipped and thirdparty $shipped = array( 'succeeded' => array(), 'failed' => array(), ); $thirdparty = array( 'succeeded' => array(), 'failed' => array(), ); foreach($responses as $response) { if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) { if($response['response']->succeeded()) { $shipped['succeeded'][$response['app']] = $response['response']; } else { $shipped['failed'][$response['app']] = $response['response']; } } else { if($response['response']->succeeded()) { $thirdparty['succeeded'][$response['app']] = $response['response']; } else { $thirdparty['failed'][$response['app']] = $response['response']; } } } // Remove any error responses if there is one shipped response that succeeded if(!empty($shipped['succeeded'])) { $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); } else if(!empty($shipped['failed'])) { // Which shipped response do we use if they all failed? // They may have failed for different reasons (different status codes) // Which reponse code should we return? // Maybe any that are not OC_API::RESPOND_SERVER_ERROR $response = reset($shipped['failed']); return $response; } elseif(!empty($thirdparty['failed'])) { // Return the third party failure result $response = reset($thirdparty['failed']); return $response; } else { $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); } // Merge the successful responses $meta = array(); $data = array(); foreach($responses as $app => $response) { if(OC_App::isShipped($app)) { $data = array_merge_recursive($response->getData(), $data); } else { $data = array_merge_recursive($data, $response->getData()); } } $result = new OC_OCS_Result($data, 100); return $result; } /** * authenticate the api call * @param array $action the action details as supplied to OC_API::register() * @return bool */ private static function isAuthorised($action) { $level = $action['authlevel']; switch($level) { case OC_API::GUEST_AUTH: // Anyone can access return true; break; case OC_API::USER_AUTH: // User required return self::loginUser(); break; case OC_API::SUBADMIN_AUTH: // Check for subadmin $user = self::loginUser(); if(!$user) { return false; } else { $subAdmin = OC_SubAdmin::isSubAdmin($user); $admin = OC_User::isAdminUser($user); if($subAdmin || $admin) { return true; } else { return false; } } break; case OC_API::ADMIN_AUTH: // Check for admin $user = self::loginUser(); if(!$user) { return false; } else { return OC_User::isAdminUser($user); } break; default: // oops looks like invalid level supplied return false; break; } } /** * http basic auth * @return string|false (username, or false on failure) */ private static function loginUser(){ $authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; $authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; return OC_User::login($authUser, $authPw) ? $authUser : false; } /** * respond to a call * @param OC_OCS_Result $result * @param string $format the format xml|json */ private static function respond($result, $format='xml') { // Send 401 headers if unauthorised if($result->getStatusCode() === self::RESPOND_UNAUTHORISED) { header('WWW-Authenticate: Basic realm="Authorisation Required"'); header('HTTP/1.0 401 Unauthorized'); } $response = array( 'ocs' => array( 'meta' => $result->getMeta(), 'data' => $result->getData(), ), ); if ($format == 'json') { OC_JSON::encodedPrint($response); } else if ($format == 'xml') { header('Content-type: text/xml; charset=UTF-8'); $writer = new XMLWriter(); $writer->openMemory(); $writer->setIndent( true ); $writer->startDocument(); self::toXML($response, $writer); $writer->endDocument(); echo $writer->outputMemory(true); } } private static function toXML($array, $writer) { foreach($array as $k => $v) { if ($k[0] === '@') { $writer->writeAttribute(substr($k, 1), $v); continue; } else if (is_numeric($k)) { $k = 'element'; } if(is_array($v)) { $writer->startElement($k); self::toXML($v, $writer); $writer->endElement(); } else { $writer->writeElement($k, $v); } } } } > 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <fo:layout-master-set>

    <!-- layout for the first page -->
    <fo:simple-page-master master-name="first"
                  margin-top="1in"
                  margin-bottom="1in"
                  margin-left="1in"
                  margin-right="1in">
      <fo:region-body margin-top="2.5cm" margin-bottom="1.5cm"/>
      <fo:region-before extent="2.5cm"/>
      <fo:region-after extent="1.5cm"/>
    </fo:simple-page-master>


  </fo:layout-master-set>
  <!-- end: defines page layout -->

  <!-- actual layout -->
  <fo:page-sequence master-reference="first">

    <!-- header -->
    <fo:static-content flow-name="xsl-region-before">
      <fo:block text-align="end"
            font-size="8pt"
            font-family="serif"
            line-height="14pt" >
            <fo:basic-link external-destination="http://xml.apache.org/fop"
                           color="rgb(150,150,150)" font-style="italic">
               http://xml.apache.org/fop
            </fo:basic-link>
      </fo:block>
    </fo:static-content>


<fo:flow flow-name="xsl-region-body">

  <fo:block space-after.optimum="3pt" font-family="serif" id="block1">
     FOP is the world's first print formatter driven by XSL formatting
     objects. It is a Java 1.1 application that reads a formatting object
     tree and then turns it into a PDF document. The formatting object
     tree, can be in the form of an XML document (output by an XSLT engine
     like XT or Xalan) or can be passed in memory as a DOM Document or (in
     the case of XT) SAX events.
  </fo:block>

  <fo:block space-after.optimum="12pt" font-family="serif">FOP is part of Apache's XML project. The homepage of FOP is
     <fo:inline font-style="italic" font-family="serif"><fo:basic-link color="blue" external-destination="http://xml.apache.org/fop">http://xml.apache.org/fop</fo:basic-link></fo:inline>
  </fo:block>

<fo:block space-after.optimum="12pt" font-family="serif" font-weight="bold" text-align="center">
align="start"
</fo:block>

<fo:block space-after.optimum="12pt" font-family="serif" text-align="start">
     Apache FOP is the world's first print formatter driven by XSL formatting
     objects. It is a Java 1.1 application that reads a <fo:basic-link internal-destination="block1" color="blue">formatting object</fo:basic-link>
     tree and then turns it into a <fo:basic-link internal-destination="block1" color="blue">PDF document</fo:basic-link>. The formatting object
     tree, can be in the form of an XML <fo:basic-link internal-destination="block1" color="blue">document</fo:basic-link> (output by an XSLT engine
     like XT or Xalan) or can be passed in memory as a DOM Document or (in
     the case of XT) SAX events.

  </fo:block>

<fo:block space-after.optimum="12pt" font-family="serif" font-weight="bold" text-align="center">
align="center"
</fo:block>

<fo:block space-after.optimum="12pt" font-family="serif" text-align="center">
     Apache FOP is the world's first print formatter driven by XSL formatting
     objects. It is a Java 1.1 application that reads a <fo:basic-link internal-destination="block1" color="blue">formatting object</fo:basic-link>
     tree and then turns it into a <fo:basic-link internal-destination="block1" color="blue">PDF document</fo:basic-link>. The formatting object
     tree, can be in the form of an XML <fo:basic-link internal-destination="block1" color="blue">document</fo:basic-link> (output by an XSLT engine
     like XT or Xalan) or can be passed in memory as a DOM Document or (in
     the case of XT) SAX events.

  </fo:block>

<fo:block space-after.optimum="12pt" font-family="serif" font-weight="bold" text-align="center">
align="justify"
</fo:block>

  <fo:block space-after.optimum="12pt" font-family="serif" text-align="justify">
     Apache FOP is the world's first print formatter driven by XSL formatting
     objects. It is a Java 1.1 application that reads a <fo:basic-link internal-destination="block1" color="blue">formatting object</fo:basic-link>
     tree and then turns it into a <fo:basic-link internal-destination="block1" color="blue">PDF document</fo:basic-link>. The formatting object
     tree, can be in the form of an XML <fo:basic-link internal-destination="block1" color="blue">document</fo:basic-link> (output by an XSLT engine
     like XT or Xalan) or can be passed in memory as a DOM Document or (in
     the case of XT) SAX events.

  </fo:block>

<!-- table start -->
    <fo:table>
      <fo:table-column column-width="50mm"/>
      <fo:table-column column-width="50mm"/>
      <fo:table-column column-width="50mm"/>
      <fo:table-body>
        <fo:table-row>
          <fo:table-cell ><fo:block>good</fo:block></fo:table-cell>
          <fo:table-cell ><fo:block>bad</fo:block></fo:table-cell>
          <fo:table-cell ><fo:block><fo:basic-link internal-destination="block1" color="blue">ugly</fo:basic-link></fo:block></fo:table-cell>
        </fo:table-row>
        <fo:table-row>
          <fo:table-cell ><fo:block>nice</fo:block></fo:table-cell>
          <fo:table-cell ><fo:block><fo:basic-link internal-destination="block1" color="blue">dice</fo:basic-link></fo:block></fo:table-cell>
          <fo:table-cell ><fo:block>vice</fo:block></fo:table-cell>
        </fo:table-row>
        <fo:table-row>
          <fo:table-cell ><fo:block>literature</fo:block></fo:table-cell>
          <fo:table-cell ><fo:block>music</fo:block></fo:table-cell>
          <fo:table-cell ><fo:block><fo:basic-link internal-destination="block1" color="blue">art</fo:basic-link></fo:block></fo:table-cell>
        </fo:table-row>
        <fo:table-row>
          <fo:table-cell ><fo:block><fo:basic-link internal-destination="block1" color="blue">java</fo:basic-link></fo:block></fo:table-cell>
          <fo:table-cell ><fo:block>perl</fo:block></fo:table-cell>
          <fo:table-cell ><fo:block>python</fo:block></fo:table-cell>
        </fo:table-row>
      </fo:table-body>
    </fo:table>
    <!-- table end -->

  <fo:block break-before="page" space-after.optimum="12pt" font-family="serif" text-align="start" font-weight="bold">
      Links in different orientations
  </fo:block>

      <fo:block>
        This block container has a different reference orientation.
        <fo:block-container reference-orientation="90" inline-progression-dimension="150pt">
          <fo:block>
            A link applies to the inline parent area that is created
            by the basic-link. This inline area has a trait specifying
            the link.
          </fo:block>
          <fo:block>
            <fo:basic-link external-destination="http://xml.apache.org/fop"
                           color="blue" text-decoration="underline">
               http://xml.apache.org/fop
            </fo:basic-link>
          </fo:block>
        </fo:block-container>
      </fo:block>


</fo:flow>

</fo:page-sequence>
</fo:root>