diff --git a/README.md b/README.md index 5ba12f66..77be8cfd 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,9 @@ I'm sebsauvage, webmaster of [sebsauvage.net](http://sebsauvage.net), author of Thanks to [Mitsukarenai](https://github.com/Mitsukarenai) for the inspiration. +Patch : +- Yves ASTIER (Draeli) : PHP optimizations, minor fixes, dynamic brigde list with all stuff behind + Licence === Code is public domain. diff --git a/rss-bridge-flickr-explore.php b/bridges/flickr-explore.php similarity index 86% rename from rss-bridge-flickr-explore.php rename to bridges/flickr-explore.php index e7f153eb..6acfeab4 100644 --- a/rss-bridge-flickr-explore.php +++ b/bridges/flickr-explore.php @@ -1,9 +1,10 @@ returnError('404 Not Found', 'ERROR: could not request Flickr.'); + $html = file_get_html('http://www.flickr.com/explore') or $this->returnError(404, 'could not request Flickr.'); $this->items = Array(); foreach($html->find('span.photo_container') as $element) { $item['uri'] = 'http://flickr.com'.$element->find('a',0)->href; @@ -25,5 +26,4 @@ class RssBridgeFlickrExplore extends RssBridgeAbstractClass } $bridge = new RssBridgeFlickrExplore(); -$bridge->process(); -?> \ No newline at end of file +$bridge->process(); \ No newline at end of file diff --git a/rss-bridge-googlesearch.php b/bridges/googlesearch.php similarity index 78% rename from rss-bridge-googlesearch.php rename to bridges/googlesearch.php index c19a6ca3..9ef0c047 100644 --- a/rss-bridge-googlesearch.php +++ b/bridges/googlesearch.php @@ -1,16 +1,17 @@ returnError('404 Not Found', 'ERROR: no results for this query.'); + $html = file_get_html('http://www.google.com/search?q='.urlencode($request['q']).'&num=100&complete=0&tbs=qdr:y,sbd:1') or $this->returnError(404, 'no results for this query.'); } else { - $this->returnError('400 Bad Request', 'ERROR: You must specify a keyword (?q=...).'); + $this->returnError(400, 'You must specify a keyword (?q=...).'); } $this->items = Array(); foreach($html->find('div[id=ires]',0)->find('li[class=g]') as $element) { @@ -37,5 +38,4 @@ class RssBridgeGoogleSearch extends RssBridgeAbstractClass } $bridge = new RssBridgeGoogleSearch(); -$bridge->process(); -?> \ No newline at end of file +$bridge->process(); \ No newline at end of file diff --git a/rss-bridge-twitter.php b/bridges/twitter.php similarity index 80% rename from rss-bridge-twitter.php rename to bridges/twitter.php index b08ac0d9..8423cef8 100644 --- a/rss-bridge-twitter.php +++ b/bridges/twitter.php @@ -1,9 +1,12 @@ returnError('404 Not Found', 'ERROR: no results for this query.'); + $html = file_get_html('http://twitter.com/search/realtime?q='.urlencode($request['q']).'+include:retweets&src=typd') or $this->returnError(404, 'no results for this query.'); } elseif (isset($request['u'])) { /* user timeline mode */ - $html = file_get_html('http://twitter.com/'.urlencode($request['u'])) or $this->returnError('404 Not Found', 'ERROR: requested username can\'t be found.'); + $html = file_get_html('http://twitter.com/'.urlencode($request['u'])) or $this->returnError(404, 'requested username can\'t be found.'); } else { - $this->returnError('400 Bad Request', 'ERROR: You must specify a keyword (?q=...) or a Twitter username (?u=...).'); + $this->returnError(400, 'You must specify a keyword (?q=...) or a Twitter username (?u=...).'); } $this->items = Array(); foreach($html->find('div.tweet') as $tweet) { @@ -33,8 +36,7 @@ class RssBridgeTwitter extends RssBridgeAbstractClass $this->items[] = $item; } } -} +} $bridge = new RssBridgeTwitter(); -$bridge->process(); -?> \ No newline at end of file +$bridge->process(); \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 00000000..3ef2b8ab --- /dev/null +++ b/index.php @@ -0,0 +1,148 @@ +[1-9][0-9]*)\s?\((?.+)\)(?:\r|\n)#', $commentary, $outComment); // Catch specific information about "use". + if( isset($outComment['args']) && is_array($outComment['args']) ){ + $infos['use'] = array(); + foreach($outComment['args'] as $num => $args){ // Each use + preg_match_all('#(?[a-z]+)="(?.*)"(?:,|$)#U', $args, $outArg); // Catch arguments for current use + if( isset($outArg['name']) ){ + $usePos = $outComment['num'][$num]; // Current use name + if( !isset($infos['use'][$usePos]) ){ // Not information actually for this "use" ? + $infos['use'][$usePos] = array(); + } + + foreach($outArg['name'] as $numArg => $name){ // Each arguments + $infos['use'][$usePos][$name] = $outArg['value'][$numArg]; + } + } + } + } + } + } + + if( isset($infos['name']) ){ // If informations containt at least a name + // $listBridge + $listBridge[$out[1]] = $infos; + } + } + } + closedir($handle); + } + + return $listBridge; +} + +function createNetworkLink($bridgeName, $arguments){ + +} + +if( isset($_REQUEST) && isset($_REQUEST['action']) ){ + switch($_REQUEST['action']){ + case 'create': + if( isset($_REQUEST['bridge']) ){ + unset($_REQUEST['action']); + $bridge = $_REQUEST['bridge']; + unset($_REQUEST['bridge']); + // var_dump($_REQUEST);die; + $pathBridge = PATH_BRIDGES_RELATIVE . $bridge . '.php'; + if( file_exists($pathBridge) ){ + require $pathBridge; + exit(); + } + } + break; + } +} + +$listBridge = searchBridgeInformation(PATH_BRIDGES); +// echo '
';
+// var_dump($listBridge);
+// echo '
'; +?> + + + + + Rss-bridge - Create your own network ! + + + + +
    + $bridgeInformations): ?> +
  • +
    +
    +

    + +

    + 0 ): ?> +
      + $anUse): ?> +
    1. +
      + + + $argDescription): ?> + +
      + + + + + +
      +
    2. + +
    + +
    + + + + + + +
    + +
    +
  • + +
+ + \ No newline at end of file diff --git a/rss-bridge-lib.php b/rss-bridge-lib.php index b4ff7f40..8f7236df 100644 --- a/rss-bridge-lib.php +++ b/rss-bridge-lib.php @@ -7,32 +7,34 @@ ini_set('user_agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0'); date_default_timezone_set('UTC'); error_reporting(0); -//ini_set('display_errors','1'); error_reporting(E_ALL); // For debugging only. +ini_set('display_errors','1'); error_reporting(E_ALL); // For debugging only. define('CACHEDIR','cache/'); // Directory containing cache files. Do not forget trailing slash. +define('CHARSET', 'UTF-8'); +define('SimpleDomLib', 'vendor/simplehtmldom/simple_html_dom.php'); + ob_start(); // Create cache directory if it does not exist. if (!is_dir(CACHEDIR)) { mkdir(CACHEDIR,0705); chmod(CACHEDIR,0705); } // Import DOM library. -if (!file_exists('simple_html_dom.php')) +if (!file_exists(SimpleDomLib)) { - header('HTTP/1.1 500 Internal Server Error'); + header('HTTP/1.1 500 Internal Server Error'); header('Content-Type: text/plain'); - die('"PHP Simple HTML DOM Parser" is missing. Get it from http://simplehtmldom.sourceforge.net/ and place the script "simple_html_dom.php" in the same folder to allow me to work.'); + die('"PHP Simple HTML DOM Parser" is missing. Get it from http://simplehtmldom.sourceforge.net and place the script "simple_html_dom.php" in the same folder to allow me to work.'); } -require_once('simple_html_dom.php'); +require_once(SimpleDomLib); /** * Abstract RSSBridge class on which all bridges are build upon. * It provides utility methods (cache, ATOM feed building...) */ -abstract class RssBridgeAbstractClass -{ +abstract class RssBridgeAbstractClass { /** * $items is an array of dictionnaries. Each subclass must fill this array when collectData() is called. - * eg. $items = Array( Array('uri'=>'http://foo.bar', 'title'=>'My beautiful foobar', 'content'='Hello, world !','timestamp'=>'1375864834'), - * Array('uri'=>'http://toto.com', 'title'=>'Welcome to toto', 'content'='What is this website about ?','timestamp'=>'1375868313') + * eg. $items = array( array('uri'=>'http://foo.bar', 'title'=>'My beautiful foobar', 'content'='Hello, world !','timestamp'=>'1375864834'), + * array('uri'=>'http://toto.com', 'title'=>'Welcome to toto', 'content'='What is this website about ?','timestamp'=>'1375868313') * ) * Keys in dictionnaries: * uri (string;mandatory) = The URI the item points to. @@ -42,82 +44,83 @@ abstract class RssBridgeAbstractClass * Other keys can be added, but will be ignored. * $items will be used to build the ATOM feed, json and other outputs. */ - var $items; + public $items; private $contentType; // MIME type returned to browser. - + /** * Sets the content-type returns to browser. - * Example: $this->setContentType('text/html; charset=UTF-8') + * + * @param string Content-type returns to browser - Example: $this->setContentType('text/html; charset=UTF-8') + * @return this */ - private function setContentType($value) - { + private function setContentType($value){ $this->contentType = $value; header('Content-Type: '.$value); + return $this; } /** * collectData() will be called to ask the bridge to go collect data on the net. * All derived classes must implement this method. * This method must fill $this->items with collected items. - * Input: $request : The incoming request (=$_GET). This can be used or ignored by the bridge. + * @param mixed $request : The incoming request (=$_GET). This can be used or ignored by the bridge. */ abstract protected function collectData($request); /** * Returns a HTTP error to user, with a message. - * Example: $this->returnError('404 Not Found', 'ERROR: no results.'); + * Example: $this->returnError(404, 'no results.'); + * @param integer $code + * @param string $message */ - protected function returnError($code, $message) - { - header("HTTP/1.1 $code"); header('Content-Type: text/plain;charset=UTF-8'); - die($message); + protected function returnError($code, $message){ + $errors = array( + 400 => 'Bad Request', + 404 => 'Not Found', + 501 => 'Not Implemented', + ); + + header('HTTP/1.1 ' . $code . ( isset($errors[$code]) ? ' ' . $errors[$code] : '')); + header('Content-Type: text/plain;charset=' . CHARSET); + die('ERROR : ' . $message); } - + /** * Builds an ATOM feed from $this->items and return it to browser. */ - private function returnATOM() - { - $this->setContentType('application/atom+xml; charset=UTF-8'); + private function returnATOM(){ + $this->setContentType('application/atom+xml; charset=' . CHARSET); + + $https = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '' ); + $httpHost = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''; + $httpInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; + echo ''."\n"; + echo ''.htmlspecialchars($this->bridgeName).''."\n"; - echo 'http'.(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '')."://{$_SERVER['HTTP_HOST']}{$_SERVER['PATH_INFO']}".'/'."\n"; + echo 'http' . $https . '://' . $httpHost . $httpInfo . './'."\n"; echo ''."\n"; // FIXME echo ''."\n"; - echo ''."\n"."\n"; + echo ''."\n"."\n"; foreach($this->items as $item) { echo ''.htmlspecialchars($this->bridgeName).''.htmlspecialchars($this->bridgeURI).''."\n"; echo '<![CDATA['.$item['title'].']]>'."\n"; echo ''."\n"; echo ''.$item['uri'].''."\n"; - if (isset($item['timestamp'])) - { - echo ''.date(DATE_ATOM, $item['timestamp']).''."\n"; - - } - else - { - echo ''."\n"; - } - if (isset($item['content'])) - { - echo ''."\n"; - } - else - { - echo ''."\n"; - } + echo '' . ( isset($item['timestamp']) ? date(DATE_ATOM, $item['timestamp']) : '' ) . ''."\n"; + echo '' . ( isset($item['content']) ? '' : '') . ''."\n"; + // FIXME: Security: Disable Javascript ? echo ''."\n\n"; - } + } + echo ''; } - private function returnHTML() - { - $this->setContentType('text/html; charset=UTF-8'); + private function returnHTML(){ + $this->setContentType('text/html; charset=' . CHARSET); echo ''.htmlspecialchars($this->bridgeName).''; echo ''; echo '

'.htmlspecialchars($this->bridgeName).'

'; @@ -134,8 +137,7 @@ abstract class RssBridgeAbstractClass /** * Builds a JSON string from $this->items and return it to browser. */ - private function returnJSON() - { + private function returnJSON(){ $this->setContentType('application/json'); echo json_encode($this->items); } @@ -143,25 +145,23 @@ abstract class RssBridgeAbstractClass /** * Returns $this->items as raw php data. */ - private function returnPlaintext() - { - $this->setContentType('text/plain;charset=UTF-8'); + private function returnPlaintext(){ + $this->setContentType('text/plain;charset=' . CHARSET); print_r($this->items); } /** * Start processing request and return response to browser. */ - public function process() - { + public function process(){ $this->serveCachedVersion(); // Cache file does not exists or has expired: We re-fetch the results and cache it. - $this->collectData($_GET); - if (empty($this->items)) { $this->returnError('404 Not Found', 'ERROR: no results.'); } + $this->collectData($_REQUEST); - $format = 'atom'; - if (!empty($_GET['format'])) { $format = $_GET['format']; } + if (empty($this->items)) { $this->returnError(404, 'no results.'); } + + $format = isset($_REQUEST['format']) ? $_REQUEST['format'] : 'atom'; switch($format) { case 'plaintext': $this->returnPlaintext(); @@ -179,15 +179,23 @@ abstract class RssBridgeAbstractClass $this->storeReponseInCache(); } + private function getCacheName(){ + if( !isset($_REQUEST) ){ + $this->returnError(501, 'WTF ?'); + } + + $stringToEncode = $_SERVER['REQUEST_URI'] . http_build_query($_REQUEST); + return CACHEDIR.hash('sha1',$stringToEncode).'.cache'; + } + /** * Returns the cached version of current request URI directly to the browser * if it exists and if cache has not expired. * Continues execution no cached version available. */ - private function serveCachedVersion() - { + private function serveCachedVersion(){ // See if cache exists for this request - $cachefile = CACHEDIR.hash('sha1',$_SERVER['REQUEST_URI']).'.cache'; // Cache path and filename + $cachefile = $this->getCacheName(); // Cache path and filename if (file_exists($cachefile)) { // The cache file exists. if (time() - ($this->cacheDuration*60) < filemtime($cachefile)) { // Cache file has not expired. Serve it. $data = json_decode(file_get_contents($cachefile),true); @@ -198,17 +206,16 @@ abstract class RssBridgeAbstractClass } } } - + /** * Stores currently generated page in cache. + * @return this */ - private function storeReponseInCache() - { - $cachefile = CACHEDIR.hash('sha1',$_SERVER['REQUEST_URI']).'.cache'; // Cache path and filename - $data = Array('data'=>ob_get_contents(), 'Content-Type'=>$this->contentType); + private function storeReponseInCache(){ + $cachefile = $this->getCacheName(); // Cache path and filename + $data = array('data'=>ob_get_contents(), 'Content-Type'=>$this->contentType); file_put_contents($cachefile,json_encode($data)); ob_end_flush(); + return $this; } -} - -?> \ No newline at end of file +} \ No newline at end of file