SHINDIG-1056 by lipeng, BasicRemoteContentTest doesn't depend on static private key...
[shindig.git] / php / src / gadgets / ProxyHandler.php
blobc5008e81c83d66030fbd9eb74334415bc2d03c9e
1 <?php
2 /**
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
21 /**
22 * The ProxyHandler class does the actual proxy'ing work. it deals both with
23 * GET and POST based input, and peforms a request based on the input, headers and
24 * httpmethod params.
27 class ProxyHandler extends ProxyBase {
29 /**
30 * Fetches the content and returns it as-is using the headers as returned
31 * by the remote host.
33 * @param string $url the url to retrieve
35 public function fetch($url) {
36 $url = $this->validateUrl($url);
37 $request = $this->buildRequest($url, 'GET');
38 $request->getOptions()->ignoreCache = $this->context->getIgnoreCache();
39 $result = $this->context->getHttpFetcher()->fetch($request);
40 $httpCode = (int)$result->getHttpCode();
41 $isShockwaveFlash = false;
42 foreach ($result->getResponseHeaders() as $key => $val) {
43 if (! in_array($key, $this->disallowedHeaders)) {
44 header("$key: $val", true);
46 if ($key == 'Content-Type' && strtolower($val) == 'application/x-shockwave-flash') {
47 // We're skipping the content disposition header for flash due to an issue with Flash player 10
48 // This does make some sites a higher value phishing target, but this can be mitigated by
49 // additional referer checks.
50 $isShockwaveFlash = true;
53 if (! $isShockwaveFlash) {
54 header('Content-Disposition: attachment;filename=p.txt');
56 $lastModified = $result->getResponseHeader('Last-Modified') != null ? $result->getResponseHeader('Last-Modified') : gmdate('D, d M Y H:i:s', $result->getCreated()) . ' GMT';
57 $notModified = false;
58 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $lastModified && ! isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
59 $if_modified_since = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
60 // Use the request's Last-Modified, otherwise fall back on our internal time keeping (the time the request was created)
61 $lastModified = strtotime($lastModified);
62 if ($lastModified <= $if_modified_since) {
63 $notModified = true;
66 if ($httpCode == 200) {
67 // only set caching headers if the result was 'OK'
68 $this->setCachingHeaders($lastModified);
69 // was the &gadget=<gadget url> specified in the request? if so parse it and check the rewrite settings
70 if (isset($_GET['gadget'])) {
71 $this->rewriteContent($_GET['gadget'], $result);
74 // If the cached file time is within the refreshInterval params value, return not-modified
75 if ($notModified) {
76 header('HTTP/1.0 304 Not Modified', true);
77 header('Content-Length: 0', true);
78 } else {
79 // then echo the content
80 echo $result->getResponseContent();
84 private function rewriteContent($gadgetUrl, RemoteContentRequest &$result) {
85 try {
86 // At the moment we're only able to rewrite CSS files, so check the content type and/or the file extension before rewriting
87 $headers = $result->getResponseHeaders();
88 $isCss = false;
89 if (isset($headers['Content-Type']) && strtolower($headers['Content-Type'] == 'text/csss')) {
90 $isCss = true;
91 } else {
92 $ext = substr($_GET['url'], strrpos($_GET['url'], '.') + 1);
93 $isCss = strtolower($ext) == 'css';
95 if ($isCss) {
96 $gadget = $this->createGadget($gadgetUrl);
97 $rewrite = $gadget->gadgetSpec->rewrite;
98 if (is_array($rewrite)) {
99 $contentRewriter = new ContentRewriter($this->context, $gadget);
100 $result->setResponseContent($contentRewriter->rewriteCSS($result->getResponseContent()));
103 } catch (Exception $e) {
104 // ignore, not being able to rewrite anything isn't fatal
110 * Uses the GadgetFactory to instrance the specified gadget
112 * @param string $gadgetUrl
114 private function createGadget($gadgetUrl) {
115 // Only include these files if appropiate, else it would slow down the entire proxy way to much
116 require_once 'src/gadgets/GadgetSpecParser.php';
117 require_once 'src/gadgets/GadgetBlacklist.php';
118 require_once 'src/gadgets/sample/BasicGadgetBlacklist.php';
119 require_once 'src/gadgets/GadgetContext.php';
120 require_once 'src/gadgets/GadgetFactory.php';
121 require_once 'src/gadgets/GadgetSpec.php';
122 require_once 'src/gadgets/Gadget.php';
123 require_once 'src/gadgets/GadgetException.php';
124 require_once 'src/gadgets/rewrite/GadgetRewriter.php';
125 require_once 'src/gadgets/rewrite/DomRewriter.php';
126 require_once 'src/gadgets/rewrite/ContentRewriter.php';
127 // make sure our context returns the gadget url and not the proxied document url
128 $this->context->setUrl($gadgetUrl);
129 // and create & return the gadget
130 $gadgetSpecFactory = new GadgetFactory($this->context, null);
131 $gadget = $gadgetSpecFactory->createGadget();
132 return $gadget;