More informations on our website: [wallabag.org](http://wallabag.org)
## License
-Copyright © 2010-2013 Nicolas Lœuillet <nicolas@loeuillet.org>
+Copyright © 2010-2014 Nicolas Lœuillet <nicolas@loeuillet.org>
This work is free. You can redistribute it and/or modify it under the
terms of the Do What The Fuck You Want To Public License, Version 2,
as published by Sam Hocevar. See the COPYING file for more details.
*/\r
class FeedItem\r
{\r
- private $elements = array(); //Collection of feed elements\r
- private $version;\r
- \r
- /**\r
- * Constructor \r
- * \r
- * @param contant (RSS1/RSS2/ATOM) RSS2 is default. \r
- */ \r
- function __construct($version = RSS2)\r
- { \r
- $this->version = $version;\r
- }\r
+ private $elements = array(); //Collection of feed elements\r
+ private $version;\r
+ \r
+ /**\r
+ * Constructor \r
+ * \r
+ * @param contant (RSS1/RSS2/ATOM) RSS2 is default. \r
+ */ \r
+ function __construct($version = RSS2)\r
+ { \r
+ $this->version = $version;\r
+ }\r
\r
- /**\r
- * Set element (overwrites existing elements with $elementName)\r
- * \r
- * @access public\r
- * @param srting The tag name of an element\r
- * @param srting The content of tag\r
- * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
- * @return void\r
- */\r
- public function setElement($elementName, $content, $attributes = null)\r
- {\r
- if (isset($this->elements[$elementName])) {\r
- unset($this->elements[$elementName]);\r
- }\r
- $this->addElement($elementName, $content, $attributes);\r
- } \r
- \r
- /**\r
- * Add an element to elements array\r
- * \r
- * @access public\r
- * @param srting The tag name of an element\r
- * @param srting The content of tag\r
- * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
- * @return void\r
- */\r
- public function addElement($elementName, $content, $attributes = null)\r
- {\r
- $i = 0;\r
- if (isset($this->elements[$elementName])) {\r
- $i = count($this->elements[$elementName]);\r
- } else {\r
- $this->elements[$elementName] = array();\r
- }\r
- $this->elements[$elementName][$i]['name'] = $elementName;\r
- $this->elements[$elementName][$i]['content'] = $content;\r
- $this->elements[$elementName][$i]['attributes'] = $attributes;\r
- }\r
- \r
- /**\r
- * Set multiple feed elements from an array. \r
- * Elements which have attributes cannot be added by this method\r
- * \r
- * @access public\r
- * @param array array of elements in 'tagName' => 'tagContent' format.\r
- * @return void\r
- */\r
- public function addElementArray($elementArray)\r
- {\r
- if(! is_array($elementArray)) return;\r
- foreach ($elementArray as $elementName => $content) \r
- {\r
- $this->addElement($elementName, $content);\r
- }\r
- }\r
- \r
- /**\r
- * Return the collection of elements in this feed item\r
- * \r
- * @access public\r
- * @return array\r
- */\r
- public function getElements()\r
- {\r
- return $this->elements;\r
- }\r
- \r
- // Wrapper functions ------------------------------------------------------\r
- \r
- /**\r
- * Set the 'dscription' element of feed item\r
- * \r
- * @access public\r
- * @param string The content of 'description' element\r
- * @return void\r
- */\r
- public function setDescription($description) \r
- {\r
- $tag = 'description'; \r
- $this->setElement($tag, $description);\r
- }\r
- \r
- /**\r
- * @desc Set the 'title' element of feed item\r
- * @access public\r
- * @param string The content of 'title' element\r
- * @return void\r
- */\r
- public function setTitle($title) \r
- {\r
- $this->setElement('title', $title); \r
- }\r
- \r
- /**\r
- * Set the 'date' element of feed item\r
- * \r
- * @access public\r
- * @param string The content of 'date' element\r
- * @return void\r
- */\r
- public function setDate($date) \r
- {\r
- if(! is_numeric($date))\r
- {\r
- $date = strtotime($date);\r
- }\r
+ /**\r
+ * Set element (overwrites existing elements with $elementName)\r
+ * \r
+ * @access public\r
+ * @param srting The tag name of an element\r
+ * @param srting The content of tag\r
+ * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
+ * @return void\r
+ */\r
+ public function setElement($elementName, $content, $attributes = null)\r
+ {\r
+ if (isset($this->elements[$elementName])) {\r
+ unset($this->elements[$elementName]);\r
+ }\r
+ $this->addElement($elementName, $content, $attributes);\r
+ } \r
+ \r
+ /**\r
+ * Add an element to elements array\r
+ * \r
+ * @access public\r
+ * @param srting The tag name of an element\r
+ * @param srting The content of tag\r
+ * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
+ * @return void\r
+ */\r
+ public function addElement($elementName, $content, $attributes = null)\r
+ {\r
+ $i = 0;\r
+ if (isset($this->elements[$elementName])) {\r
+ $i = count($this->elements[$elementName]);\r
+ } else {\r
+ $this->elements[$elementName] = array();\r
+ }\r
+ $this->elements[$elementName][$i]['name'] = $elementName;\r
+ $this->elements[$elementName][$i]['content'] = $content;\r
+ $this->elements[$elementName][$i]['attributes'] = $attributes;\r
+ }\r
+ \r
+ /**\r
+ * Set multiple feed elements from an array. \r
+ * Elements which have attributes cannot be added by this method\r
+ * \r
+ * @access public\r
+ * @param array array of elements in 'tagName' => 'tagContent' format.\r
+ * @return void\r
+ */\r
+ public function addElementArray($elementArray)\r
+ {\r
+ if(! is_array($elementArray)) return;\r
+ foreach ($elementArray as $elementName => $content) \r
+ {\r
+ $this->addElement($elementName, $content);\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Return the collection of elements in this feed item\r
+ * \r
+ * @access public\r
+ * @return array\r
+ */\r
+ public function getElements()\r
+ {\r
+ return $this->elements;\r
+ }\r
+ \r
+ // Wrapper functions ------------------------------------------------------\r
+ \r
+ /**\r
+ * Set the 'dscription' element of feed item\r
+ * \r
+ * @access public\r
+ * @param string The content of 'description' element\r
+ * @return void\r
+ */\r
+ public function setDescription($description) \r
+ {\r
+ $this->setElement('description', $description);\r
+ }\r
+ \r
+ /**\r
+ * @desc Set the 'title' element of feed item\r
+ * @access public\r
+ * @param string The content of 'title' element\r
+ * @return void\r
+ */\r
+ public function setTitle($title) \r
+ {\r
+ $this->setElement('title', $title); \r
+ }\r
+ \r
+ /**\r
+ * Set the 'date' element of feed item\r
+ * \r
+ * @access public\r
+ * @param string The content of 'date' element\r
+ * @return void\r
+ */\r
+ public function setDate($date) \r
+ {\r
+ if(! is_numeric($date))\r
+ {\r
+ $date = strtotime($date);\r
+ }\r
\r
- if($this->version == RSS2) \r
- {\r
- $tag = 'pubDate';\r
- $value = date(DATE_RSS, $date);\r
- }\r
- else \r
- {\r
- $tag = 'dc:date';\r
- $value = date("Y-m-d", $date);\r
- }\r
- \r
- $this->setElement($tag, $value); \r
- }\r
- \r
- /**\r
- * Set the 'link' element of feed item\r
- * \r
- * @access public\r
- * @param string The content of 'link' element\r
- * @return void\r
- */\r
- public function setLink($link) \r
- {\r
- if($this->version == RSS2 || $this->version == RSS1)\r
- {\r
- $this->setElement('link', $link);\r
- $this->setElement('guid', $link);\r
- }\r
- else\r
- {\r
- $this->setElement('link','',array('href'=>$link));\r
- $this->setElement('id', FeedWriter::uuid($link,'urn:uuid:'));\r
- } \r
- \r
- }\r
- \r
- /**\r
- * Set the 'encloser' element of feed item\r
- * For RSS 2.0 only\r
- * \r
- * @access public\r
- * @param string The url attribute of encloser tag\r
- * @param string The length attribute of encloser tag\r
- * @param string The type attribute of encloser tag\r
- * @return void\r
- */\r
- public function setEncloser($url, $length, $type)\r
- {\r
- $attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);\r
- $this->setElement('enclosure','',$attributes);\r
- }\r
- \r
+ if($this->version == RSS2) \r
+ {\r
+ $tag = 'pubDate';\r
+ $value = date(DATE_RSS, $date);\r
+ }\r
+ else \r
+ {\r
+ $tag = 'dc:date';\r
+ $value = date("Y-m-d", $date);\r
+ }\r
+ \r
+ $this->setElement($tag, $value); \r
+ }\r
+ \r
+ /**\r
+ * Set the 'link' element of feed item\r
+ * \r
+ * @access public\r
+ * @param string The content of 'link' element\r
+ * @return void\r
+ */\r
+ public function setLink($link) \r
+ {\r
+ if($this->version == RSS2 || $this->version == RSS1)\r
+ {\r
+ $this->setElement('link', $link);\r
+ $this->setElement('guid', $link);\r
+ }\r
+ else\r
+ {\r
+ $this->setElement('link','',array('href'=>$link));\r
+ $this->setElement('id', FeedWriter::uuid($link,'urn:uuid:'));\r
+ } \r
+ \r
+ }\r
+\r
+ /**\r
+ * Set the 'source' element of feed item\r
+ * \r
+ * @access public\r
+ * @param string The content of 'source' element\r
+ * @return void\r
+ */\r
+ public function setSource($link) \r
+ {\r
+ $this->setElement('source', $link);\r
+ }\r
+ \r
+ /**\r
+ * Set the 'encloser' element of feed item\r
+ * For RSS 2.0 only\r
+ * \r
+ * @access public\r
+ * @param string The url attribute of encloser tag\r
+ * @param string The length attribute of encloser tag\r
+ * @param string The type attribute of encloser tag\r
+ * @return void\r
+ */\r
+ public function setEncloser($url, $length, $type)\r
+ {\r
+ $attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);\r
+ $this->setElement('enclosure','',$attributes);\r
+ }\r
+ \r
} // end of class FeedItem\r
-?>\r
+?>
\ No newline at end of file
*/\r
class FeedWriter\r
{\r
- private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html\r
- private $hubs = array(); // PubSubHubbub hubs\r
- private $channels = array(); // Collection of channel elements\r
- private $items = array(); // Collection of items as object of FeedItem class.\r
- private $data = array(); // Store some other version wise data\r
- private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA\r
- private $xsl = null; // stylesheet to render RSS (used by Chrome)\r
- private $json = null; // JSON object\r
-\r
- private $version = null;\r
-\r
- /**\r
- * Constructor\r
- *\r
- * @param constant the version constant (RSS2 or JSON).\r
- */\r
- function __construct($version = RSS2)\r
- {\r
- $this->version = $version;\r
-\r
- // Setting default value for assential channel elements\r
- $this->channels['title'] = $version . ' Feed';\r
- $this->channels['link'] = 'http://www.ajaxray.com/blog';\r
-\r
- //Tag names to encode in CDATA\r
- $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');\r
- }\r
-\r
- public function setFormat($format) {\r
- $this->version = $format;\r
- }\r
-\r
- // Start # public functions ---------------------------------------------\r
-\r
- /**\r
- * Set a channel element\r
- * @access public\r
- * @param srting name of the channel tag\r
- * @param string content of the channel tag\r
- * @return void\r
- */\r
- public function setChannelElement($elementName, $content)\r
- {\r
- $this->channels[$elementName] = $content ;\r
- }\r
-\r
- /**\r
- * Set multiple channel elements from an array. Array elements\r
- * should be 'channelName' => 'channelContent' format.\r
- *\r
- * @access public\r
- * @param array array of channels\r
- * @return void\r
- */\r
- public function setChannelElementsFromArray($elementArray)\r
- {\r
- if(! is_array($elementArray)) return;\r
- foreach ($elementArray as $elementName => $content)\r
- {\r
- $this->setChannelElement($elementName, $content);\r
- }\r
- }\r
-\r
- /**\r
- * Genarate the actual RSS/JSON file\r
- *\r
- * @access public\r
- * @return void\r
- */\r
- public function genarateFeed()\r
- {\r
- if ($this->version == RSS2) {\r
-// header('Content-type: text/xml; charset=UTF-8');\r
- // this line prevents Chrome 20 from prompting download\r
- // used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss\r
-// header('X-content-type-options: nosniff');\r
- } elseif ($this->version == JSON) {\r
-// header('Content-type: application/json; charset=UTF-8');\r
- $this->json = new stdClass();\r
- } elseif ($this->version == JSONP) {\r
-// header('Content-type: application/javascript; charset=UTF-8');\r
- $this->json = new stdClass();\r
- }\r
- $this->printHead();\r
- $this->printChannels();\r
- $this->printItems();\r
- $this->printTale();\r
- if ($this->version == JSON || $this->version == JSONP) {\r
- echo json_encode($this->json);\r
- }\r
- }\r
-\r
- /**\r
- * Create a new FeedItem.\r
- *\r
- * @access public\r
- * @return object instance of FeedItem class\r
- */\r
- public function createNewItem()\r
- {\r
- $Item = new FeedItem($this->version);\r
- return $Item;\r
- }\r
-\r
- /**\r
- * Add a FeedItem to the main class\r
- *\r
- * @access public\r
- * @param object instance of FeedItem class\r
- * @return void\r
- */\r
- public function addItem($feedItem)\r
- {\r
- $this->items[] = $feedItem;\r
- }\r
-\r
- // Wrapper functions -------------------------------------------------------------------\r
-\r
- /**\r
- * Set the 'title' channel element\r
- *\r
- * @access public\r
- * @param srting value of 'title' channel tag\r
- * @return void\r
- */\r
- public function setTitle($title)\r
- {\r
- $this->setChannelElement('title', $title);\r
- }\r
-\r
- /**\r
- * Add a hub to the channel element\r
- *\r
- * @access public\r
- * @param string URL\r
- * @return void\r
- */\r
- public function addHub($hub)\r
- {\r
- $this->hubs[] = $hub;\r
- }\r
-\r
- /**\r
- * Set XSL URL\r
- *\r
- * @access public\r
- * @param string URL\r
- * @return void\r
- */\r
- public function setXsl($xsl)\r
- {\r
- $this->xsl = $xsl;\r
- }\r
-\r
- /**\r
- * Set self URL\r
- *\r
- * @access public\r
- * @param string URL\r
- * @return void\r
- */\r
- public function setSelf($self)\r
- {\r
- $this->self = $self;\r
- }\r
-\r
- /**\r
- * Set the 'description' channel element\r
- *\r
- * @access public\r
- * @param srting value of 'description' channel tag\r
- * @return void\r
- */\r
- public function setDescription($desciption)\r
- {\r
- $tag = ($this->version == ATOM)? 'subtitle' : 'description';\r
- $this->setChannelElement($tag, $desciption);\r
- }\r
-\r
- /**\r
- * Set the 'link' channel element\r
- *\r
- * @access public\r
- * @param srting value of 'link' channel tag\r
- * @return void\r
- */\r
- public function setLink($link)\r
- {\r
- $this->setChannelElement('link', $link);\r
- }\r
-\r
- /**\r
- * Set the 'image' channel element\r
- *\r
- * @access public\r
- * @param srting title of image\r
- * @param srting link url of the imahe\r
- * @param srting path url of the image\r
- * @return void\r
- */\r
- public function setImage($title, $link, $url)\r
- {\r
- $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));\r
- }\r
-\r
- // End # public functions ----------------------------------------------\r
-\r
- // Start # private functions ----------------------------------------------\r
-\r
- /**\r
- * Prints the xml and rss namespace\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- private function printHead()\r
- {\r
- if ($this->version == RSS2)\r
- {\r
- $out = '<?xml version="1.0" encoding="utf-8"?>'."\n";\r
- if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL;\r
- $out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">' . PHP_EOL;\r
- echo $out;\r
- }\r
- elseif ($this->version == JSON || $this->version == JSONP)\r
- {\r
- $this->json->rss = array('@attributes' => array('version' => '2.0'));\r
- }\r
- }\r
-\r
- /**\r
- * Closes the open tags at the end of file\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- private function printTale()\r
- {\r
- if ($this->version == RSS2)\r
- {\r
- echo '</channel>',PHP_EOL,'</rss>';\r
- }\r
- // do nothing for JSON\r
- }\r
-\r
- /**\r
- * Creates a single node as xml format\r
- *\r
- * @access private\r
- * @param string name of the tag\r
- * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format\r
- * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
- * @return string formatted xml tag\r
- */\r
- private function makeNode($tagName, $tagContent, $attributes = null)\r
- {\r
- if ($this->version == RSS2)\r
- {\r
- $nodeText = '';\r
- $attrText = '';\r
- if (is_array($attributes))\r
- {\r
- foreach ($attributes as $key => $value)\r
- {\r
- $attrText .= " $key=\"$value\" ";\r
- }\r
- }\r
- $nodeText .= "<{$tagName}{$attrText}>";\r
- if (is_array($tagContent))\r
- {\r
- foreach ($tagContent as $key => $value)\r
- {\r
- $nodeText .= $this->makeNode($key, $value);\r
- }\r
- }\r
- else\r
- {\r
- //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);\r
- $nodeText .= htmlspecialchars($tagContent);\r
- }\r
- //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";\r
- $nodeText .= "</$tagName>";\r
- return $nodeText . PHP_EOL;\r
- }\r
- elseif ($this->version == JSON || $this->version == JSONP)\r
- {\r
- $tagName = (string)$tagName;\r
- $tagName = strtr($tagName, ':', '_');\r
- $node = null;\r
- if (!$tagContent && is_array($attributes) && count($attributes))\r
- {\r
- $node = array('@attributes' => $this->json_keys($attributes));\r
- } else {\r
- if (is_array($tagContent)) {\r
- $node = $this->json_keys($tagContent);\r
- } else {\r
- $node = $tagContent;\r
- }\r
- }\r
- return $node;\r
- }\r
- return ''; // should not get here\r
- }\r
-\r
- private function json_keys(array $array) {\r
- $new = array();\r
- foreach ($array as $key => $val) {\r
- if (is_string($key)) $key = strtr($key, ':', '_');\r
- if (is_array($val)) {\r
- $new[$key] = $this->json_keys($val);\r
- } else {\r
- $new[$key] = $val;\r
- }\r
- }\r
- return $new;\r
- }\r
-\r
- /**\r
- * @desc Print channels\r
- * @access private\r
- * @return void\r
- */\r
- private function printChannels()\r
- {\r
- //Start channel tag\r
- if ($this->version == RSS2) {\r
- echo '<channel>' . PHP_EOL;\r
- // add hubs\r
- foreach ($this->hubs as $hub) {\r
- //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));\r
- echo '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;\r
- }\r
- // add self\r
- if (isset($this->self)) {\r
- //echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));\r
- echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;\r
- }\r
- //Print Items of channel\r
- foreach ($this->channels as $key => $value)\r
- {\r
- echo $this->makeNode($key, $value);\r
- }\r
- } elseif ($this->version == JSON || $this->version == JSONP) {\r
- $this->json->rss['channel'] = (object)$this->json_keys($this->channels);\r
- }\r
- }\r
-\r
- /**\r
- * Prints formatted feed items\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- private function printItems()\r
- {\r
- foreach ($this->items as $item) {\r
- $itemElements = $item->getElements();\r
-\r
- echo $this->startItem();\r
-\r
- if ($this->version == JSON || $this->version == JSONP) {\r
- $json_item = array();\r
- }\r
-\r
- foreach ($itemElements as $thisElement) {\r
- foreach ($thisElement as $instance) {\r
- if ($this->version == RSS2) {\r
- echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\r
- } elseif ($this->version == JSON || $this->version == JSONP) {\r
- $_json_node = $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\r
- if (count($thisElement) > 1) {\r
- $json_item[strtr($instance['name'], ':', '_')][] = $_json_node;\r
- } else {\r
- $json_item[strtr($instance['name'], ':', '_')] = $_json_node;\r
- }\r
- }\r
- }\r
- }\r
- echo $this->endItem();\r
- if ($this->version == JSON || $this->version == JSONP) {\r
- if (count($this->items) > 1) {\r
- $this->json->rss['channel']->item[] = $json_item;\r
- } else {\r
- $this->json->rss['channel']->item = $json_item;\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Make the starting tag of channels\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- private function startItem()\r
- {\r
- if ($this->version == RSS2)\r
- {\r
- echo '<item>' . PHP_EOL;\r
- }\r
- // nothing for JSON\r
- }\r
-\r
- /**\r
- * Closes feed item tag\r
- *\r
- * @access private\r
- * @return void\r
- */\r
- private function endItem()\r
- {\r
- if ($this->version == RSS2)\r
- {\r
- echo '</item>' . PHP_EOL;\r
- }\r
- // nothing for JSON\r
- }\r
-\r
- // End # private functions ----------------------------------------------\r
+ private $self = null; // self URL - http://feed2.w3.org/docs/warning/MissingAtomSelfLink.html\r
+ private $hubs = array(); // PubSubHubbub hubs\r
+ private $channels = array(); // Collection of channel elements\r
+ private $items = array(); // Collection of items as object of FeedItem class.\r
+ private $data = array(); // Store some other version wise data\r
+ private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA\r
+ private $xsl = null; // stylesheet to render RSS (used by Chrome)\r
+ private $json = null; // JSON object\r
+\r
+ private $version = null;\r
+\r
+ /**\r
+ * Constructor\r
+ *\r
+ * @param constant the version constant (RSS2 or JSON).\r
+ */\r
+ function __construct($version = RSS2)\r
+ {\r
+ $this->version = $version;\r
+\r
+ // Setting default value for assential channel elements\r
+ $this->channels['title'] = $version . ' Feed';\r
+ $this->channels['link'] = 'http://www.ajaxray.com/blog';\r
+\r
+ //Tag names to encode in CDATA\r
+ $this->CDATAEncoding = array('description', 'content:encoded', 'content', 'subtitle', 'summary');\r
+ }\r
+\r
+ public function setFormat($format) {\r
+ $this->version = $format;\r
+ }\r
+\r
+ // Start # public functions ---------------------------------------------\r
+\r
+ /**\r
+ * Set a channel element\r
+ * @access public\r
+ * @param srting name of the channel tag\r
+ * @param string content of the channel tag\r
+ * @return void\r
+ */\r
+ public function setChannelElement($elementName, $content)\r
+ {\r
+ $this->channels[$elementName] = $content ;\r
+ }\r
+\r
+ /**\r
+ * Set multiple channel elements from an array. Array elements\r
+ * should be 'channelName' => 'channelContent' format.\r
+ *\r
+ * @access public\r
+ * @param array array of channels\r
+ * @return void\r
+ */\r
+ public function setChannelElementsFromArray($elementArray)\r
+ {\r
+ if(! is_array($elementArray)) return;\r
+ foreach ($elementArray as $elementName => $content)\r
+ {\r
+ $this->setChannelElement($elementName, $content);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Genarate the actual RSS/JSON file\r
+ *\r
+ * @access public\r
+ * @return void\r
+ */\r
+ public function genarateFeed()\r
+ {\r
+ if ($this->version == RSS2) {\r
+// header('Content-type: text/xml; charset=UTF-8');\r
+ // this line prevents Chrome 20 from prompting download\r
+ // used by Google: https://news.google.com/news/feeds?ned=us&topic=b&output=rss\r
+// header('X-content-type-options: nosniff');\r
+ } elseif ($this->version == JSON) {\r
+// header('Content-type: application/json; charset=UTF-8');\r
+ $this->json = new stdClass();\r
+ } elseif ($this->version == JSONP) {\r
+// header('Content-type: application/javascript; charset=UTF-8');\r
+ $this->json = new stdClass();\r
+ }\r
+ $this->printHead();\r
+ $this->printChannels();\r
+ $this->printItems();\r
+ $this->printTale();\r
+ if ($this->version == JSON || $this->version == JSONP) {\r
+ echo json_encode($this->json);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Create a new FeedItem.\r
+ *\r
+ * @access public\r
+ * @return object instance of FeedItem class\r
+ */\r
+ public function createNewItem()\r
+ {\r
+ $Item = new FeedItem($this->version);\r
+ return $Item;\r
+ }\r
+\r
+ /**\r
+ * Add a FeedItem to the main class\r
+ *\r
+ * @access public\r
+ * @param object instance of FeedItem class\r
+ * @return void\r
+ */\r
+ public function addItem($feedItem)\r
+ {\r
+ $this->items[] = $feedItem;\r
+ }\r
+\r
+ // Wrapper functions -------------------------------------------------------------------\r
+\r
+ /**\r
+ * Set the 'title' channel element\r
+ *\r
+ * @access public\r
+ * @param srting value of 'title' channel tag\r
+ * @return void\r
+ */\r
+ public function setTitle($title)\r
+ {\r
+ $this->setChannelElement('title', $title);\r
+ }\r
+\r
+ /**\r
+ * Add a hub to the channel element\r
+ *\r
+ * @access public\r
+ * @param string URL\r
+ * @return void\r
+ */\r
+ public function addHub($hub)\r
+ {\r
+ $this->hubs[] = $hub;\r
+ }\r
+\r
+ /**\r
+ * Set XSL URL\r
+ *\r
+ * @access public\r
+ * @param string URL\r
+ * @return void\r
+ */\r
+ public function setXsl($xsl)\r
+ {\r
+ $this->xsl = $xsl;\r
+ }\r
+\r
+ /**\r
+ * Set self URL\r
+ *\r
+ * @access public\r
+ * @param string URL\r
+ * @return void\r
+ */\r
+ public function setSelf($self)\r
+ {\r
+ $this->self = $self;\r
+ }\r
+\r
+ /**\r
+ * Set the 'description' channel element\r
+ *\r
+ * @access public\r
+ * @param srting value of 'description' channel tag\r
+ * @return void\r
+ */\r
+ public function setDescription($description)\r
+ {\r
+ $this->setChannelElement('description', $description);\r
+ }\r
+\r
+ /**\r
+ * Set the 'link' channel element\r
+ *\r
+ * @access public\r
+ * @param srting value of 'link' channel tag\r
+ * @return void\r
+ */\r
+ public function setLink($link)\r
+ {\r
+ $this->setChannelElement('link', $link);\r
+ }\r
+\r
+ /**\r
+ * Set the 'image' channel element\r
+ *\r
+ * @access public\r
+ * @param srting title of image\r
+ * @param srting link url of the imahe\r
+ * @param srting path url of the image\r
+ * @return void\r
+ */\r
+ public function setImage($title, $link, $url)\r
+ {\r
+ $this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));\r
+ }\r
+\r
+ // End # public functions ----------------------------------------------\r
+\r
+ // Start # private functions ----------------------------------------------\r
+\r
+ /**\r
+ * Prints the xml and rss namespace\r
+ *\r
+ * @access private\r
+ * @return void\r
+ */\r
+ private function printHead()\r
+ {\r
+ if ($this->version == RSS2)\r
+ {\r
+ $out = '<?xml version="1.0" encoding="utf-8"?>'."\n";\r
+ if ($this->xsl) $out .= '<?xml-stylesheet type="text/xsl" href="'.htmlspecialchars($this->xsl).'"?>' . PHP_EOL;\r
+ $out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">' . PHP_EOL;\r
+ echo $out;\r
+ }\r
+ elseif ($this->version == JSON || $this->version == JSONP)\r
+ {\r
+ $this->json->rss = array('@attributes' => array('version' => '2.0'));\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Closes the open tags at the end of file\r
+ *\r
+ * @access private\r
+ * @return void\r
+ */\r
+ private function printTale()\r
+ {\r
+ if ($this->version == RSS2)\r
+ {\r
+ echo '</channel>',PHP_EOL,'</rss>';\r
+ }\r
+ // do nothing for JSON\r
+ }\r
+\r
+ /**\r
+ * Creates a single node as xml format\r
+ *\r
+ * @access private\r
+ * @param string name of the tag\r
+ * @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format\r
+ * @param array Attributes(if any) in 'attrName' => 'attrValue' format\r
+ * @return string formatted xml tag\r
+ */\r
+ private function makeNode($tagName, $tagContent, $attributes = null)\r
+ {\r
+ if ($this->version == RSS2)\r
+ {\r
+ $nodeText = '';\r
+ $attrText = '';\r
+ if (is_array($attributes))\r
+ {\r
+ foreach ($attributes as $key => $value)\r
+ {\r
+ $attrText .= " $key=\"$value\" ";\r
+ }\r
+ }\r
+ $nodeText .= "<{$tagName}{$attrText}>";\r
+ if (is_array($tagContent))\r
+ {\r
+ foreach ($tagContent as $key => $value)\r
+ {\r
+ $nodeText .= $this->makeNode($key, $value);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);\r
+ $nodeText .= htmlspecialchars($tagContent);\r
+ }\r
+ //$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";\r
+ $nodeText .= "</$tagName>";\r
+ return $nodeText . PHP_EOL;\r
+ }\r
+ elseif ($this->version == JSON || $this->version == JSONP)\r
+ {\r
+ $tagName = (string)$tagName;\r
+ $tagName = strtr($tagName, ':', '_');\r
+ $node = null;\r
+ if (!$tagContent && is_array($attributes) && count($attributes))\r
+ {\r
+ $node = array('@attributes' => $this->json_keys($attributes));\r
+ } else {\r
+ if (is_array($tagContent)) {\r
+ $node = $this->json_keys($tagContent);\r
+ } else {\r
+ $node = $tagContent;\r
+ }\r
+ }\r
+ return $node;\r
+ }\r
+ return ''; // should not get here\r
+ }\r
+\r
+ private function json_keys(array $array) {\r
+ $new = array();\r
+ foreach ($array as $key => $val) {\r
+ if (is_string($key)) $key = strtr($key, ':', '_');\r
+ if (is_array($val)) {\r
+ $new[$key] = $this->json_keys($val);\r
+ } else {\r
+ $new[$key] = $val;\r
+ }\r
+ }\r
+ return $new;\r
+ }\r
+\r
+ /**\r
+ * @desc Print channels\r
+ * @access private\r
+ * @return void\r
+ */\r
+ private function printChannels()\r
+ {\r
+ //Start channel tag\r
+ if ($this->version == RSS2) {\r
+ echo '<channel>' . PHP_EOL;\r
+ // add hubs\r
+ foreach ($this->hubs as $hub) {\r
+ //echo $this->makeNode('link', '', array('rel'=>'hub', 'href'=>$hub, 'xmlns'=>'http://www.w3.org/2005/Atom'));\r
+ echo '<link rel="hub" href="'.htmlspecialchars($hub).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;\r
+ }\r
+ // add self\r
+ if (isset($this->self)) {\r
+ //echo $this->makeNode('link', '', array('rel'=>'self', 'href'=>$this->self, 'xmlns'=>'http://www.w3.org/2005/Atom'));\r
+ echo '<link rel="self" href="'.htmlspecialchars($this->self).'" xmlns="http://www.w3.org/2005/Atom" />' . PHP_EOL;\r
+ }\r
+ //Print Items of channel\r
+ foreach ($this->channels as $key => $value)\r
+ {\r
+ echo $this->makeNode($key, $value);\r
+ }\r
+ } elseif ($this->version == JSON || $this->version == JSONP) {\r
+ $this->json->rss['channel'] = (object)$this->json_keys($this->channels);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Prints formatted feed items\r
+ *\r
+ * @access private\r
+ * @return void\r
+ */\r
+ private function printItems()\r
+ {\r
+ foreach ($this->items as $item) {\r
+ $itemElements = $item->getElements();\r
+\r
+ echo $this->startItem();\r
+\r
+ if ($this->version == JSON || $this->version == JSONP) {\r
+ $json_item = array();\r
+ }\r
+\r
+ foreach ($itemElements as $thisElement) {\r
+ foreach ($thisElement as $instance) {\r
+ if ($this->version == RSS2) {\r
+ echo $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\r
+ } elseif ($this->version == JSON || $this->version == JSONP) {\r
+ $_json_node = $this->makeNode($instance['name'], $instance['content'], $instance['attributes']);\r
+ if (count($thisElement) > 1) {\r
+ $json_item[strtr($instance['name'], ':', '_')][] = $_json_node;\r
+ } else {\r
+ $json_item[strtr($instance['name'], ':', '_')] = $_json_node;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ echo $this->endItem();\r
+ if ($this->version == JSON || $this->version == JSONP) {\r
+ if (count($this->items) > 1) {\r
+ $this->json->rss['channel']->item[] = $json_item;\r
+ } else {\r
+ $this->json->rss['channel']->item = $json_item;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Make the starting tag of channels\r
+ *\r
+ * @access private\r
+ * @return void\r
+ */\r
+ private function startItem()\r
+ {\r
+ if ($this->version == RSS2)\r
+ {\r
+ echo '<item>' . PHP_EOL;\r
+ }\r
+ // nothing for JSON\r
+ }\r
+\r
+ /**\r
+ * Closes feed item tag\r
+ *\r
+ * @access private\r
+ * @return void\r
+ */\r
+ private function endItem()\r
+ {\r
+ if ($this->version == RSS2)\r
+ {\r
+ echo '</item>' . PHP_EOL;\r
+ }\r
+ // nothing for JSON\r
+ }\r
+\r
+ // End # private functions ----------------------------------------------\r
}
\ No newline at end of file
}
else {
$sql = '
- CREATE TABLE tags (
+ CREATE TABLE IF NOT EXISTS tags (
id bigserial primary key,
value varchar(255) NOT NULL
);
}
else {
$sql = '
- CREATE TABLE tags_entries (
+ CREATE TABLE IF NOT EXISTS tags_entries (
id bigserial primary key,
entry_id integer NOT NULL,
tag_id integer NOT NULL
$sql_limit = "LIMIT ".$limit." OFFSET 0";
}
- $sql = "SELECT * FROM entries WHERE (content = '' OR content IS NULL) AND user_id=? ORDER BY id " . $sql_limit;
+ $sql = "SELECT * FROM entries WHERE (content = '' OR content IS NULL) AND title LIKE 'Untitled - Import%' AND user_id=? ORDER BY id " . $sql_limit;
$query = $this->executeQuery($sql, array($user_id));
$entries = $query->fetchAll();
}
public function retrieveUnfetchedEntriesCount($user_id) {
- $sql = "SELECT count(*) FROM entries WHERE (content = '' OR content IS NULL) AND user_id=?";
+ $sql = "SELECT count(*) FROM entries WHERE (content = '' OR content IS NULL) AND title LIKE 'Untitled - Import%' AND user_id=?";
$query = $this->executeQuery($sql, array($user_id));
list($count) = $query->fetch();
$id = null;
}
else {
- $id = intval($this->getLastId( (STORAGE == 'postgres') ? 'users_id_seq' : '' ));
+ $id = intval($this->getLastId( (STORAGE == 'postgres') ? 'entries_id_seq' : '') );
}
return $id;
}
public function getLastId($column = '') {
return $this->getHandle()->lastInsertId($column);
}
-
+
public function search($term, $user_id, $limit = '') {
$search = '%'.$term.'%';
$sql_action = "SELECT * FROM entries WHERE user_id=? AND (content LIKE ? OR title LIKE ? OR url LIKE ?) "; //searches in content, title and URL
$body = $content['rss']['channel']['item']['description'];
// clean content from prevent xss attack
- $config = HTMLPurifier_Config::createDefault();
- $config->set('Cache.SerializerPath', CACHE);
- $purifier = new HTMLPurifier($config);
+ $purifier = $this->getPurifier();
$title = $purifier->purify($title);
$body = $purifier->purify($body);
define('IMPORT_LIMIT', 5);
}
if (!defined('IMPORT_DELAY')) {
- define('IMPORT_DELAY', 5);
+ define('IMPORT_DELAY', 5);
}
if ( isset($_FILES['file']) ) {
+ Tools::logm('Import stated: parsing file');
+
// assume, that file is in json format
$str_data = file_get_contents($_FILES['file']['tmp_name']);
$data = json_decode($str_data, true);
$read = 0;
foreach (array('ol','ul') as $list) {
foreach ($html->find($list) as $ul) {
- foreach ($ul->find('li') as $li) {
- $tmpEntry = array();
- $a = $li->find('a');
- $tmpEntry['url'] = $a[0]->href;
- $tmpEntry['tags'] = $a[0]->tags;
- $tmpEntry['is_read'] = $read;
- if ($tmpEntry['url']) {
- $data[] = $tmpEntry;
- }
- }
- # the second <ol/ul> is for read links
- $read = ((sizeof($data) && $read)?0:1);
+ foreach ($ul->find('li') as $li) {
+ $tmpEntry = array();
+ $a = $li->find('a');
+ $tmpEntry['url'] = $a[0]->href;
+ $tmpEntry['tags'] = $a[0]->tags;
+ $tmpEntry['is_read'] = $read;
+ if ($tmpEntry['url']) {
+ $data[] = $tmpEntry;
+ }
+ }
+ # the second <ol/ul> is for read links
+ $read = ((sizeof($data) && $read)?0:1);
}
}
}
$data[] = $record;
foreach ($record as $record2) {
if (is_array($record2)) {
- $data[] = $record2;
+ $data[] = $record2;
}
}
}
}
- $i = 0; //counter for articles inserted
+ $urlsInserted = array(); //urls of articles inserted
foreach ($data as $record) {
$url = trim( isset($record['article__url']) ? $record['article__url'] : (isset($record['url']) ? $record['url'] : '') );
- if ( $url ) {
+ if ( $url and !in_array($url, $urlsInserted) ) {
$title = (isset($record['title']) ? $record['title'] : _('Untitled - Import - ').'</a> <a href="./?import">'._('click to finish import').'</a><a>');
$body = (isset($record['content']) ? $record['content'] : '');
$isRead = (isset($record['is_read']) ? intval($record['is_read']) : (isset($record['archive'])?intval($record['archive']):0));
//insert new record
$id = $this->store->add($url, $title, $body, $this->user->getId(), $isFavorite, $isRead);
if ( $id ) {
- //increment no of records inserted
- $i++;
+ $urlsInserted[] = $url; //add
+
if ( isset($record['tags']) && trim($record['tags']) ) {
- //@TODO: set tags
+ //@TODO: set tags
}
}
}
}
+ $i = sizeof($urlsInserted);
if ( $i > 0 ) {
$this->messages->add('s', _('Articles inserted: ').$i._('. Please note, that some may be marked as "read".'));
}
+ Tools::logm('Import of articles finished: '.$i.' articles added (w/o content if not provided).');
}
//file parsing finished here
if ( $recordsDownloadRequired == 0 ) {
//nothing to download
$this->messages->add('s', _('Import finished.'));
+ Tools::logm('Import finished completely');
Tools::redirect();
}
else {
//if just inserted - don't download anything, download will start in next reload
if ( !isset($_FILES['file']) ) {
//download next batch
+ Tools::logm('Fetching next batch of articles...');
$items = $this->store->retrieveUnfetchedEntries($this->user->getId(), IMPORT_LIMIT);
- $config = HTMLPurifier_Config::createDefault();
- $config->set('Cache.SerializerPath', CACHE);
- $purifier = new HTMLPurifier($config);
+ $purifier = $this->getPurifier();
foreach ($items as $item) {
- $url = new Url(base64_encode($item['url']));
- $content = Tools::getPageContent($url);
+ $url = new Url(base64_encode($item['url']));
+ Tools::logm('Fetching article '.$item['id']);
+ $content = Tools::getPageContent($url);
- $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
- $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
+ $title = (($content['rss']['channel']['item']['title'] != '') ? $content['rss']['channel']['item']['title'] : _('Untitled'));
+ $body = (($content['rss']['channel']['item']['description'] != '') ? $content['rss']['channel']['item']['description'] : _('Undefined'));
- //clean content to prevent xss attack
- $title = $purifier->purify($title);
- $body = $purifier->purify($body);
+ //clean content to prevent xss attack
+ $title = $purifier->purify($title);
+ $body = $purifier->purify($body);
- $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
+ $this->store->updateContentAndTitle($item['id'], $title, $body, $this->user->getId());
+ Tools::logm('Article '.$item['id'].' updated.');
}
}
* export poche entries in json
* @return json all poche entries
*/
- public function export()
- {
- $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
- header('Content-Disposition: attachment; filename='.$filename);
-
- $entries = $this->store->retrieveAll($this->user->getId());
- echo $this->tpl->render('export.twig', array(
- 'export' => Tools::renderJson($entries),
- ));
- Tools::logm('export view');
+ public function export() {
+ $filename = "wallabag-export-".$this->user->getId()."-".date("Y-m-d").".json";
+ header('Content-Disposition: attachment; filename='.$filename);
+
+ $entries = $this->store->retrieveAll($this->user->getId());
+ echo $this->tpl->render('export.twig', array(
+ 'export' => Tools::renderJson($entries),
+ ));
+ Tools::logm('export view');
}
/**
* @param string $which 'prod' or 'dev'
* @return string latest $which version
*/
- private function getPocheVersion($which = 'prod')
- {
- $cache_file = CACHE . '/' . $which;
- $check_time = time();
-
- # checks if the cached version file exists
- if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 86400 ))) {
- $version = file_get_contents($cache_file);
- $check_time = filemtime($cache_file);
- } else {
- $version = file_get_contents('http://static.wallabag.org/versions/' . $which);
- file_put_contents($cache_file, $version, LOCK_EX);
- }
- return array($version, $check_time);
+ private function getPocheVersion($which = 'prod') {
+ $cache_file = CACHE . '/' . $which;
+ $check_time = time();
+
+ # checks if the cached version file exists
+ if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 86400 ))) {
+ $version = file_get_contents($cache_file);
+ $check_time = filemtime($cache_file);
+ } else {
+ $version = file_get_contents('http://static.wallabag.org/versions/' . $which);
+ file_put_contents($cache_file, $version, LOCK_EX);
+ }
+ return array($version, $check_time);
}
public function generateToken()
{
- if (ini_get('open_basedir') === '') {
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- echo 'This is a server using Windows!';
- // alternative to /dev/urandom for Windows
- $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
- } else {
- $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
- }
- }
- else {
- $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
+ if (ini_get('open_basedir') === '') {
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ echo 'This is a server using Windows!';
+ // alternative to /dev/urandom for Windows
+ $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
+ } else {
+ $token = substr(base64_encode(file_get_contents('/dev/urandom', false, null, 0, 20)), 0, 15);
}
+ }
+ else {
+ $token = substr(base64_encode(uniqid(mt_rand(), true)), 0, 20);
+ }
- $token = str_replace('+', '', $token);
- $this->store->updateUserConfig($this->user->getId(), 'token', $token);
- $currentConfig = $_SESSION['poche_user']->config;
- $currentConfig['token'] = $token;
- $_SESSION['poche_user']->setConfig($currentConfig);
- Tools::redirect();
+ $token = str_replace('+', '', $token);
+ $this->store->updateUserConfig($this->user->getId(), 'token', $token);
+ $currentConfig = $_SESSION['poche_user']->config;
+ $currentConfig['token'] = $token;
+ $_SESSION['poche_user']->setConfig($currentConfig);
+ Tools::redirect();
}
public function generateFeeds($token, $user_id, $tag_id, $type = 'home')
foreach ($entries as $entry) {
$newItem = $feed->createNewItem();
$newItem->setTitle($entry['title']);
+ $newItem->setSource(Tools::getPocheUrl() . '?view=view&id=' . $entry['id']);
$newItem->setLink($entry['url']);
$newItem->setDate(time());
$newItem->setDescription($entry['content']);
$this->messages->add('s', _('Cache deleted.'));
Tools::redirect();
}
+
+ /**
+ * return new purifier object with actual config
+ */
+ protected function getPurifier() {
+ $config = HTMLPurifier_Config::createDefault();\r
+ $config->set('Cache.SerializerPath', CACHE);\r
+ $config->set('HTML.SafeIframe', true);\r
+ $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%'); //allow YouTube and Vimeo$purifier = new HTMLPurifier($config);
+\r
+ return new HTMLPurifier($config);
+ }
}
return $scriptname;
}
+ $host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']));
+
return 'http' . ($https ? 's' : '') . '://'
- . $_SERVER["HTTP_HOST"] . $serverport . $scriptname;
+ . $host . $serverport . $scriptname;
}
public static function redirect($url = '')
* @license http://www.wtfpl.net/ see COPYING file
*/
-define ('POCHE', '1.6.0');
+define ('POCHE', '1.6.1');
require 'check_setup.php';
require_once 'inc/poche/global.inc.php';
msgid ""
msgstr ""
-"Project-Id-Version: \n"
+"Project-Id-Version: wallabag 1.6.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 18:33+0300\n"
"PO-Revision-Date: \n"
-"Last-Translator: Maryana <mariroz@mr.lviv.ua>\n"
+"Last-Translator: Gilles WITTEZAELE <gilles.wittezaele@laposte.net>\n"
"Language-Team: \n"
-"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
-"X-Poedit-Basepath: .\n"
-"X-Poedit-SourceCharset: utf-8\n"
-"X-Generator: Poedit 1.5.7\n"
-"X-Poedit-SearchPath-0: /home/mariroz/_DEV/web/wallabag/wallabag-master-testing\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Generator: Poedit 1.6.4\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Language: fr_FR\n"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, un système open source de lecture différé"
msgid "login failed: user doesn't exist"
-msgstr "identification échouée : l'utilisateur n'existe pas"
+msgstr "échec de l'identification : cet utilisateur n'existe pas"
msgid "return home"
msgstr "retour à l'accueil"
msgstr "Sauvegarde des articles"
msgid "There are several ways to save an article:"
-msgstr "Il y a plusieurs façons de sauver un article :"
+msgstr "Il y a plusieurs façons d'enregistrer un article :"
msgid "read the documentation"
msgstr "lisez la documentation"
msgid "download the extension"
-msgstr "télécharger l'extension"
+msgstr "téléchargez l'extension"
msgid "via F-Droid"
msgstr "via F-Droid"
msgstr "via Google PlayStore"
msgid "download the application"
-msgstr "télécharger l'application"
+msgstr "téléchargez l'application"
msgid "By filling this field"
msgstr "En remplissant ce champ"
msgid "Feeds"
msgstr "Flux"
-msgid "Your feed token is currently empty and must first be generated to enable feeds. Click <a href='?feed&action=generate'>here to generate it</a>."
-msgstr "Votre jeton de flux est actuellement vide doit d'abord être généré pour activer les flux. Cliquez <a href='?feed&action=generate'>ici</a> pour le générer."
+msgid ""
+"Your feed token is currently empty and must first be generated to enable "
+"feeds. Click <a href='?feed&action=generate'>here to generate it</a>."
+msgstr ""
+"Votre jeton de flux est actuellement vide et doit d'abord être généré pour "
+"activer les flux. Cliquez <a href='?feed&action=generate'>ici</a> pour "
+"le générer."
msgid "Unread feed"
msgstr "Flux des non lus"
msgid "Your user id:"
msgstr "Votre ID utilisateur :"
-msgid "You can regenerate your token: <a href='?feed&action=generate'>generate!</a>."
-msgstr "Vous pouvez regénérer votre jeton : <a href='?feed&action=generate'>génération !</a>."
+msgid ""
+"You can regenerate your token: <a href='?feed&action=generate'>generate!"
+"</a>."
+msgstr ""
+"Vous pouvez regénérer votre jeton : <a href='?feed&"
+"action=generate'>génération !</a>."
msgid "Change your theme"
msgstr "Changer votre thème"
msgid "Import"
msgstr "Importer"
-msgid "Please execute the import script locally as it can take a very long time."
-msgstr "Merci d'exécuter l'import en local car cela peut prendre du temps."
+msgid ""
+"Please execute the import script locally as it can take a very long time."
+msgstr ""
+"Merci d'exécuter le script d'importation en local car cela peut prendre du "
+"temps."
msgid "More info in the official documentation:"
msgstr "Plus d'infos dans la documentation officielle :"
msgstr "(le fichier %s doit être présent sur le serveur)"
msgid "Import from Readability"
-msgstr "Import depuis Readability"
+msgstr "Importer depuis Readability"
msgid "Import from Instapaper"
-msgstr "Import depuis Instapaper"
+msgstr "Importer depuis Instapaper"
msgid "Import from wallabag"
-msgstr "Import depuis wallabag"
+msgstr "Importer depuis wallabag"
msgid "Export your wallabag data"
msgstr "Exporter vos données de wallabag"
msgid "plop"
msgstr "plop"
-msgid "You can <a href='wallabag_compatibility_test.php'>check your configuration here</a>."
-msgstr "Vous pouvez vérifier votre configuration <a href='wallabag_compatibility_test.php'>ici</a>."
+msgid ""
+"You can <a href='wallabag_compatibility_test.php'>check your configuration "
+"here</a>."
+msgstr ""
+"Vous pouvez vérifier votre configuration <a "
+"href='wallabag_compatibility_test.php'>ici</a>."
msgid "favoris"
msgstr "favoris"
msgid "install your wallabag"
msgstr "installez votre wallabag"
-msgid "wallabag is still not installed. Please fill the below form to install it. Don't hesitate to <a href='http://doc.wallabag.org/'>read the documentation on wallabag website</a>."
-msgstr "wallabag n'est pas encore installé. Merci de remplir le formulaire suivant pour l'installer. N'hésitez pas à <a href='http://doc.wallabag.org'>lire la documentation sur le site de wallabag</a>."
+msgid ""
+"wallabag is still not installed. Please fill the below form to install it. "
+"Don't hesitate to <a href='http://doc.wallabag.org/'>read the documentation "
+"on wallabag website</a>."
+msgstr ""
+"wallabag n'est pas encore installé. Merci de remplir le formulaire suivant "
+"pour l'installer. N'hésitez pas à <a href='http://doc.wallabag.org'>lire la "
+"documentation sur le site de wallabag</a>."
msgid "Login"
msgstr "Nom d'utilisateur"
msgstr "Se connecter à wallabag"
msgid "you are in demo mode, some features may be disabled."
-msgstr "vous êtes en mode démo, certaines fonctionnalités peuvent être désactivées."
+msgstr ""
+"vous êtes en mode démo, certaines fonctionnalités peuvent être désactivées."
msgid "Username"
msgstr "Nom d'utilisateur"
msgstr "tags :"
msgid "Edit tags"
-msgstr "Editer les tags"
+msgstr "Modifier les tags"
msgid "save link!"
-msgstr "sauver le lien !"
+msgstr "enregistrer le lien !"
msgid "powered by"
msgstr "propulsé par"
msgstr "tweet"
msgid "email"
-msgstr "ee-mail"
+msgstr "e-mail"
msgid "this article appears wrong?"
msgstr "cet article s'affiche mal ?"
msgstr "Aucun lien n'est disponible ici !"
msgid "Poching a link"
-msgstr "Sauver un lien"
+msgstr "Enregistrer un lien"
msgid "by filling this field"
msgstr "en remplissant ce champ"
msgstr "une version de développement plus récente est disponible."
msgid "Please execute the import script locally, it can take a very long time."
-msgstr "Merci d'exécuter l'import en local car cela peut prendre du temps."
+msgstr ""
+"Merci d'exécuter le script d'importation en local car cela peut prendre du "
+"temps."
msgid "More infos in the official doc:"
msgstr "Plus d'infos dans la documentation officielle :"
msgid "import from Pocket"
-msgstr "import depuis Pocket"
+msgstr "importation depuis Pocket"
msgid "import from Readability"
-msgstr "import depuis Readability"
+msgstr "importation depuis Readability"
msgid "import from Instapaper"
-msgstr "import depuis Instapaper"
+msgstr "importation depuis Instapaper"
msgid "estimated reading time :"
msgstr "temps de lecture estimé :"
msgid "your password has been updated"
msgstr "votre mot de passe a été mis à jour"
-msgid "the two fields have to be filled & the password must be the same in the two fields"
-msgstr "les deux champs doivent être remplis & le mot de passe doit être le même dans les deux"
+msgid ""
+"the two fields have to be filled & the password must be the same in the two "
+"fields"
+msgstr ""
+"les deux champs doivent être remplis & le mot de passe doit être le même "
+"dans les deux"
msgid "still using the \""
msgstr "utilise encore \""
msgstr "ce thème ne semble pas installé"
msgid "you have changed your theme preferences"
-msgstr "vous avez changez vos préférences de thème"
+msgstr "vous avez changé vos préférences de thème"
msgid "that language does not seem to be installed"
msgstr "cette langue ne semble pas être installée"
msgstr "vous avez changé vos préférences de langue"
msgid "login failed: you have to fill all fields"
-msgstr "identification échouée : vous devez remplir tous les champs"
+msgstr "échec de l'identification : vous devez remplir tous les champs"
msgid "welcome to your wallabag"
msgstr "bienvenue dans votre wallabag"
msgid "login failed: bad login or password"
-msgstr "identification échouée : mauvais identifiant ou mot de passe"
+msgstr "échec de l'identification : mauvais identifiant ou mot de passe"
msgid "import from instapaper completed"
-msgstr "Import depuis Instapaper complété"
+msgstr "Importation depuis Instapaper complété"
msgid "import from pocket completed"
-msgstr "Import depuis Pocket complété"
+msgstr "Importation depuis Pocket complété"
msgid "import from Readability completed. "
-msgstr "Import depuis Readability complété"
+msgstr "Importation depuis Readability complété"
msgid "import from Poche completed. "
-msgstr "Import depuis Pocket complété"
+msgstr "Importation depuis Pocket complété"
msgid "Unknown import provider."
-msgstr "Fournisseur d'import inconnu."
+msgstr "Format d'importation inconnu."
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr "Fichier inc/poche/define.inc.php incomplet, merci de définir \""
msgstr "Ne peut pas trouver \""
msgid "Uh, there is a problem while generating feeds."
-msgstr "Ih, il y a un problème lors de la génération des flux."
+msgstr "Hum, il y a un problème lors de la génération des flux."
msgid "Cache deleted."
msgstr "Cache effacé."
<script src="{{ poche_url }}themes/{{theme}}/js/jquery.cookie.js"></script>
<script src="{{ poche_url }}themes/{{theme}}/js/init.js"></script>
<script src="{{ poche_url }}themes/default/js/saveLink.js"></script>
+ <script src="{{ poche_url }}themes/default/js/popupForm.js"></script>
<script src="{{ poche_url }}themes/{{theme}}/js/closeMessage.js"></script>
-<div id="search-form" class="messages info">
+<div id="search-form" class="messages info">
<form method="get" action="index.php">
- <input type="hidden" name="view" value="search"></input>
+ <input type="hidden" name="view" value="search"></input>
<label><a href="javascript: void(null);" id="search-form-close">X</a>{% trans "Search" %}</label> : <input type="text" name="search" />
- <input id="submit-search" type="submit" value="{% trans "Search" %} !"></input>
+ <input id="submit-search" type="submit" value="{% trans "Search" %} !"></input>
</form>
-</div>
-<script type="text/javascript">
- $(document).ready(function() {
-
- $("#search-form").hide();
-
- $("#search").click(function(){
- $("#search-form").toggle();
- $("#search").toggleClass("current");
- $("#search-arrow").toggleClass("arrow-down");
- });
-
-
- });
-</script>
\ No newline at end of file
+</div>
\ No newline at end of file
letter-spacing:normal;
box-shadow: 0 3px 7px rgba(0,0,0,0.3);
display: inline-block;
- width: 32%!important;
+ width: 32%;
margin-bottom: 1.5em;
vertical-align: top;
- margin-left: 1.5%!important;
+ margin-left: 1.5%;
position: relative;
overflow: hidden;
padding: 1.5em 1.5em 3em 1.5em;
}
.entrie:nth-child(3n+1) {
- margin-left: 0!important;
+ margin-left: 0;
}
.results {
2.1 = "save a link" popup div related styles
========================================================================== */
-#bagit-form {
+#bagit-form, #search-form {
background: rgba(0,0,0,0.5);
position: absolute;
top: 0;
border-left: 1px #EEE solid;
}
-#bagit-form form {
+#bagit-form form, #search-form form {
background: #FFF;
position: absolute;
top: 0;
padding: 2em;
}
-a#bagit-form-close {
+a#bagit-form-close, a#search-form-close {
background: #000;
color: #FFF;
padding: 0.2em 0.5em;
float: right;
font-size: 0.6em;
}
-a#bagit-form-close:hover {
+a#bagit-form-close:hover, a#search-form-close:hover {
background: #999;
color: #000;
}
display: none;
}
- #bagit-form {
+ #bagit-form, #search-form {
left: 0;
}
}
<h2>{% trans "Poching a link" %}</h2>
<p>{% trans "There are several ways to save an article:" %} (<a class="special" href="http://doc.wallabag.org" title="{% trans "read the documentation" %}">?</a>)</p>
<ul>
- <li>firefox: <a href="https://bitbucket.org/jogaulupeau/poche/downloads/poche.xpi" title="download the firefox extension">{% trans "download the extension" %}</a></li>
- <li>chrome: <a href="https://bitbucket.org/jogaulupeau/poche/downloads/poche.crx" title="download the chrome extension">{% trans "download the extension" %}</a></li>
- <li>android: <a href="https://bitbucket.org/jogaulupeau/poche/downloads/Poche.apk" title="download the application">{% trans "download the application" %}</a></li>
+ <li>Firefox: <a href="https://addons.mozilla.org/firefox/addon/wallabag/" title="download the firefox extension">{% trans "download the extension" %}</a></li>
+ <li>Chrome: <a href="http://doc.wallabag.org/doku.php?id=users:chrome_extension" title="download the chrome extension">{% trans "download the extension" %}</a></li>
+ <li>Android: <a href="https://f-droid.org/app/fr.gaulupeau.apps.InThePoche" title="download the application">{% trans "via F-Droid" %}</a> {% trans " or " %} <a href="https://play.google.com/store/apps/details?id=fr.gaulupeau.apps.InThePoche" title="download the application">{% trans "via Google Play" %}</a></li>
+ <li>iOS: <a href="https://itunes.apple.com/app/wallabag/id828331015?mt=8" title="download the iOS application">{% trans "download the application" %}</a></li>
+ <li>Windows Phone: <a href="http://www.windowsphone.com/en-us/store/app/wallabag/ff890514-348c-4d0b-9b43-153fff3f7450" title="download the window phone application">{% trans "download the application" %}</a></li>
<li>
<form method="get" action="index.php">
<label class="addurl" for="plainurl">{% trans "by filling this field" %}:</label>
<h2>{% trans "Export your wallabag data" %}</h2>
<p><a href="./?export" target="_blank">{% trans "Click here" %}</a> {% trans "to export your wallabag data." %}</p>
</div>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
<script src="{{ poche_url }}themes/default/js/autoClose.js"></script>
<script src="{{ poche_url }}themes/default/js/closeMessage.js"></script>
<script src="{{ poche_url }}themes/default/js/saveLink.js"></script>
+ <script src="{{ poche_url }}themes/default/js/popupForm.js"></script>
\ No newline at end of file
--- /dev/null
+$(document).ready(function() {
+
+ $("#search-form").hide();
+
+ function closeSearch() {
+ $("#search-form").toggle();
+ $("#search").toggleClass("current");
+ $("#search-arrow").toggleClass("arrow-down");
+ }
+
+ $("#search").click(function(){
+ closeSearch();
+ });
+
+ $("#search-form-close").click(function(){
+ closeSearch();
+ });
+
+
+});
\ No newline at end of file
========================================================================== */
$(window).keydown(function(e){
- if ( ( e.target.tagName.toLowerCase() !== 'input' && e.keyCode == 83 ) || e.keyCode == 27 ) {
+ if ( ( e.target.tagName.toLowerCase() !== 'input' && e.keyCode == 83 ) || (e.keyCode == 27 && $bagitForm.is(':visible') ) ) {
$bagit.removeClass("current");
$("#bagit-arrow").removeClass("arrow-down");
toggleSaveLinkForm();