mirror of
https://github.com/wallabag/wallabag.git
synced 2024-12-24 16:40:30 +00:00
use directly MOBIClass
This commit is contained in:
parent
c70bfefc68
commit
fb9df0c269
47 changed files with 309 additions and 1551 deletions
|
@ -11,18 +11,30 @@ class ImageHandler {
|
|||
$imgFile = @imagecreatefromstring($data);
|
||||
|
||||
if($imgFile !== false){
|
||||
@imagefilter($imgFile, IMG_FILTER_GRAYSCALE);
|
||||
|
||||
ob_start();
|
||||
@imagejpeg($imgFile);
|
||||
$image = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
@imagedestroy($imgFile);
|
||||
|
||||
return $image;
|
||||
$result = self::CreateImage($imgFile);
|
||||
imagedestroy($imgFile);
|
||||
return $result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Create an image
|
||||
* @param resource $img Create an image created with createimagetruecolor
|
||||
* @return false|string False if failed, else the data of the image (converted to grayscale jpeg)
|
||||
*/
|
||||
public static function CreateImage($img){
|
||||
try{
|
||||
imagefilter($img, IMG_FILTER_GRAYSCALE);
|
||||
|
||||
ob_start();
|
||||
imagejpeg($img);
|
||||
$image = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $image;
|
||||
}catch(Exception $e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -18,11 +18,9 @@ require_once(dirname(__FILE__).'/FileTri.php');
|
|||
require_once(dirname(__FILE__).'/Http.php');
|
||||
require_once(dirname(__FILE__).'/http_build_url.php');
|
||||
require_once(dirname(__FILE__).'/ImageHandler.php');
|
||||
require_once(dirname(__FILE__).'/MOBIFile.php');
|
||||
require_once(dirname(__FILE__).'/OnlineArticle.php');
|
||||
require_once(dirname(__FILE__).'/PalmRecord.php');
|
||||
require_once(dirname(__FILE__).'/PEOFRecord.php');
|
||||
require_once(dirname(__FILE__).'/PFCISRecord.php');
|
||||
require_once(dirname(__FILE__).'/PFLISRecord.php');
|
||||
require_once(dirname(__FILE__).'/Prc.php');
|
||||
require_once(dirname(__FILE__).'/PreprocessedArticle.php');
|
||||
require_once(dirname(__FILE__).'/RecognizeURL.php');
|
||||
|
@ -43,7 +41,7 @@ require_once(dirname(__FILE__).'/Settings.php');
|
|||
* $mobi->setFileSource($file); //Load a local file without any extra changes
|
||||
* $mobi->setData($data); //Load data
|
||||
*
|
||||
* //If you want, you can set some optional settings
|
||||
* //If you want, you can set some optional settings (see Settings.php for all recognized settings)
|
||||
* $options = array(
|
||||
* "title"=>"Insert title here",
|
||||
* "author"=>"Author"
|
||||
|
@ -86,7 +84,7 @@ class MOBI {
|
|||
*/
|
||||
public function setContentProvider($content){
|
||||
$this->setOptions($content->getMetaData());
|
||||
$this->images = $content->getImages();
|
||||
$this->setImages($content->getImages());
|
||||
$this->setData($content->getTextData());
|
||||
}
|
||||
|
||||
|
@ -149,16 +147,9 @@ class MOBI {
|
|||
$mobiHeader = new PalmRecord($settings, $dataRecords, $nRecords, $len, sizeof($this->images));
|
||||
array_unshift($dataRecords, $mobiHeader);
|
||||
$dataRecords = array_merge($dataRecords, $this->images);
|
||||
$mobiFooter1 = new PFLISRecord($len);
|
||||
$mobiFooter2 = new PFCISRecord($len);
|
||||
$mobiFooter3 = new PEOFRecord($len);
|
||||
$dataRecords[] = $mobiFooter1;
|
||||
$dataRecords[] = $mobiFooter2;
|
||||
$dataRecords[] = $mobiFooter3;
|
||||
/*$dataRecords = array_merge($dataRecords, $mobiFooter);
|
||||
*$dataRecords[] = $rec->createFLISRecord();*
|
||||
$dataRecords[] = $rec->createFLISRecord();
|
||||
$dataRecords[] = $rec->createFCISRecord($len);
|
||||
$dataRecords[] = $rec->createEOFRecord();*/
|
||||
$dataRecords[] = $rec->createEOFRecord();
|
||||
$this->prc = new Prc($settings, $dataRecords);
|
||||
return $this->prc;
|
||||
}
|
||||
|
@ -183,7 +174,7 @@ class MOBI {
|
|||
$length = strlen($data);
|
||||
|
||||
if($this->debug) return; //In debug mode, don't start the download
|
||||
/*
|
||||
|
||||
header("Content-Type: application/x-mobipocket-ebook");
|
||||
header("Content-Disposition: attachment; filename=\"".$name."\"");
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
|
@ -192,12 +183,8 @@ class MOBI {
|
|||
header('Pragma: private');
|
||||
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
||||
header("Content-Length: ".$length);
|
||||
echo $data;*/
|
||||
|
||||
|
||||
$hh = fopen("D:\hakuna.mobi", "w");
|
||||
fwrite($hh, $data);
|
||||
fclose($hh);
|
||||
echo $data;
|
||||
//Finished!
|
||||
}
|
||||
|
157
inc/3rdparty/libraries/MOBIClass/MOBIFile.php
vendored
Normal file
157
inc/3rdparty/libraries/MOBIClass/MOBIFile.php
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
<?php
|
||||
/**
|
||||
* This is the way MOBI files should be created if you want all features (TOC, images).
|
||||
*
|
||||
* File modified by Dawson for use in eBook Creator
|
||||
* Added pagebreaks and a setting to remove table of contents.
|
||||
*/
|
||||
|
||||
class MOBIFile extends ContentProvider {
|
||||
const PARAGRAPH = 0;
|
||||
const H2 = 1;
|
||||
const H3 = 2;
|
||||
const IMAGE = 3;
|
||||
const PAGEBREAK = 4;
|
||||
|
||||
private $settings = array("title" => "Unknown Title", "toc" => true);
|
||||
private $parts = array();
|
||||
private $images = array();
|
||||
|
||||
/**
|
||||
* Get the text data (the "html" code)
|
||||
*/
|
||||
public function getTextData(){
|
||||
$prefix = "<html><head><guide><reference title='CONTENT' type='toc' filepos=0000000000 /></guide></head><body>";
|
||||
|
||||
$title = "<h1>".$this->settings["title"]."</h1>";
|
||||
|
||||
list($text, $entries) = $this->generateText();
|
||||
|
||||
if($this->settings["toc"]) {
|
||||
$toc = $this->generateTOC($entries); //Generate TOC to get the right length
|
||||
$toc = $this->generateTOC($entries, strlen($prefix)+strlen($toc)+strlen($title)); //Generate the real TOC
|
||||
}
|
||||
|
||||
$suffix = "</body></html>";
|
||||
|
||||
return $prefix.$toc.$title.$text.$suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the body's text and the chapter entries
|
||||
* @return array($string, $entries) $string is the html data, $entries
|
||||
* contains the level, the title and the position of the titles.
|
||||
*/
|
||||
public function generateText(){
|
||||
$str = "";
|
||||
$entries = array();
|
||||
|
||||
for($i = 0; $i < sizeof($this->parts); $i++){
|
||||
list($type, $data) = $this->parts[$i];
|
||||
$id = "title_".$i;
|
||||
switch($type){
|
||||
case self::PARAGRAPH:
|
||||
$str .= "<p>".$data."</p>";
|
||||
break;
|
||||
case self::PAGEBREAK:
|
||||
$str .= '<mbp:pagebreak/>';
|
||||
break;
|
||||
case self::H2:
|
||||
$entries[] = array("level" => 2, "position" => strlen($str), "title" => $data, "id" => $id);
|
||||
$str .= "<h2 id='" . $id . "'>".$data."</h2>";
|
||||
break;
|
||||
case self::H3:
|
||||
$entries[] = array("level" => 3, "position" => strlen($str), "title" => $data, "id" => $id);
|
||||
$str .= "<h3 id='" . $id . "'>".$data."</h3>";
|
||||
break;
|
||||
case self::IMAGE:
|
||||
$str .= "<img recindex=".str_pad($data+1, 10, "0", STR_PAD_LEFT)." />";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array($str, $entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a TOC
|
||||
* @param $entries The entries array generated by generateText
|
||||
* @param $base The zero position
|
||||
*/
|
||||
public function generateTOC($entries, $base = 0){
|
||||
$toc = "<h2>Contents</h2>";
|
||||
$toc .= "<blockquote><table summary='Table of Contents'><col/><tbody>";
|
||||
for($i = 0, $len = sizeof($entries); $i < $len; $i++){
|
||||
$entry = $entries[$i];
|
||||
$pos = str_pad($entry["position"]+$base, 10, "0", STR_PAD_LEFT);
|
||||
$toc .= "<tr><td><a href='#".$entry["id"]."' filepos='".$pos."'>".$entry["title"]."</a></td></tr>";
|
||||
}
|
||||
return $toc."</tbody></b></table></blockquote><mbp:pagebreak/>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file records of the images
|
||||
*/
|
||||
public function getImages(){
|
||||
return $this->images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metadata
|
||||
*/
|
||||
public function getMetaData(){
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the file's settings. For example set("author", "John Doe") or set("title", "The adventures of John Doe").
|
||||
* @param $key Key of the setting to insert.
|
||||
*/
|
||||
public function set($key, $value){
|
||||
$this->settings[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file's settings.
|
||||
*/
|
||||
public function get($key){
|
||||
return $this->settings[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a paragraph of text to the file.
|
||||
* @param string $text The text to insert.
|
||||
*/
|
||||
public function appendParagraph($text){
|
||||
$this->parts[] = array(self::PARAGRAPH, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a chapter title (H2)
|
||||
* @param string $title The title to insert.
|
||||
*/
|
||||
public function appendChapterTitle($title){
|
||||
$this->parts[] = array(self::H2, $title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a section title (H3)
|
||||
* @param string $title The title to insert.
|
||||
*/
|
||||
public function appendSectionTitle($title){
|
||||
$this->parts[] = array(self::H3, $title);
|
||||
}
|
||||
|
||||
public function appendPageBreak() {
|
||||
$this->parts[] = array(self::PAGEBREAK, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an image.
|
||||
* @param resource $img An image file (for example, created by `imagecreate`)
|
||||
*/
|
||||
public function appendImage($img){
|
||||
$imgIndex = sizeof($this->images);
|
||||
$this->images[] = new FileRecord(new Record(ImageHandler::CreateImage($img)));
|
||||
$this->parts[] = array(self::IMAGE, $imgIndex);
|
||||
}
|
||||
}
|
|
@ -38,32 +38,19 @@ class PalmRecord extends FileObject {
|
|||
"huffmanRecordOffset"=>new FileInt(),
|
||||
"huffmanRecordCount"=>new FileInt(),
|
||||
"unused3"=>new FileString(8),
|
||||
"exthFlags"=>new FileInt(0x50),
|
||||
"exthFlags"=>new FileInt(0x40),
|
||||
"unknown"=>new FileString(32),
|
||||
"drmOffset"=>new FileInt(0xFFFFFFFF),
|
||||
"drmCount"=>new FileInt(0xFFFFFFFF),
|
||||
"drmSize"=>new FileInt(),
|
||||
"drmCount"=>new FileShort(0xFFFFFFFF),
|
||||
"drmSize"=>new FileShort(),
|
||||
"drmFlags"=>new FileInt(),
|
||||
"mobiFiller"=>new FileString(12),
|
||||
"offset192"=>new FileShort(0x01),
|
||||
"offset194"=>new FileShort(),
|
||||
"offset196"=>new FileInt(0x01),
|
||||
"offset200"=>new FileInt(),
|
||||
"offset204"=>new FileInt(0x01),
|
||||
"offset208"=>new FileInt(),
|
||||
"offset212"=>new FileInt(0x01),
|
||||
"offset216"=>new FileString(8),
|
||||
"offset224"=>new FileInt(0xFFFFFFFF),
|
||||
"offset228"=>new FileInt(),
|
||||
"offset232"=>new FileString(8),
|
||||
"offset240"=>new FileInt(0x01),
|
||||
"offset244"=>new FileInt(0xFFFFFFFF),
|
||||
"mobiFiller"=>new FileString(72),
|
||||
//EXTH Header
|
||||
"exthIdentifier"=>new FileString("EXTH", 4),
|
||||
"exthHeaderLength"=>new FileInt(),
|
||||
"exthRecordCount"=>new FileInt(),
|
||||
"exthRecords"=>new FileElement(),
|
||||
"exthPadding"=>new FileString(),//added the 2 extra pad bytes that comes before name/title
|
||||
"exthPadding"=>new FileString(),
|
||||
//"fullNamePadding"=>new FileString(100),
|
||||
"fullName"=>new FileString()
|
||||
));
|
||||
|
@ -96,7 +83,7 @@ class PalmRecord extends FileObject {
|
|||
}
|
||||
|
||||
if($images > 0){
|
||||
$this->elements->get("firstImageIndex")->set($textRecords+2);
|
||||
$this->elements->get("firstImageIndex")->set($textRecords+1);
|
||||
}
|
||||
$this->elements->get("firstNonBookIndex")->set($textRecords+2+$images);
|
||||
$this->elements->get("reserved")->set(str_pad("", 40, chr(255), STR_PAD_RIGHT));
|
||||
|
@ -104,21 +91,16 @@ class PalmRecord extends FileObject {
|
|||
$this->elements->set("exthRecords", $exthElems);
|
||||
$pad = $l%4;
|
||||
$pad = (4-$pad)%4;
|
||||
$this->elements->get("exthPadding")->set(str_pad("", $pad+2, "\0", STR_PAD_RIGHT));
|
||||
$this->elements->get("exthPadding")->set(str_pad("", $pad, "\0", STR_PAD_RIGHT));
|
||||
$this->elements->get("exthHeaderLength")->set(12+$l+$pad);
|
||||
|
||||
|
||||
$this->elements->get("recordCount")->set($textRecords);
|
||||
|
||||
$this->elements->get("fullNameOffset")->set($this->elements->offsetToEntry("fullName"));//need to be checked
|
||||
$this->elements->get("fullNameOffset")->set($this->elements->offsetToEntry("fullName"));
|
||||
$this->elements->get("fullNameLength")->set(strlen($settings->get("title")));
|
||||
$this->elements->get("fullName")->set($settings->get("title"));
|
||||
$this->elements->get("textLength")->set($textLength);
|
||||
|
||||
$this->elements->get("offset194")->set($textRecords+2+$images);
|
||||
$this->elements->get("offset200")->set($textRecords+4+$images);
|
||||
$this->elements->get("offset208")->set($textRecords+3+$images);
|
||||
$this->elements->get("offset232")->set(str_pad("", 8, chr(255), STR_PAD_RIGHT));
|
||||
}
|
||||
|
||||
public function getByteLength(){
|
|
@ -40,7 +40,7 @@ class Prc extends FileElement {
|
|||
foreach($records as $record){
|
||||
$offset = new FileInt();
|
||||
$attr = new FileByte();
|
||||
$uniqueID = new FileTri(2*$i);
|
||||
$uniqueID = new FileTri($i);
|
||||
|
||||
$this->elements["recordList"]->add("Rec".$i, new FileElement(array(
|
||||
"offset"=>$offset,
|
||||
|
@ -49,7 +49,7 @@ class Prc extends FileElement {
|
|||
)));
|
||||
|
||||
$this->elements["records"]->add("Rec".$i, $record);
|
||||
$i+=1;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$this->updateOffsets($records);
|
|
@ -62,21 +62,7 @@ class RecordFactory {
|
|||
}
|
||||
|
||||
public function createFLISRecord(){
|
||||
|
||||
$this->elements = new FileElement(array(
|
||||
"offsetL0"=>new FileString("FLIS", 4), //FLIS
|
||||
"offsetL4"=>new FileInt(0x08),
|
||||
"offsetL8"=>new FileShort(0x41),
|
||||
"offsetL10"=>new FileTri(),
|
||||
"offsetL16"=>new FileInt(0xFFFFFFFF),
|
||||
"offsetL20"=>new FileShort(0x01),
|
||||
"offsetL22"=>new FileShort(0x03),
|
||||
"offsetL24"=>new FileInt(0x03),
|
||||
"offsetL28"=>new FileInt(0x01),
|
||||
"offsetL32"=>new FileInt(0xFFFFFFFF)
|
||||
));
|
||||
|
||||
/*$r = "FLIS";
|
||||
$r = "FLIS";
|
||||
$r .= $this->asString(8, 4);
|
||||
$r .= $this->asString(65, 2);
|
||||
$r .= $this->asString(0, 2);
|
||||
|
@ -87,7 +73,7 @@ class RecordFactory {
|
|||
$r .= $this->asString(3, 4);
|
||||
$r .= $this->asString(1, 4);
|
||||
$r .= $this->asString(-1, 4);
|
||||
return new Record($r);*/
|
||||
return new Record($r);
|
||||
}
|
||||
|
||||
private function asString($int, $size){
|
|
@ -19,6 +19,7 @@ class Settings {
|
|||
* be added with a key/value pair format.
|
||||
*/
|
||||
public function __construct($additionalSettings = array()) {
|
||||
// Most values shouldn't be changed (the result will be an invalid file)
|
||||
$this->values = array(
|
||||
"attributes"=>0,
|
||||
"version"=>0,
|
||||
|
@ -48,13 +49,14 @@ class Settings {
|
|||
"minimumVersion"=>6,
|
||||
"huffmanRecordOffset"=>0,
|
||||
"huffmanRecordCount"=>0,
|
||||
"exthFlags"=>0x50,
|
||||
"exthFlags"=>0x40,
|
||||
"drmOffset"=>0xFFFFFFFF,
|
||||
"drmCount"=>0xFFFFFFFF,
|
||||
"drmCount"=>0,
|
||||
"drmSize"=>0,
|
||||
"drmFlags"=>0,
|
||||
"extraDataFlags"=>0,
|
||||
"exthIdentifier"=>"EXTH",
|
||||
// These can be changed without any risk
|
||||
"title"=>"Unknown title",
|
||||
"author"=>"Unknown author",
|
||||
"subject"=>"Unknown subject"
|
2
inc/3rdparty/libraries/mpdf/mpdf.php
vendored
2
inc/3rdparty/libraries/mpdf/mpdf.php
vendored
|
@ -7451,7 +7451,7 @@ function Output($name='',$dest='')
|
|||
// don't use length if server using compression
|
||||
header('Content-Length: '.strlen($this->buffer));
|
||||
}
|
||||
header('Content-disposition: inline; filename="'.$name.'"');
|
||||
header('Content-disposition: attachment; filename="'.$name.'"');
|
||||
header('Cache-Control: public, must-revalidate, max-age=0');
|
||||
header('Pragma: public');
|
||||
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* A Record of a End file
|
||||
*
|
||||
* @author Pratyush
|
||||
*/
|
||||
class PEOFRecord extends FileObject {
|
||||
/**
|
||||
* @var FileElement
|
||||
*/
|
||||
private $elements;
|
||||
|
||||
public function __construct($leng){
|
||||
$this->elements = new FileElement(array(
|
||||
|
||||
"offset44"=>new FileInt(0xe98e0d0a)
|
||||
));
|
||||
}
|
||||
public function getByteLength(){
|
||||
return $this->getLength();
|
||||
}
|
||||
|
||||
public function getLength(){
|
||||
return $this->elements->getByteLength();
|
||||
}
|
||||
|
||||
public function get(){
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set($elements){
|
||||
throw new Exception("Unallowed set");
|
||||
}
|
||||
|
||||
public function serialize() {
|
||||
return $this->elements->serialize();
|
||||
}
|
||||
|
||||
public function unserialize($data) {
|
||||
$this->elements->unserialize($data);
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
$output = "PalmDoc Record (".$this->getByteLength()." bytes):\n";
|
||||
$output .= $this->elements;
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* A Record of a End file
|
||||
*
|
||||
* @author Pratyush
|
||||
*/
|
||||
class PFCISRecord extends FileObject {
|
||||
/**
|
||||
* @var FileElement
|
||||
*/
|
||||
private $elements;
|
||||
|
||||
public function __construct($leng){
|
||||
$this->elements = new FileElement(array(
|
||||
"offset0"=>new FileString("FCIS", 4), //FCIS
|
||||
"offset4"=>new FileInt(0x014),
|
||||
"offset8"=>new FileInt(0x10),
|
||||
"offset12"=>new FileInt(0x01),
|
||||
"offset16"=>new FileInt(),
|
||||
"offset20"=>new FileInt($leng),
|
||||
"offset24"=>new FileInt(),
|
||||
"offset28"=>new FileInt(0x20),
|
||||
"offset32"=>new FileInt(0x08),
|
||||
"offset36"=>new FileShort(0x01),
|
||||
"offset38"=>new FileShort(0x01),
|
||||
"offset40"=>new FileInt()
|
||||
));
|
||||
}
|
||||
public function getByteLength(){
|
||||
return $this->getLength();
|
||||
}
|
||||
|
||||
public function getLength(){
|
||||
return $this->elements->getByteLength();
|
||||
}
|
||||
|
||||
public function get(){
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set($elements){
|
||||
throw new Exception("Unallowed set");
|
||||
}
|
||||
|
||||
public function serialize() {
|
||||
return $this->elements->serialize();
|
||||
}
|
||||
|
||||
public function unserialize($data) {
|
||||
$this->elements->unserialize($data);
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
$output = "PalmDoc Record (".$this->getByteLength()." bytes):\n";
|
||||
$output .= $this->elements;
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* A Record of a End file
|
||||
*
|
||||
* @author Pratyush
|
||||
*/
|
||||
class PFLISRecord extends FileObject {
|
||||
/**
|
||||
* @var FileElement
|
||||
*/
|
||||
private $elements;
|
||||
|
||||
public function __construct($leng){
|
||||
$this->elements = new FileElement(array(
|
||||
"offsetL0"=>new FileString("FLIS", 4), //FLIS
|
||||
"offsetL4"=>new FileInt(0x08),
|
||||
"offsetL8"=>new FileShort(0x41),
|
||||
"offsetL10"=>new FileString(6),
|
||||
"offsetL16"=>new FileInt(0xFFFFFFFF),
|
||||
"offsetL20"=>new FileShort(0x01),
|
||||
"offsetL22"=>new FileShort(0x03),
|
||||
"offsetL24"=>new FileInt(0x03),
|
||||
"offsetL28"=>new FileInt(0x01),
|
||||
"offsetL32"=>new FileInt(0xFFFFFFFF)
|
||||
|
||||
));
|
||||
}
|
||||
public function getByteLength(){
|
||||
return $this->getLength();
|
||||
}
|
||||
|
||||
public function getLength(){
|
||||
return $this->elements->getByteLength();
|
||||
}
|
||||
|
||||
public function get(){
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set($elements){
|
||||
throw new Exception("Unallowed set");
|
||||
}
|
||||
|
||||
public function serialize() {
|
||||
return $this->elements->serialize();
|
||||
}
|
||||
|
||||
public function unserialize($data) {
|
||||
$this->elements->unserialize($data);
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
$output = "PalmDoc Record (".$this->getByteLength()." bytes):\n";
|
||||
$output .= $this->elements;
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
234
inc/3rdparty/libraries/send2kindle/api.php
vendored
234
inc/3rdparty/libraries/send2kindle/api.php
vendored
|
@ -1,234 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Dimmduh
|
||||
* @email dimmduh@gmail.com
|
||||
*/
|
||||
class API{
|
||||
|
||||
private $service;
|
||||
private $auth;
|
||||
private $token;
|
||||
private $source = 'GoogleReaderAPIClass-0.1';
|
||||
private $client = 'scroll';
|
||||
private $account_type = 'HOSTED_OR_GOOGLE';
|
||||
private $clientlogin_url = 'https://www.google.com/accounts/ClientLogin';
|
||||
private $reader_api_url = 'http://www.google.com/reader/api/0/';
|
||||
private $session_var_auth_name = 'google_auth';
|
||||
|
||||
|
||||
public function __construct( $email, $password, $service = 'reader' ){
|
||||
if (isset( $service ) ){
|
||||
$this -> service = $service;
|
||||
}
|
||||
/* if ( isset($_SESSION[ $this -> session_var_auth_name ] ) ){
|
||||
$this -> auth = $_SESSION[ $this -> session_var_auth_name ];
|
||||
echo "Loading";
|
||||
} else { */
|
||||
$this -> clientLogin( $email, $password );
|
||||
$this -> get_token();
|
||||
/* } */
|
||||
}
|
||||
|
||||
|
||||
private function request( $url, $type = 'get', $headers = false, $fields = false, $cookie = false){
|
||||
|
||||
$curl = curl_init();
|
||||
|
||||
if ( $fields ){
|
||||
if ($type == 'get'){
|
||||
$url .= '?'.http_build_query( $fields );
|
||||
} else {
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($fields) );
|
||||
}
|
||||
}
|
||||
if ( $headers ){
|
||||
curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
if ( $cookie ){
|
||||
curl_setopt($curl, CURLOPT_COOKIE, $cookie);
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
if (strpos($url, 'https://') !== false){
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
}
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
|
||||
|
||||
$response = array();
|
||||
$response['text'] = curl_exec($curl);
|
||||
$response['info'] = curl_getinfo( $curl);
|
||||
$response['code'] = curl_getinfo( $curl, CURLINFO_HTTP_CODE );
|
||||
$response['body'] = substr( $response['text'], $response['info']['header_size'] );
|
||||
|
||||
curl_close( $curl );
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function request2google( $url, $type = 'get', $headers = false, $fields = false ){
|
||||
if ( $this -> auth ){
|
||||
$headers[] = 'Content-type: application/x-www-form-urlencoded';
|
||||
$headers[] = 'Authorization: GoogleLogin auth='.$this -> auth;
|
||||
|
||||
if ( strpos( $url, 'http://') === false && strpos( $url, 'https://' ) === false ){
|
||||
$url = $this -> reader_api_url.$url;
|
||||
}
|
||||
|
||||
$response = $this -> request( $url, $type, $headers, $fields);
|
||||
if ( $response['code'] == 200 ){
|
||||
if ( isset( $fields['output'] ) ){
|
||||
switch ($fields['output']){
|
||||
case 'xml':
|
||||
return (new SimpleXMLElement( $response['body'] ) );
|
||||
break;
|
||||
case 'json':
|
||||
default:
|
||||
return json_decode( $response['body'] );
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return $response['body'];
|
||||
}
|
||||
} else {
|
||||
Throw new AutentificationException('Auth error: server response '.$response['code'] );
|
||||
}
|
||||
|
||||
} else {
|
||||
Throw new AutentificationException('Auth error: not finded Auth token');
|
||||
}
|
||||
}
|
||||
|
||||
public function get_tag_list( $output = 'json' ){
|
||||
return $this -> request2google('tag/list', "get", false, array(
|
||||
'output' => $output,
|
||||
'ck' => time(),
|
||||
'client' => $this -> client,
|
||||
));
|
||||
}
|
||||
public function get_subscription_list( $output = 'json' ){
|
||||
return $this -> request2google('subscription/list', "get", false, array(
|
||||
'output' => $output,
|
||||
'ck' => time(),
|
||||
'client' => $this -> client,
|
||||
));
|
||||
}
|
||||
public function get_preference_list( $output = 'json' ){
|
||||
return $this -> request2google('preference/list', "get", false, array(
|
||||
'output' => $output,
|
||||
'ck' => time(),
|
||||
'client' => $this -> client,
|
||||
));
|
||||
}
|
||||
public function get_unread_count( $output = 'json' ){
|
||||
return $this -> request2google('unread-count', "get", false, array(
|
||||
'all' => true,
|
||||
'output' => $output,
|
||||
'ck' => time(),
|
||||
'client' => $this -> client,
|
||||
));
|
||||
}
|
||||
public function get_user_info( $output = 'json' ){
|
||||
return $this -> request2google('user-info', "get", false, array(
|
||||
'output' => $output,
|
||||
'ck' => time(),
|
||||
'client' => $this -> client,
|
||||
));
|
||||
}
|
||||
private function get_token(){
|
||||
$this -> token = $this -> request2google('token');
|
||||
}
|
||||
|
||||
//get contents functions
|
||||
/*
|
||||
r - order
|
||||
r = n - new items
|
||||
r = o - old items
|
||||
r = a - auto sort
|
||||
|
||||
*/
|
||||
private function get_content( $content_url = '', $number = 20, $order = 'n', $exclude_target = '', $start_time = '', $continuation = ''){
|
||||
$fields = array(
|
||||
'ck' => time(),
|
||||
'client' => $this -> client,
|
||||
'n' => $number,
|
||||
'r' => $order,
|
||||
'output' => 'json',
|
||||
);
|
||||
if ( !empty($exclude_target) ){$fields['xt'] = $exclude_target;}
|
||||
if ( !empty($start_time) ){$fields['ot'] = $start_time;}
|
||||
if ( !empty($continuation) ){$fields['c'] = $continuation;}
|
||||
|
||||
return $this -> request2google('stream/contents/'.Utils::urlencode( $content_url ), 'get', false, $fields);
|
||||
}
|
||||
|
||||
public function get_content_feed( $feed_url = '', $number = 20, $order = 'n', $exclude_target = '', $start_time = '', $continuation = ''){
|
||||
return $this -> get_content( $feed_url, $number, $order, $exclude_target, $start_time, $continuation );
|
||||
}
|
||||
public function get_content_by_label( $label = '', $number = 20, $order = 'n', $exclude_target = '', $start_time = '', $continuation = ''){
|
||||
return $this -> get_content( (strpos($label, '/') === false?'user/-/label/':'').$label, $number, $order, $exclude_target, $start_time, $continuation );
|
||||
}
|
||||
public function get_content_by_state( $state = '', $number = 20, $order = 'n', $exclude_target = '', $start_time = '', $continuation = ''){
|
||||
return $this -> get_content( (strpos($state, '/') === false?'user/-/state/com.google/':'').$state, $number, $order, $exclude_target, $start_time, $continuation );
|
||||
}
|
||||
|
||||
public function get_unread( $number = 20, $order = 'n' ){
|
||||
return $this ->get_content_by_state('reading-list', $number, $order, 'user/-/state/com.google/read');
|
||||
}
|
||||
|
||||
public function get_starred($number = 20, $order = 'n'){
|
||||
return $this ->get_content_by_state('starred', $number, $order);
|
||||
}
|
||||
|
||||
/*
|
||||
Edit functions
|
||||
*/
|
||||
private function edit_do( $api_function , $post_fields ){
|
||||
$post_fields['T'] = $this -> token;
|
||||
if ( $this -> request2google( $api_function, "post", false, $post_fields ) == "OK"){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* public function edit_subscription(
|
||||
s return $this -> edit_do( 'subscription/edit',
|
||||
} */
|
||||
public function set_state( $itemId, $state = 'read'){
|
||||
$post_fields = array(
|
||||
"i" => $itemId,
|
||||
"a" => 'user/-/state/com.google/'.$state,
|
||||
);
|
||||
//print_r( $post_fields );
|
||||
return $this ->edit_do('edit-tag?client='.$this -> client, $post_fields);
|
||||
}
|
||||
|
||||
private function clientLogin( $email, $password ){
|
||||
|
||||
$response = $this -> request( $this -> clientlogin_url, 'post', false, array(
|
||||
"accountType" => $this -> account_type,
|
||||
"Email" => $email,
|
||||
"Passwd" => $password,
|
||||
"service" => $this -> service,
|
||||
"source" => $this -> source,
|
||||
));
|
||||
|
||||
if ( $response['code'] == 200) {
|
||||
preg_match("/Auth=([a-z0-9_\-]+)/i", $response['body'], $matches_auth);
|
||||
if ($matches_auth[1]){
|
||||
$this -> auth = $matches_auth[1];
|
||||
$_SESSION[ $this -> session_var_auth_name ] = $this -> auth;
|
||||
return true;
|
||||
} else {
|
||||
Throw new AutentificationException('Auth error: not finded Auth token in response');
|
||||
}
|
||||
} else {
|
||||
Throw new AutentificationException('Auth error: server response '.$response['code'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Exceptions
|
||||
class AutentificationException extends Exception {}
|
136
inc/3rdparty/libraries/send2kindle/images.php
vendored
136
inc/3rdparty/libraries/send2kindle/images.php
vendored
|
@ -1,136 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Get images from content and prepare to save in articles
|
||||
*/
|
||||
class Images {
|
||||
|
||||
/**
|
||||
* JPER quality for resize
|
||||
*/
|
||||
const JPEG_QUALITY = 80;
|
||||
|
||||
/**
|
||||
* Articles content
|
||||
* @var string
|
||||
*/
|
||||
private $_content;
|
||||
|
||||
/**
|
||||
* Storage to keep images
|
||||
* @var object Storage
|
||||
*/
|
||||
private $_storage;
|
||||
|
||||
/**
|
||||
* images from content
|
||||
* @var array
|
||||
*/
|
||||
private $_images_from_content = array();
|
||||
|
||||
/**
|
||||
* Prepare get images
|
||||
* @param Strage $storage
|
||||
* @param string $article_content
|
||||
*/
|
||||
public function __construct(Storage $storage, $article_content)
|
||||
{
|
||||
$this->_storage = $storage;
|
||||
$this->_content = $article_content;
|
||||
$this->_images_from_content = $this->_get_images_from_content($article_content);
|
||||
}
|
||||
|
||||
/**
|
||||
* get images from url
|
||||
* @param string $content
|
||||
* @return array images hashtable
|
||||
*/
|
||||
private function _get_images_from_content($content)
|
||||
{
|
||||
$result = array();
|
||||
preg_match_all('/src=\"([a-zA-Z0-9\.\/\-\_\?\+\%\~\&\;\=\:]+)\"/i', $content, $result);
|
||||
|
||||
return $result[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Start conversion
|
||||
* @return string converted content
|
||||
*/
|
||||
public function convert()
|
||||
{
|
||||
foreach ( $this->_images_from_content as $n => $image_url )
|
||||
{
|
||||
$image = $this->_get_image($image_url);
|
||||
$this->_content = str_replace($image_url, '" recindex="'.(int)basename($image), $this->_content);
|
||||
}
|
||||
|
||||
return $this->_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize image
|
||||
* @param string $file path
|
||||
* @param int $new_width max width
|
||||
*/
|
||||
private function _resize($file, $new_width = 500)
|
||||
{
|
||||
list($width, $height) = getimagesize($file);
|
||||
|
||||
$new_height = 0;
|
||||
|
||||
//setup the new size of the image
|
||||
if( $width > $new_width )
|
||||
{
|
||||
$ratio = $height/$width;
|
||||
$new_height = $new_width * $ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_width = $width;
|
||||
$new_height = $height;
|
||||
}
|
||||
|
||||
// resample the image
|
||||
$new_image = imagecreatetruecolor($new_width, $new_height);
|
||||
|
||||
$type = exif_imagetype ( $file );
|
||||
|
||||
switch ( $type )
|
||||
{
|
||||
case IMAGETYPE_JPEG:
|
||||
$old_image = imagecreatefromjpeg($file);
|
||||
imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
|
||||
imagejpeg($new_image, $file, self::JPEG_QUALITY);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$old_image = imagecreatefrompng($file);
|
||||
imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
|
||||
imagepng($new_image, $file);
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
$old_image = imagecreatefromgif($file);
|
||||
imagecopyresampled($new_image, $old_image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
|
||||
imagegif($new_image, $file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize image
|
||||
* @return string image path
|
||||
*/
|
||||
private function _get_image($url)
|
||||
{
|
||||
$image_data = @file_get_contents($url);
|
||||
|
||||
if ( $image_data !== false )
|
||||
{
|
||||
$image_name = $this->_storage->save_image($image_data);
|
||||
$this->_resize($image_name);
|
||||
|
||||
return $image_name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
250
inc/3rdparty/libraries/send2kindle/io.php
vendored
250
inc/3rdparty/libraries/send2kindle/io.php
vendored
|
@ -1,250 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Simple output message and args prepared
|
||||
*
|
||||
* @author Jakub Westfalewski <jwest@jwest.pl>
|
||||
*/
|
||||
class IO {
|
||||
|
||||
/**
|
||||
* Max line height
|
||||
*/
|
||||
const COMMAND_LENGTH = 50;
|
||||
|
||||
/**
|
||||
* args for run screen
|
||||
* @var array
|
||||
*/
|
||||
protected static $_args = array
|
||||
(
|
||||
'help' => array('value' => FALSE, 'description' => 'show help for news2kindle'),
|
||||
'grab' => array('value' => FALSE, 'description' => 'grab articles from google reader'),
|
||||
'mobi' => array('value' => FALSE, 'description' => 'prepare mobi format'),
|
||||
'send' => array('value' => FALSE, 'description' => 'send articles to kindle'),
|
||||
'login' => array('value' => NULL, 'description' => 'your login to google account *requred'),
|
||||
'password' => array('value' => NULL, 'description' => 'your password to google account *required'),
|
||||
'kindle' => array('value' => NULL, 'description' => 'your kindle email *required'),
|
||||
'items' => array('value' => 100, 'description' => 'max items to grab in run'),
|
||||
'render' => array('value' => 'std', 'description' => 'name of html template for newspapper'),
|
||||
//'timeout' => array('value' => FALSE, 'description' => 'timeout is most important than items count'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Write on screen text line
|
||||
* @param string $message
|
||||
* @param bool $broken_line
|
||||
*/
|
||||
public static function msg($message, $broken_line = TRUE)
|
||||
{
|
||||
echo ( $broken_line ? "\n" : "" ) . $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write command for status
|
||||
* @param string $message
|
||||
*/
|
||||
public static function command($message)
|
||||
{
|
||||
$output_whitespaces = '';
|
||||
|
||||
for ($i = strlen($message); $i <= self::COMMAND_LENGTH; ++$i )
|
||||
{
|
||||
$output_whitespaces .= '-';
|
||||
}
|
||||
|
||||
self::msg( $message . ' ' . $output_whitespaces.' ' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Status - OK
|
||||
*/
|
||||
public static function ok()
|
||||
{
|
||||
$colored_string = "\033[1;37m" . "\033[42m" . ' OK ' . "\033[0m";
|
||||
self::msg( $colored_string, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Status - Error
|
||||
*/
|
||||
public static function error($message = NULL)
|
||||
{
|
||||
$colored_string = "\033[1;37m" . "\033[41m" . ' ERROR ' . "\033[0m";
|
||||
self::msg( $colored_string, FALSE );
|
||||
|
||||
if ( $message !== NULL )
|
||||
{
|
||||
self::msg( ' - ' . $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get run args
|
||||
* @param string $name key config
|
||||
* @return mixed config value
|
||||
*/
|
||||
public static function arg($name)
|
||||
{
|
||||
return self::$_args[$name]['value'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config from ini
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
protected static function _get_config($path)
|
||||
{
|
||||
$config = parse_ini_file( $path . 'config.ini' );
|
||||
|
||||
foreach($config as $key => $value)
|
||||
{
|
||||
self::$_args[$key]['value'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare args for script
|
||||
* (from http://php.net/manual/en/features.commandline.php)
|
||||
* @param array $argv array
|
||||
* @param string $path
|
||||
* @return bool success or error
|
||||
*/
|
||||
public static function prepare_args($argv, $path)
|
||||
{
|
||||
self::command('Parse args');
|
||||
|
||||
self::_get_config($path);
|
||||
|
||||
array_shift($argv);
|
||||
$out = array();
|
||||
|
||||
foreach ( $argv as $arg )
|
||||
{
|
||||
if ( substr($arg,0,2) == '--' )
|
||||
{
|
||||
$eqPos = strpos($arg,'=');
|
||||
|
||||
if ( $eqPos === false )
|
||||
{
|
||||
$key = substr($arg,2);
|
||||
$out[$key] = isset($out[$key]) ? $out[$key] : true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$key = substr($arg,2,$eqPos-2);
|
||||
$out[$key] = substr($arg,$eqPos+1);
|
||||
}
|
||||
|
||||
}
|
||||
else if ( substr($arg,0,1) == '-' )
|
||||
{
|
||||
if ( substr($arg,2,1) == '=' )
|
||||
{
|
||||
$key = substr($arg,1,1);
|
||||
$out[$key] = substr($arg,3);
|
||||
}
|
||||
else
|
||||
{
|
||||
$chars = str_split(substr($arg,1));
|
||||
|
||||
foreach ( $chars as $char )
|
||||
{
|
||||
$key = $char;
|
||||
$out[$key] = isset($out[$key]) ? $out[$key] : true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$out[] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$args = self::_validate_args($out);
|
||||
|
||||
foreach ( $args as $key => $value )
|
||||
{
|
||||
self::$_args[$key]['value'] = $value;
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
self::error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
self::ok();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate args for script
|
||||
* (from http://php.net/manual/en/features.commandline.php)
|
||||
* @param array $argv array
|
||||
* @return array args
|
||||
*/
|
||||
private static function _validate_args($args)
|
||||
{
|
||||
if( array_key_exists('help', $args) OR array_key_exists('h', $args) )
|
||||
{
|
||||
$args['grab'] = false;
|
||||
$args['mobi'] = false;
|
||||
$args['send'] = false;
|
||||
$args['login'] = false;
|
||||
$args['password'] = false;
|
||||
$args['kindle'] = false;
|
||||
}
|
||||
|
||||
foreach ( $args as $key => $arg )
|
||||
{
|
||||
if ( strlen($key) === 1 )
|
||||
{
|
||||
foreach ( self::$_args as $keyA => $argA )
|
||||
{
|
||||
if($keyA[0] === $key )
|
||||
{
|
||||
unset( $args[$key] );
|
||||
$args[$keyA] = $arg;
|
||||
$key = $keyA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! array_key_exists($key, self::$_args) )
|
||||
{
|
||||
throw new Exception('Param "'.$key.'" is invalid!');
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( self::$_args as $key => $arg )
|
||||
{
|
||||
if( self::$_args[$key]['value'] === NULL AND !array_key_exists($key, $args) )
|
||||
{
|
||||
throw new Exception('Param "'.$key.'" must be declared!');
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare help
|
||||
* @return array
|
||||
*/
|
||||
public static function get_help()
|
||||
{
|
||||
$output = array();
|
||||
|
||||
foreach ( self::$_args as $arg => $item )
|
||||
{
|
||||
$output[$arg] = $item['description'];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
249
inc/3rdparty/libraries/send2kindle/readability.php
vendored
249
inc/3rdparty/libraries/send2kindle/readability.php
vendored
|
@ -1,249 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* PHP Readability
|
||||
*
|
||||
* Readability PHP 版本,详见
|
||||
* http://code.google.com/p/arc90labs-readability/
|
||||
*
|
||||
* ChangeLog:
|
||||
*
|
||||
* [+] 2011-02-17 初始化版本
|
||||
*
|
||||
* @author mingcheng<i.feelinglucky#gmail.com>
|
||||
* @date 2011-02-17
|
||||
* @link http://www.gracecode.com/
|
||||
*/
|
||||
|
||||
define("READABILITY_VERSION", 0.12);
|
||||
|
||||
class Readability2 {
|
||||
// 保存判定结果的标记位名称
|
||||
const ATTR_CONTENT_SCORE = "contentScore";
|
||||
|
||||
// DOM 解析类目前只支持 UTF-8 编码
|
||||
const DOM_DEFAULT_CHARSET = "utf-8";
|
||||
|
||||
// 当判定失败时显示的内容
|
||||
const MESSAGE_CAN_NOT_GET = "Sorry, readability was unable to parse this page for content. \n
|
||||
If you feel like it should have been able to,
|
||||
please let me know by mail: lucky[at]gracecode.com";
|
||||
|
||||
// DOM 解析类(PHP5 已内置)
|
||||
protected $DOM = null;
|
||||
|
||||
// 需要解析的源代码
|
||||
protected $source = "";
|
||||
|
||||
// 章节的父元素列表
|
||||
private $parentNodes = array();
|
||||
|
||||
// 需要删除的标签
|
||||
private $junkTags = Array("style", "form", "iframe", "script", "button", "input", "textarea");
|
||||
|
||||
// 需要删除的属性
|
||||
private $junkAttrs = Array("style", "class", "onclick", "onmouseover", "align", "border", "margin");
|
||||
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param $input_char 字符串的编码。默认 utf-8,可以省略
|
||||
*/
|
||||
function __construct($source, $input_char = "utf-8") {
|
||||
$this->source = $source;
|
||||
|
||||
// DOM 解析类只能处理 UTF-8 格式的字符
|
||||
$source = mb_convert_encoding($source, 'HTML-ENTITIES', $input_char);
|
||||
|
||||
// 预处理 HTML 标签,剔除冗余的标签等
|
||||
$source = $this->preparSource($source);
|
||||
|
||||
// 生成 DOM 解析类
|
||||
$this->DOM = new DOMDocument('1.0', $input_char);
|
||||
try {
|
||||
//libxml_use_internal_errors(true);
|
||||
// 会有些错误信息,不过不要紧 :^)
|
||||
if (!@$this->DOM->loadHTML('<?xml encoding="'.Readability2::DOM_DEFAULT_CHARSET.'">'.$source)) {
|
||||
throw new Exception("Parse HTML Error!");
|
||||
}
|
||||
|
||||
foreach ($this->DOM->childNodes as $item) {
|
||||
if ($item->nodeType == XML_PI_NODE) {
|
||||
$this->DOM->removeChild($item); // remove hack
|
||||
}
|
||||
}
|
||||
|
||||
// insert proper
|
||||
$this->DOM->encoding = Readability2::DOM_DEFAULT_CHARSET;
|
||||
} catch (Exception $e) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 预处理 HTML 标签,使其能够准确被 DOM 解析类处理
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
private function preparSource($string) {
|
||||
// 剔除多余的 HTML 编码标记,避免解析出错
|
||||
preg_match("/charset=([\w|\-]+);?/", $string, $match);
|
||||
if (isset($match[1])) {
|
||||
$string = preg_replace("/charset=([\w|\-]+);?/", "", $string, 1);
|
||||
}
|
||||
|
||||
// Replace all doubled-up <BR> tags with <P> tags, and remove fonts.
|
||||
$string = preg_replace("/<br\/?>[ \r\n\s]*<br\/?>/i", "</p><p>", $string);
|
||||
$string = preg_replace("/<\/?font[^>]*>/i", "", $string);
|
||||
|
||||
return trim($string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除 DOM 元素中所有的 $TagName 标签
|
||||
*
|
||||
* @return DOMDocument
|
||||
*/
|
||||
private function removeJunkTag($RootNode, $TagName) {
|
||||
$Tags = $RootNode->getElementsByTagName($TagName);
|
||||
|
||||
$i = 0;
|
||||
while($Tag = $Tags->item($i++)) {
|
||||
$parentNode = $Tag->parentNode;
|
||||
$parentNode->removeChild($Tag);
|
||||
}
|
||||
|
||||
return $RootNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除元素中所有不需要的属性
|
||||
*/
|
||||
private function removeJunkAttr($RootNode, $Attr) {
|
||||
$Tags = $RootNode->getElementsByTagName("*");
|
||||
|
||||
$i = 0;
|
||||
while($Tag = $Tags->item($i++)) {
|
||||
$Tag->removeAttribute($Attr);
|
||||
}
|
||||
|
||||
return $RootNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据评分获取页面主要内容的盒模型
|
||||
* 判定算法来自:http://code.google.com/p/arc90labs-readability/
|
||||
*
|
||||
* @return DOMNode
|
||||
*/
|
||||
private function getTopBox() {
|
||||
// 获得页面所有的章节
|
||||
$allParagraphs = $this->DOM->getElementsByTagName("p");
|
||||
|
||||
// Study all the paragraphs and find the chunk that has the best score.
|
||||
// A score is determined by things like: Number of <p>'s, commas, special classes, etc.
|
||||
$i = 0;
|
||||
while($paragraph = $allParagraphs->item($i++)) {
|
||||
$parentNode = $paragraph->parentNode;
|
||||
$contentScore = intval($parentNode->getAttribute(Readability2::ATTR_CONTENT_SCORE));
|
||||
$className = $parentNode->getAttribute("class");
|
||||
$id = $parentNode->getAttribute("id");
|
||||
|
||||
// Look for a special classname
|
||||
if (preg_match("/(comment|meta|footer|footnote)/i", $className)) {
|
||||
$contentScore -= 50;
|
||||
} else if(preg_match(
|
||||
"/((^|\\s)(post|hentry|entry[-]?(content|text|body)?|article[-]?(content|text|body)?)(\\s|$))/i",
|
||||
$className)) {
|
||||
$contentScore += 25;
|
||||
}
|
||||
|
||||
// Look for a special ID
|
||||
if (preg_match("/(comment|meta|footer|footnote)/i", $id)) {
|
||||
$contentScore -= 50;
|
||||
} else if (preg_match(
|
||||
"/^(post|hentry|entry[-]?(content|text|body)?|article[-]?(content|text|body)?)$/i",
|
||||
$id)) {
|
||||
$contentScore += 25;
|
||||
}
|
||||
|
||||
// Add a point for the paragraph found
|
||||
// Add points for any commas within this paragraph
|
||||
if (strlen($paragraph->nodeValue) > 10) {
|
||||
$contentScore += strlen($paragraph->nodeValue);
|
||||
}
|
||||
|
||||
// 保存父元素的判定得分
|
||||
$parentNode->setAttribute(Readability2::ATTR_CONTENT_SCORE, $contentScore);
|
||||
|
||||
// 保存章节的父元素,以便下次快速获取
|
||||
array_push($this->parentNodes, $parentNode);
|
||||
}
|
||||
|
||||
$topBox = $this->DOM->createElement('div', Readability2::MESSAGE_CAN_NOT_GET);
|
||||
// Assignment from index for performance.
|
||||
// See http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5
|
||||
for ($i = 0, $len = sizeof($this->parentNodes); $i < $len; $i++) {
|
||||
$parentNode = $this->parentNodes[$i];
|
||||
$contentScore = intval($parentNode->getAttribute(Readability2::ATTR_CONTENT_SCORE));
|
||||
$orgContentScore = intval($topBox->getAttribute(Readability2::ATTR_CONTENT_SCORE));
|
||||
|
||||
if ($contentScore && $contentScore > $orgContentScore) {
|
||||
$topBox = $parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
// 此时,$topBox 应为已经判定后的页面内容主元素
|
||||
return $topBox;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 HTML 页面标题
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public function getTitle() {
|
||||
$title = $this->DOM->getElementsByTagName("title");
|
||||
return $title->item(0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取页面的主要内容(Readability 以后的内容)
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getContent() {
|
||||
if (!$this->DOM) return false;
|
||||
|
||||
// 获取页面标题
|
||||
$ContentTitle = $this->getTitle();
|
||||
|
||||
// 获取页面主内容
|
||||
$ContentBox = $this->getTopBox();
|
||||
|
||||
// 复制内容到新的 DOMDocument
|
||||
$Target = new DOMDocument;
|
||||
$Target->appendChild($Target->importNode($ContentBox, true));
|
||||
|
||||
// 删除不需要的标签
|
||||
foreach ($this->junkTags as $tag) {
|
||||
$Target = $this->removeJunkTag($Target, $tag);
|
||||
}
|
||||
|
||||
// 删除不需要的属性
|
||||
foreach ($this->junkAttrs as $attr) {
|
||||
$Target = $this->removeJunkAttr($Target, $attr);
|
||||
}
|
||||
|
||||
// 多个数据,以数组的形式返回
|
||||
return Array(
|
||||
'title' => $ContentTitle ? $ContentTitle->nodeValue : "",
|
||||
'content' => $Target->saveHTML()
|
||||
);
|
||||
}
|
||||
|
||||
function __destruct() { }
|
||||
}
|
69
inc/3rdparty/libraries/send2kindle/send.php
vendored
69
inc/3rdparty/libraries/send2kindle/send.php
vendored
|
@ -1,69 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Send to kindle email
|
||||
* @author jwest <jwest@jwest.pl>
|
||||
*/
|
||||
class Send {
|
||||
|
||||
/**
|
||||
* Your kindle email
|
||||
* @var string
|
||||
*/
|
||||
private $_kindle_email;
|
||||
|
||||
/**
|
||||
* Your email (must be added on amazon)
|
||||
* @var string
|
||||
*/
|
||||
private $_email;
|
||||
|
||||
/**
|
||||
* Prepare mail
|
||||
* @param string $kindle_email your kindle email
|
||||
* @param string $email email for send to kindle
|
||||
*/
|
||||
public function __construct($kindle_email, $email)
|
||||
{
|
||||
$this->_kindle_email = $kindle_email;
|
||||
$this->_email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send file
|
||||
* @param string $file path to file
|
||||
* @return bool
|
||||
*/
|
||||
public function send($file)
|
||||
{
|
||||
//prepare file
|
||||
$file_size = filesize($file);
|
||||
$filename = basename($file);
|
||||
$handle = fopen($file, "r");
|
||||
$content = fread($handle, $file_size);
|
||||
fclose($handle);
|
||||
$content = chunk_split(base64_encode($content));
|
||||
|
||||
$uid = md5(uniqid(time()));
|
||||
|
||||
//generate header for mail
|
||||
$header = "From: News2Kindle <".$this->_email.">\r\n";
|
||||
$header .= "MIME-Version: 1.0\r\n";
|
||||
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
|
||||
$header .= "This is a multi-part message in MIME format.\r\n";
|
||||
$header .= "--".$uid."\r\n";
|
||||
$header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
|
||||
$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
|
||||
$header .= "send via News2Kindle script\r\n\r\n";
|
||||
$header .= "--".$uid."\r\n";
|
||||
$header .= "Content-Type: application/x-mobipocket-ebook; name=\"".$filename."\"\r\n";
|
||||
$header .= "Content-Transfer-Encoding: base64\r\n";
|
||||
$header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
|
||||
$header .= $content."\r\n\r\n";
|
||||
$header .= "--".$uid."--";
|
||||
|
||||
//send mail
|
||||
return mail( $this->_kindle_email, '[newsToKindle] ' . $filename, "", $header );
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
230
inc/3rdparty/libraries/send2kindle/storage.php
vendored
230
inc/3rdparty/libraries/send2kindle/storage.php
vendored
|
@ -1,230 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Storage for news2Kindle
|
||||
* @author jwest <jwest@jwest.pl>
|
||||
*/
|
||||
class Storage {
|
||||
|
||||
/**
|
||||
* Newspapper name
|
||||
* @var string
|
||||
*/
|
||||
private $_name;
|
||||
|
||||
/**
|
||||
* Default dir
|
||||
* @var string
|
||||
*/
|
||||
private $_default_dir = 'data/';
|
||||
|
||||
/**
|
||||
* Info about newspapper
|
||||
* @var array
|
||||
*/
|
||||
private $_info;
|
||||
|
||||
/**
|
||||
* Prepare storage
|
||||
* @param string $newspapper
|
||||
* @param string $default_dir
|
||||
*/
|
||||
public function __construct($newspapper, $default_dir = NULL)
|
||||
{
|
||||
$this->_name = $newspapper;
|
||||
|
||||
if ( $default_dir !== NULL )
|
||||
{
|
||||
$this->_default_dir = $default_dir;
|
||||
}
|
||||
|
||||
$this->_info = $this->_get_info();
|
||||
}
|
||||
|
||||
/**
|
||||
* save info before exit from script
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->_save_info($this->_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path
|
||||
* @param bool $newspapper path to newspapper
|
||||
* @return string path to repository
|
||||
*/
|
||||
public function get_path($newspapper = true)
|
||||
{
|
||||
$path = $this->_default_dir;
|
||||
|
||||
if ( $newspapper )
|
||||
{
|
||||
$path .= $this->_name . '/';
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about newspapper
|
||||
* @return array newspapper info
|
||||
*/
|
||||
private function _get_info()
|
||||
{
|
||||
$content = unserialize( $this->_get_file('info.dat') );
|
||||
|
||||
if( $content === FALSE )
|
||||
{
|
||||
$content = (object) array
|
||||
(
|
||||
'images_count' => 0,
|
||||
'articles_count' => 0,
|
||||
'images' => array(),
|
||||
);
|
||||
|
||||
$this->_save_info($content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info key
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function info($key)
|
||||
{
|
||||
return $this->_info->$key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save info
|
||||
* @param array $info info from class
|
||||
*/
|
||||
private function _save_info($info)
|
||||
{
|
||||
$this->_save_file( 'info.dat', serialize($info) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save image in storage
|
||||
* @param resource $image
|
||||
* @param string $name image name, if null create auto name
|
||||
* @return string image name
|
||||
*/
|
||||
public function save_image($image, $name = NULL)
|
||||
{
|
||||
if ( $name === NULL )
|
||||
{
|
||||
$image_name = (string) $this->_info->images_count;
|
||||
|
||||
for ($i=strlen($image_name); $i<6; $i++)
|
||||
{
|
||||
$image_name = '0'.$image_name;
|
||||
}
|
||||
|
||||
$this->_info->images_count++;
|
||||
$this->_info->images[$this->_info->images_count] = $image_name;
|
||||
|
||||
$name = $image_name;
|
||||
}
|
||||
|
||||
$this->_save_file($name, $image);
|
||||
|
||||
return $this->_default_dir . $this->_name . '/' . $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image
|
||||
* @param string $name image name
|
||||
* @return resource
|
||||
*/
|
||||
public function get_image($name)
|
||||
{
|
||||
return $this->_get_file($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put article contents
|
||||
* @param string $id unique id for article
|
||||
* @param string $title
|
||||
* @param string $content article content
|
||||
* @param string $url url for article
|
||||
* @param object $website
|
||||
*/
|
||||
public function add_content($id, $title, $content, $url, $website)
|
||||
{
|
||||
$articles = unserialize( $this->_get_file('articles.dat') );
|
||||
|
||||
$articles[$id] = (object) array
|
||||
(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'content' => $content,
|
||||
'url' => $url,
|
||||
'website' => $website,
|
||||
);
|
||||
|
||||
$this->_save_file( 'articles.dat', serialize($articles) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get articles contents
|
||||
* @param string $file_name
|
||||
* @param string $file_content
|
||||
*/
|
||||
public function get_contents()
|
||||
{
|
||||
return unserialize( $this->_get_file( 'articles.dat' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file content
|
||||
* @param string $file_name
|
||||
* @param string $file_content
|
||||
*/
|
||||
private function _save_file($file_name, $file_content)
|
||||
{
|
||||
if( ! file_exists( $this->_default_dir . $this->_name ) )
|
||||
{
|
||||
mkdir( $this->_default_dir . $this->_name, 0777, TRUE );
|
||||
}
|
||||
|
||||
file_put_contents($this->_default_dir . $this->_name . '/' . $file_name, $file_content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file content
|
||||
* @param string $file_name
|
||||
* @param string $default_file_content (if file not exists)
|
||||
* @return string file content
|
||||
*/
|
||||
private function _get_file($file_name, $default_file_content = NULL)
|
||||
{
|
||||
$content = @file_get_contents($this->_default_dir . $this->_name . '/' . $file_name);
|
||||
|
||||
if ($content === FALSE)
|
||||
{
|
||||
return $default_file_content;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean newspapper after convert to mobi
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
$files_to_remove = glob($this->_default_dir . $this->_name . '/*');
|
||||
|
||||
foreach ( $files_to_remove as $file )
|
||||
{
|
||||
unlink( $file );
|
||||
}
|
||||
|
||||
rmdir( $this->_default_dir . $this->_name );
|
||||
}
|
||||
|
||||
}
|
37
inc/3rdparty/libraries/send2kindle/utils.php
vendored
37
inc/3rdparty/libraries/send2kindle/utils.php
vendored
|
@ -1,37 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Utils for news2kindle
|
||||
* @author jwest <jwest@jwest.pl>
|
||||
*/
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* URL encode
|
||||
* @param string $url
|
||||
* @return string $ar_url
|
||||
*/
|
||||
public static function urlencode( $url )
|
||||
{
|
||||
$ar_url = explode( '/', $url );
|
||||
|
||||
foreach ( $ar_url as $key => $val )
|
||||
{
|
||||
$ar_url[ $key ] = urlencode( $val );
|
||||
}
|
||||
|
||||
return implode('/', $ar_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare ID for google rss article
|
||||
* @param string $id
|
||||
* @return string
|
||||
*/
|
||||
public static function prepare_id($id)
|
||||
{
|
||||
$char_in = array('/', '.', ',', ':');
|
||||
$id = str_replace($char_in, '-', $id);
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
|
@ -112,12 +112,15 @@ class Routing
|
|||
$this->wallabag->deleteUser($_POST['password4deletinguser']);
|
||||
} elseif (isset($_GET['epub'])) {
|
||||
$epub = new WallabagEpub($this->wallabag, $_GET['method'], $_GET['value']);
|
||||
$epub->prepareData();
|
||||
$epub->produceEpub();
|
||||
} elseif (isset($_GET['mobi'])) {
|
||||
$mobi = new WallabagMobi($this->wallabag, $_GET['method'], $_GET['value']);
|
||||
$mobi->prepareData();
|
||||
$mobi->produceMobi();
|
||||
} elseif (isset($_GET['pdf'])) {
|
||||
$pdf = new WallabagPDF($this->wallabag, $_GET['method'], $_GET['value']);
|
||||
$pdf->prepareData();
|
||||
$pdf->producePDF();
|
||||
} elseif (isset($_GET['import'])) {
|
||||
$import = $this->wallabag->import();
|
||||
|
|
|
@ -30,34 +30,35 @@ class WallabagEBooks
|
|||
case 'id':
|
||||
$entryID = filter_var($this->value, FILTER_SANITIZE_NUMBER_INT);
|
||||
$entry = $this->wallabag->store->retrieveOneById($entryID, $this->wallabag->user->getId());
|
||||
$entries = array($entry);
|
||||
$bookTitle = $entry['title'];
|
||||
$bookFileName = substr($bookTitle, 0, 200);
|
||||
$this->entries = array($entry);
|
||||
$this->bookTitle = $entry['title'];
|
||||
$this->bookFileName = substr($this->bookTitle, 0, 200);
|
||||
break;
|
||||
case 'all':
|
||||
$entries = $this->wallabag->store->retrieveAll($this->wallabag->user->getId());
|
||||
$bookTitle = sprintf(_('All my articles on '), date(_('d.m.y'))); #translatable because each country has it's own date format system
|
||||
$bookFileName = _('Allarticles') . date(_('dmY'));
|
||||
$this->entries = $this->wallabag->store->retrieveAll($this->wallabag->user->getId());
|
||||
$this->bookTitle = sprintf(_('All my articles on '), date(_('d.m.y'))); #translatable because each country has it's own date format system
|
||||
$this->bookFileName = _('Allarticles') . date(_('dmY'));
|
||||
break;
|
||||
case 'tag':
|
||||
$tag = filter_var($this->value, FILTER_SANITIZE_STRING);
|
||||
$tags_id = $this->wallabag->store->retrieveAllTags($this->wallabag->user->getId(), $tag);
|
||||
$tag_id = $tags_id[0]["id"]; // we take the first result, which is supposed to match perfectly. There must be a workaround.
|
||||
$entries = $this->wallabag->store->retrieveEntriesByTag($tag_id, $this->wallabag->user->getId());
|
||||
$bookTitle = sprintf(_('Articles tagged %s'), $tag);
|
||||
$bookFileName = substr(sprintf(_('Tag %s'), $tag), 0, 200);
|
||||
$this->entries = $this->wallabag->store->retrieveEntriesByTag($tag_id, $this->wallabag->user->getId());
|
||||
$this->bookTitle = sprintf(_('Articles tagged %s'), $tag);
|
||||
$this->bookFileName = substr(sprintf(_('Tag %s'), $tag), 0, 200);
|
||||
break;
|
||||
case 'category':
|
||||
$category = filter_var($this->value, FILTER_SANITIZE_STRING);
|
||||
$entries = $this->wallabag->store->getEntriesByView($category, $this->wallabag->user->getId());
|
||||
$bookTitle = sprintf(_('All articles in category %s'), $category);
|
||||
$bookFileName = substr(sprintf(_('Category %s'), $category), 0, 200);
|
||||
$this->entries = $this->wallabag->store->getEntriesByView($category, $this->wallabag->user->getId());
|
||||
$this->bookTitle = sprintf(_('All articles in category %s'), $category);
|
||||
$this->bookFileName = substr(sprintf(_('Category %s'), $category), 0, 200);
|
||||
break;
|
||||
case 'search':
|
||||
$search = filter_var($this->value, FILTER_SANITIZE_STRING);
|
||||
$entries = $this->store->search($search, $this->wallabag->user->getId());
|
||||
$bookTitle = sprintf(_('All articles for search %s'), $search);
|
||||
$bookFileName = substr(sprintf(_('Search %s'), $search), 0, 200);
|
||||
Tools::logm($search);
|
||||
$this->entries = $this->wallabag->store->search($search, $this->wallabag->user->getId());
|
||||
$this->bookTitle = sprintf(_('All articles for search %s'), $search);
|
||||
$this->bookFileName = substr(sprintf(_('Search %s'), $search), 0, 200);
|
||||
break;
|
||||
case 'default':
|
||||
die(_('Uh, there is a problem while generating epub.'));
|
||||
|
@ -94,7 +95,7 @@ class WallabagEpub extends WallabagEBooks
|
|||
$log->logLine("getCurrentServerURL: " . $book->getCurrentServerURL());
|
||||
$log->logLine("getCurrentPageURL..: " . $book->getCurrentPageURL());
|
||||
|
||||
$book->setTitle($bookTitle);
|
||||
$book->setTitle($this->bookTitle);
|
||||
$book->setIdentifier("http://$_SERVER[HTTP_HOST]", EPub::IDENTIFIER_URI); // Could also be the ISBN number, prefered for published books, or a UUID.
|
||||
//$book->setLanguage("en"); // Not needed, but included for the example, Language is mandatory, but EPub defaults to "en". Use RFC3066 Language codes, such as "en", "da", "fr" etc.
|
||||
$book->setDescription(_("Some articles saved on my wallabag"));
|
||||
|
@ -111,7 +112,7 @@ class WallabagEpub extends WallabagEBooks
|
|||
|
||||
$log->logLine("Add Cover");
|
||||
|
||||
$fullTitle = "<h1> " . $bookTitle . "</h1>\n";
|
||||
$fullTitle = "<h1> " . $this->bookTitle . "</h1>\n";
|
||||
|
||||
$book->setCoverImage("Cover.png", file_get_contents("themes/baggy/img/apple-touch-icon-152.png"), "image/png", $fullTitle);
|
||||
|
||||
|
@ -122,7 +123,7 @@ class WallabagEpub extends WallabagEBooks
|
|||
|
||||
$book->buildTOC();
|
||||
|
||||
foreach ($entries as $entry) { //set tags as subjects
|
||||
foreach ($this->entries as $entry) { //set tags as subjects
|
||||
$tags = $this->wallabag->store->retrieveTagsByEntry($entry['id']);
|
||||
foreach ($tags as $tag) {
|
||||
$book->setSubject($tag['value']);
|
||||
|
@ -139,97 +140,82 @@ class WallabagEpub extends WallabagEBooks
|
|||
$book->addChapter("Log", "Log.html", $content_start . $log->getLog() . "\n</pre>" . $bookEnd); // log generation
|
||||
}
|
||||
$book->finalize();
|
||||
$zipData = $book->sendBook($bookFileName);
|
||||
$zipData = $book->sendBook($this->bookFileName);
|
||||
}
|
||||
}
|
||||
|
||||
class WallabagMobi extends WallabagEBooks
|
||||
{
|
||||
/**
|
||||
* Adapted from News2Kindle
|
||||
* @author Jakub Westfalewski <jwest@jwest.pl>
|
||||
*
|
||||
* MOBI Class
|
||||
* @author Sander Kromwijk
|
||||
*/
|
||||
|
||||
public function produceMobi()
|
||||
public function produceMobi($send = FALSE)
|
||||
{
|
||||
$storage = new Storage('static');
|
||||
$this->prepareData();
|
||||
foreach ($entries as $i => $item) {
|
||||
$content = $item['content'];
|
||||
$images = new Images($storage, $content);
|
||||
$content = $images->convert();
|
||||
$storage->add_content
|
||||
(
|
||||
md5($item['title']),
|
||||
mb_convert_encoding($item['title'], 'HTML-ENTITIES', 'utf-8'),
|
||||
$content,
|
||||
$item['url']],
|
||||
""
|
||||
);
|
||||
}
|
||||
$articles = $storage->get_contents();
|
||||
$toc = array();
|
||||
$articles_count = count($articles);
|
||||
|
||||
foreach($articles as $article){
|
||||
if(array_key_exists($article->website->title, $toc)){
|
||||
$toc[$article->website->title]->articles[] = $article;
|
||||
}else{
|
||||
$toc[$article->website->title] = (object)array(
|
||||
'articles' => array($article),
|
||||
'title' => $article->website->title,
|
||||
'streamId' => $article->website->streamId,
|
||||
'url' => $article->website->htmlUrl,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# Good try
|
||||
$mobi = new MOBI();
|
||||
$mobi->setData($content);
|
||||
$mobi->setOptions(array(
|
||||
'title' => 'Articles from '.date('Y-m-d'),
|
||||
'author' => 'wallabag',
|
||||
'subject' => 'Articles from '.date('Y-m-d'),
|
||||
));
|
||||
|
||||
$images = array();
|
||||
$content = new MOBIFile();
|
||||
|
||||
//prepare images for mobi format
|
||||
foreach ( $storage->info('images') as $n => $image )
|
||||
{
|
||||
$images[$n] = new FileRecord(new Record(file_get_contents($storage->get_path() . $image)));
|
||||
$content->set("title", $this->bookTitle);
|
||||
$content->set("author", "wallabag");
|
||||
|
||||
# introduction
|
||||
//$content->appendChapterTitle("Cover");
|
||||
$content->appendParagraph('<div style="text-align:center;"><p>' . _('Produced by wallabag with PHPMobi') . '</p><p>'. _('Please open <a href="https://github.com/wallabag/wallabag/issues" >an issue</a> if you have trouble with the display of this E-Book on your device.') . '</p></div>');
|
||||
$content->appendImage(imagecreatefrompng("themes/baggy/img/apple-touch-icon-152.png"));
|
||||
$content->appendPageBreak();
|
||||
|
||||
foreach ($this->entries as $item) {
|
||||
$content->appendChapterTitle($item['title']);
|
||||
$content->appendParagraph($item['content']);
|
||||
$content->appendPageBreak();
|
||||
}
|
||||
$mobi->setContentProvider($content);
|
||||
|
||||
$mobi->setImages($images);
|
||||
$mobi->save( $storage->get_path(FALSE) . 'articles-' . date('Y-m-d') . '.mobi');
|
||||
|
||||
$storage->clean();
|
||||
|
||||
if ($send) {
|
||||
$files = glob($storage->get_path(FALSE).'*.mobi');
|
||||
$mail = new Send(KINDLEMAIL,MAIL);
|
||||
foreach ( $files as $file_mobi )
|
||||
{
|
||||
$mail->send( $file_mobi );
|
||||
}
|
||||
// clean cache
|
||||
foreach ( $files as $file_mobi )
|
||||
{
|
||||
unlink( $file_mobi );
|
||||
}
|
||||
}
|
||||
}
|
||||
$mobi->download($this->bookFileName.".mobi");
|
||||
}
|
||||
}
|
||||
|
||||
class WallabagPDF extends WallabagEbooks
|
||||
{
|
||||
public function producePDF()
|
||||
{
|
||||
//$this->prepareData();
|
||||
$mpdf = new mPDF('c');
|
||||
|
||||
$mpdf->WriteHTML($html);
|
||||
$mpdf->Output();
|
||||
exit;
|
||||
# intro
|
||||
|
||||
$html = '<h1>' . $this->bookTitle . '</h1><img src="themes/baggy/img/apple-touch-icon-152.png" />';
|
||||
|
||||
foreach ($this->entries as $item) {
|
||||
$html .= '<h1>' . $item['title'] . '</h1>';
|
||||
$html .= '<indexentry content="'. $item['title'] .'" />';
|
||||
$html .= $item['content'];
|
||||
}
|
||||
|
||||
//$mpdf->h2toc = array('H1'=>0);
|
||||
|
||||
# headers
|
||||
$mpdf->SetHeader('{DATE j-m-Y}|{PAGENO}/{nb}|Produced with wallabag');
|
||||
$mpdf->SetFooter('{PAGENO}');
|
||||
|
||||
$mpdf->WriteHTML($html);
|
||||
|
||||
# remove characters that make mpdf bug
|
||||
$char_in = array('/', '.', ',', ':', '|');
|
||||
$pdfExportName = preg_replace('/\s+/', '-', str_replace($char_in, '-', $this->bookFileName . '.pdf'));
|
||||
|
||||
$mpdf->Output('cache/' . $pdfExportName);
|
||||
|
||||
header('Content-Disposition: attachment; filename="' . $pdfExportName . '"');
|
||||
|
||||
header('Content-Transfer-Encoding: base64');
|
||||
header('Content-Type: application/pdf');
|
||||
echo file_get_contents('cache/' . $pdfExportName);
|
||||
|
||||
//exit;
|
||||
}
|
||||
}
|
|
@ -42,11 +42,7 @@ require_once INCLUDES . '/3rdparty/libraries/PHPePub/EPub.php';
|
|||
require_once INCLUDES . '/3rdparty/libraries/PHPePub/EPubChapterSplitter.php';
|
||||
|
||||
# mobi library
|
||||
require_once INCLUDES . '/3rdparty/libraries/send2kindle/send.php';
|
||||
require_once INCLUDES . '/3rdparty/libraries/send2kindle/images.php';
|
||||
require_once INCLUDES . '/3rdparty/libraries/send2kindle/storage.php';
|
||||
require_once INCLUDES . '/3rdparty/libraries/send2kindle/MOBIClass/MOBI.php';
|
||||
require_once INCLUDES . '/3rdparty/libraries/send2kindle/utils.php';
|
||||
require_once INCLUDES . '/3rdparty/libraries/MOBIClass/MOBI.php';
|
||||
|
||||
# pdf library
|
||||
require_once INCLUDES . '/3rdparty/libraries/mpdf/mpdf.php';
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<input type="submit" value="{% trans "bag it!" %}" />
|
||||
</form>
|
||||
</li>
|
||||
<li>{% trans "Bookmarklet: drag & drop this link to your bookmarks bar" %} <a id="bookmarklet" ondragend="this.click();" title="i am a bookmarklet, use me !" href="javascript:if(top['bookmarklet-url@wallabag.org']){top['bookmarklet-url@wallabag.org'];}else{(function(){var%20url%20=%20location.href%20||%20url;window.open('{{ poche_url }}?action=add&url='%20+%20btoa(url),'_self');})();void(0);}">{% trans "bag it!" %}</a></li>
|
||||
<li>{% trans "Bookmarklet: drag & drop this link to your bookmarks bar" %} <a id="bookmarklet" ondragend="this.click();" title="i am a bookmarklet, use me !" href="javascript:if(top['bookmarklet-url@wallabag.org']){top['bookmarklet-url@wallabag.org'];}else{(function(){var%20url%20=%20location.href%20||%20url;window.open('{{ poche_url }}?action=add&url='%20+%20btoa(url),'_self');})();void(0);}">{% trans "bag it!" %}</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>{% trans "Upgrading wallabag" %}</h2>
|
||||
|
@ -126,7 +126,13 @@
|
|||
<p><a href="?export" target="_blank">{% trans "Click here" %}</a> {% trans "to export your wallabag data." %}</p>
|
||||
|
||||
<h2>{% trans "Fancy an E-Book ?" %}</h2>
|
||||
<p>{% trans "Click on <a href=\"./?epub&method=all\" title=\"Generate ePub\">this link</a> to get all your articles in one ebook (ePub 3 format)." %}
|
||||
<p>{% trans "Click to get all your articles in one ebook :" %}
|
||||
<ul>
|
||||
<li><a href="./?epub&method=all" title="Generate ePub file">ePub 3</a></li>
|
||||
<li><a href="./?mobi&method=all" title="Generate Mobi file">Mobi</a></li>
|
||||
<li><a href="./?pdf&method=all" title="Generate PDF file">PDF</a></li>
|
||||
</ul>
|
||||
|
||||
<br>{% trans "This can <b>take a while</b> and can <b>even fail</b> if you have too many articles, depending on your server configuration." %}</p>
|
||||
|
||||
<h2>{% trans "Cache" %}</h2>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
{% if entry.content| getReadingTime > 0 %}
|
||||
<div class="estimatedTime"><a target="_blank" title="{% trans "estimated reading time:" %} {{ entry.content| getReadingTime }} min" class="tool reading-time"><span>{% trans "estimated reading time :" %} {{ entry.content| getReadingTime }} min</span></div>
|
||||
{% else %}
|
||||
<div class="estimatedTime"><a target="_blank" title="{% trans "estimated reading time:" %} {{ entry.content| getReadingTime }} min" class="tool reading-time"><span>{% trans "estimated reading time :" %} <small class="inferieur"><</small> 1 min</span></div>
|
||||
<div class="estimatedTime"><a target="_blank" title="{% trans "estimated reading time:" %} {{ entry.content| getReadingTime }} min" class="tool reading-time"><span>{% trans "estimated reading time :" %} <small class="inferieur"></small> 1 min</span></div>
|
||||
{% endif %}
|
||||
<ul class="tools links">
|
||||
<li><a title="{% trans "Toggle mark as read" %}" class="tool icon-check icon {% if entry.is_read == 0 %}archive-off{% else %}archive{% endif %}" href="./?action=toggle_archive&id={{ entry.id|e }}"><span>{% trans "Toggle mark as read" %}</span></a></li>
|
||||
|
@ -59,11 +59,21 @@
|
|||
{{ block('pager') }}
|
||||
{% if view == 'home' %}{% if nb_results > 1 %}<a title="{% trans "Mark all the entries as read" %}" href="./?action=archive_all">{{ "Mark all the entries as read" }}</a>{% endif %}{% endif %}
|
||||
|
||||
{% if search_term is defined %}<a title="{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}" href="./?action=add_tag&search={{ search_term }}">{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}</a>{% endif %}
|
||||
{% if search_term is defined %}<a title="{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}" href="./?action=add_tag&search={{ search_term }}">{% trans %} Apply the tag {{ search_term }} to this search {% endtrans %}</a>{% endif %}
|
||||
|
||||
{% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&method=tag&value={{ tag.value }}">{% trans "Download the articles from this tag in an epub" %}</a>
|
||||
{% elseif search_term is defined %}<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&method=search&value={{ search_term }}">{% trans "Download the articles from this search in an epub" %}</a>
|
||||
{% else %}<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&method=category&value={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
|
||||
{% if tag %}
|
||||
<a title="{% trans "Download the articles from this tag in an epub file" %}" href="./?epub&method=tag&value={{ tag.value }}">{% trans "Download as ePub3" %}</a>
|
||||
<a title="{% trans "Download the articles from this tag in a mobi file" %}" href="./?mobi&method=tag&value={{ tag.value }}">{% trans "Download as Mobi" %}</a>
|
||||
<a title="{% trans "Download the articles from this tag in a pdf file" %}" href="./?pdf&method=tag&value={{ tag.value }}">{% trans "Download as PDF" %}</a>
|
||||
{% elseif search_term is defined %}
|
||||
<a title="{% trans "Download the articles from this search in an epub" %}" href="./?epub&method=search&value={{ search_term }}">{% trans "Download as ePub3" %}</a>
|
||||
<a title="{% trans "Download the articles from this search in a mobi file" %}" href="./?mobi&method=search&value={{ search_term }}">{% trans "Download as Mobi" %}</a>
|
||||
<a title="{% trans "Download the articles from this search in a pdf file" %}" href="./?pdf&method=search&value={{ search_term }}">{% trans "Download as PDF" %}</a>
|
||||
{% else %}
|
||||
<a title="{% trans "Download the articles from this category in an epub" %}" href="./?epub&method=category&value={{ view }}">{% trans "Download as ePub3" %}</a>
|
||||
<a title="{% trans "Download the articles from this category in a mobi file" %}" href="./?mobi&method=category&value={{ view }}">{% trans "Download as Mobi" %}</a>
|
||||
<a title="{% trans "Download the articles from this category in a pdf file" %}" href="./?pdf&method=category&value={{ view }}">{% trans "Download as PDF" %}</a>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
{% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool flattr icon icon-flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span></a></li>{% elseif flattr.status == constant('FLATTRED') %}<li><a href="{{ flattr.flattrItemURL }}" class="tool flattr icon icon-flattr" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span> ({{ flattr.numflattrs }})</a></li>{% endif %}{% endif %}
|
||||
{% if constant('SHOW_PRINTLINK') == 1 %}<li><a title="{% trans "Print" %}" class="tool icon icon-print" href="javascript: window.print();"><span>{% trans "Print" %}</span></a></li>{% endif %}
|
||||
<li><a href="./?epub&method=id&value={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
|
||||
<li><a href="./?mobi&method=id&value={{ entry.id|e }}" title="Generate mobi file">MOBI</a></li>
|
||||
<li><a href="./?pdf&method=id&value={{ entry.id|e }}" title="Generate epub file">PDF</a></li>
|
||||
<li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&body={{ entry.url|url_encode }}" title="{% trans "Does this article appear wrong?" %}" class="tool bad-display icon icon-delete"><span>{% trans "Does this article appear wrong?" %}</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue