/** * Appends data from <Preload> elements to make them available to * gadgets.io. * * @param gadget */ private function appendPreloads(Gadget $gadget, GadgetContext $context) { $resp = array(); $gadgetSigner = Config::get('security_token_signer'); $gadgetSigner = new $gadgetSigner(); $token = ''; try { $token = $context->extractAndValidateToken($gadgetSigner); } catch (Exception $e) { $token = ''; // no token given, safe to ignore } $unsignedRequests = $unsignedContexts = array(); $signedRequests = array(); foreach ($gadget->getPreloads() as $preload) { try { if (($preload->getAuth() == Auth::$NONE || $token != null) && (count($preload->getViews()) == 0 || in_array($context->getView(), $preload->getViews()))) { $request = new RemoteContentRequest($preload->getHref()); $request->createRemoteContentRequestWithUri($preload->getHref()); $request->getOptions()->ownerSigned = $preload->isSignOwner(); $request->getOptions()->viewerSigned = $preload->isSignViewer(); switch (strtoupper(trim($preload->getAuth()))) { case "NONE": // Unify all unsigned requests to one single multi request $unsignedRequests[] = $request; $unsignedContexts[] = $context; break; case "SIGNED": // Unify all signed requests to one single multi request $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file")); $fetcher = $signingFetcherFactory->getSigningFetcher(new BasicRemoteContentFetcher(), $token); $req = $fetcher->signRequest($preload->getHref(), $request->getMethod()); $req->setNotSignedUri($preload->getHref()); $signedRequests[] = $req; break; default: @ob_end_clean(); header("HTTP/1.0 500 Internal Server Error", true); echo "<html><body><h1>" . "500 - Internal Server Error" . "</h1></body></html>"; die; } } } catch (Exception $e) { throw new Exception($e); } } if (count($unsignedRequests)) { try { $brc = new BasicRemoteContent(); $responses = $brc->multiFetch($unsignedRequests, $unsignedContexts); foreach ($responses as $response) { $resp[$response->getUrl()] = array('body' => $response->getResponseContent(), 'rc' => $response->getHttpCode()); } } catch (Exception $e) { throw new Exception($e); } } if (count($signedRequests)) { try { $fetcher = $signingFetcherFactory->getSigningFetcher(new BasicRemoteContentFetcher(), $token); $responses = $fetcher->multiFetchRequest($signedRequests); foreach ($responses as $response) { $resp[$response->getNotSignedUrl()] = array('body' => $response->getResponseContent(), 'rc' => $response->getHttpCode()); } } catch (Exception $e) { throw new Exception($e); } } $resp = count($resp) ? json_encode($resp) : "{}"; return "gadgets.io.preloaded_ = " . $resp . ";\n"; }
/** * Fetches all remote resources simultaniously using a multiFetchRequest to optimize rendering time. * * The preloads will be json_encoded to their gadget document injection format, and the locales will * be reduced to only the GadgetContext->getLocale matching entries. * * @param Gadget $gadget * @param GadgetContext $context */ protected function fetchResources(Gadget &$gadget) { $contextLocale = $this->context->getLocale(); $unsignedRequests = $signedRequests = array(); foreach ($gadget->gadgetSpec->locales as $key => $locale) { // Only fetch the locales that match the current context's language and country if ($locale['country'] == 'all' && $locale['lang'] == 'all' || $locale['lang'] == $contextLocale['lang'] && $locale['country'] == 'all' || $locale['lang'] == $contextLocale['lang'] && $locale['country'] == $contextLocale['country']) { if (!empty($locale['messages'])) { $transformedUrl = RemoteContentRequest::transformRelativeUrl($locale['messages'], $this->context->getUrl()); if (!$transformedUrl) { // remove any locales that are not applicable to this context unset($gadget->gadgetSpec->locales[$key]); continue; } else { $gadget->gadgetSpec->locales[$key]['messages'] = $transformedUrl; } // locale matches the current context, add it to the requests queue $request = new RemoteContentRequest($gadget->gadgetSpec->locales[$key]['messages']); $request->createRemoteContentRequestWithUri($gadget->gadgetSpec->locales[$key]['messages']); $request->getOptions()->ignoreCache = $this->context->getIgnoreCache(); $unsignedRequests[] = $request; } } else { // remove any locales that are not applicable to this context unset($gadget->gadgetSpec->locales[$key]); } } if (!$gadget->gadgetContext instanceof MetadataGadgetContext) { // Add preloads to the request queue foreach ($gadget->getPreloads() as $preload) { if (!empty($preload['href'])) { $request = new RemoteContentRequest($preload['href']); if (!empty($preload['authz']) && $preload['authz'] == 'SIGNED') { if ($this->token == '') { throw new GadgetException("Signed preloading requested, but no valid security token set"); } $request = new RemoteContentRequest($preload['href']); $request->setAuthType(RemoteContentRequest::$AUTH_SIGNED); $request->setNotSignedUri($preload['href']); $request->setToken($this->token); $request->getOptions()->ignoreCache = $this->context->getIgnoreCache(); if (strcasecmp($preload['signViewer'], 'false') == 0) { $request->getOptions()->viewerSigned = false; } if (strcasecmp($preload['signOwner'], 'false') == 0) { $request->getOptions()->ownerSigned = false; } $signedRequests[] = $request; } else { $request->createRemoteContentRequestWithUri($preload['href']); $request->getOptions()->ignoreCache = $this->context->getIgnoreCache(); $unsignedRequests[] = $request; } } } // Add template libraries to the request queue if ($gadget->gadgetSpec->templatesRequireLibraries) { foreach ($gadget->gadgetSpec->templatesRequireLibraries as $key => $libraryUrl) { $request = new RemoteContentRequest($libraryUrl); $transformedUrl = RemoteContentRequest::transformRelativeUrl($libraryUrl, $this->context->getUrl()); if (!$transformedUrl) { continue; } else { $gadget->gadgetSpec->templatesRequireLibraries[$key] = $transformedUrl; } $request->createRemoteContentRequestWithUri($gadget->gadgetSpec->templatesRequireLibraries[$key]); $request->getOptions()->ignoreCache = $this->context->getIgnoreCache(); $unsignedRequests[] = $request; } } } // Perform the non-signed requests $responses = array(); if (count($unsignedRequests)) { $brc = new BasicRemoteContent(); $resps = $brc->multiFetch($unsignedRequests); foreach ($resps as $response) { $responses[$response->getUrl()] = array('body' => $response->getResponseContent(), 'rc' => $response->getHttpCode()); } } // Perform the signed requests if (count($signedRequests)) { $signingFetcherFactory = new SigningFetcherFactory(Config::get("private_key_file")); $remoteFetcherClass = Config::get('remote_content_fetcher'); $remoteFetcher = new $remoteFetcherClass(); $remoteContent = new BasicRemoteContent($remoteFetcher, $signingFetcherFactory); $resps = $remoteContent->multiFetch($signedRequests); foreach ($resps as $response) { $responses[$response->getNotSignedUrl()] = array('body' => $response->getResponseContent(), 'rc' => $response->getHttpCode()); } } // assign the results to the gadget locales and preloads (using the url as the key) foreach ($gadget->gadgetSpec->locales as $key => $locale) { if (!empty($locale['messages']) && isset($responses[$locale['messages']]) && $responses[$locale['messages']]['rc'] == 200) { $gadget->gadgetSpec->locales[$key]['messageBundle'] = $this->parseMessageBundle($responses[$locale['messages']]['body']); } } if (!$gadget->gadgetContext instanceof MetadataGadgetContext) { $preloads = array(); foreach ($gadget->gadgetSpec->preloads as $key => $preload) { if (!empty($preload['href']) && isset($responses[$preload['href']]) && $responses[$preload['href']]['rc'] == 200) { $preloads[] = array_merge(array('id' => $preload['href']), $responses[$preload['href']]); } } $gadget->gadgetSpec->preloads = $preloads; if ($gadget->gadgetSpec->templatesRequireLibraries) { $requiredLibraries = array(); foreach ($gadget->gadgetSpec->templatesRequireLibraries as $key => $libraryUrl) { if (isset($responses[$libraryUrl]) && $responses[$libraryUrl]['rc'] == 200) { $requiredLibraries[$libraryUrl] = $responses[$libraryUrl]['body']; } } $gadget->gadgetSpec->templatesRequireLibraries = $requiredLibraries; } } }
/** * Tests Gadget->getPreloads() */ public function testGetPreloads() { $this->Gadget->preloads = array(0 => 'A', 1 => 'B'); $this->assertEquals(array(0 => 'A', 1 => 'B'), $this->Gadget->getPreloads()); }