Merge branch 'epub' into dev

Conflicts:
	themes/baggy/home.twig
This commit is contained in:
tcit 2014-05-16 16:31:18 +02:00
commit 404adf970d
23 changed files with 6697 additions and 195 deletions

View File

@ -0,0 +1,266 @@
<?php
/**
* This should be a complete list of all HTML entities, mapped to their UTF-8 character codes.
*
* @author A. Grandt
* @copyright A. Grandt 2009-2013
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @version 3.00
*/
global $htmlEntities;
$htmlEntities = array();
$htmlEntities["&quot;"] ="\x22"; // &#34; ((double) quotation mark)
$htmlEntities["&amp;"] ="\x26"; // &#38; (ampersand)
$htmlEntities["&apos;"] ="\x27"; // &#39; (apostrophe = apostrophe-quote)
$htmlEntities["&lt;"] ="\x3C"; // &#60; (less-than sign)
$htmlEntities["&gt;"] ="\x3E"; // &#62; (greater-than sign)
$htmlEntities["&nbsp;"] ="\xC2\xA0"; // &#160; (non-breaking space)
$htmlEntities["&iexcl;"] ="\xC2\xA1"; // &#161; (inverted exclamation mark)
$htmlEntities["&cent;"] ="\xC2\xA2"; // &#162; (cent)
$htmlEntities["&pound;"] ="\xC2\xA3"; // &#163; (pound)
$htmlEntities["&curren;"] ="\xC2\xA4"; // &#164; (currency)
$htmlEntities["&yen;"] ="\xC2\xA5"; // &#165; (yen)
$htmlEntities["&brvbar;"] ="\xC2\xA6"; // &#166; (broken vertical bar)
$htmlEntities["&sect;"] ="\xC2\xA7"; // &#167; (section)
$htmlEntities["&uml;"] ="\xC2\xA8"; // &#168; (spacing diaeresis)
$htmlEntities["&copy;"] ="\xC2\xA9"; // &#169; (copyright)
$htmlEntities["&ordf;"] ="\xC2\xAA"; // &#170; (feminine ordinal indicator)
$htmlEntities["&laquo;"] ="\xC2\xAB"; // &#171; (angle quotation mark (left))
$htmlEntities["&not;"] ="\xC2\xAC"; // &#172; (negation)
$htmlEntities["&shy;"] ="\xC2\xAD"; // &#173; (soft hyphen)
$htmlEntities["&reg;"] ="\xC2\xAE"; // &#174; (registered trademark)
$htmlEntities["&macr;"] ="\xC2\xAF"; // &#175; (spacing macron)
$htmlEntities["&deg;"] ="\xC2\xB0"; // &#176; (degree)
$htmlEntities["&plusmn;"] ="\xC2\xB1"; // &#177; (plus-or-minus)
$htmlEntities["&sup2;"] ="\xC2\xB2"; // &#178; (superscript 2)
$htmlEntities["&sup3;"] ="\xC2\xB3"; // &#179; (superscript 3)
$htmlEntities["&acute;"] ="\xC2\xB4"; // &#180; (spacing acute)
$htmlEntities["&micro;"] ="\xC2\xB5"; // &#181; (micro)
$htmlEntities["&para;"] ="\xC2\xB6"; // &#182; (paragraph)
$htmlEntities["&middot;"] ="\xC2\xB7"; // &#183; (middle dot)
$htmlEntities["&cedil;"] ="\xC2\xB8"; // &#184; (spacing cedilla)
$htmlEntities["&sup1;"] ="\xC2\xB9"; // &#185; (superscript 1)
$htmlEntities["&ordm;"] ="\xC2\xBA"; // &#186; (masculine ordinal indicator)
$htmlEntities["&raquo;"] ="\xC2\xBB"; // &#187; (angle quotation mark (right))
$htmlEntities["&frac14;"] ="\xC2\xBC"; // &#188; (fraction 1/4)
$htmlEntities["&frac12;"] ="\xC2\xBD"; // &#189; (fraction 1/2)
$htmlEntities["&frac34;"] ="\xC2\xBE"; // &#190; (fraction 3/4)
$htmlEntities["&iquest;"] ="\xC2\xBF"; // &#191; (inverted question mark)
$htmlEntities["&Agrave;"] ="\xC3\x80"; // &#192; (capital a, grave accent)
$htmlEntities["&Aacute;"] ="\xC3\x81"; // &#193; (capital a, acute accent)
$htmlEntities["&Acirc;"] ="\xC3\x82"; // &#194; (capital a, circumflex accent)
$htmlEntities["&Atilde;"] ="\xC3\x83"; // &#195; (capital a, tilde)
$htmlEntities["&Auml;"] ="\xC3\x84"; // &#196; (capital a, umlaut mark)
$htmlEntities["&Aring;"] ="\xC3\x85"; // &#197; (capital a, ring)
$htmlEntities["&AElig;"] ="\xC3\x86"; // &#198; (capital ae)
$htmlEntities["&Ccedil;"] ="\xC3\x87"; // &#199; (capital c, cedilla)
$htmlEntities["&Egrave;"] ="\xC3\x88"; // &#200; (capital e, grave accent)
$htmlEntities["&Eacute;"] ="\xC3\x89"; // &#201; (capital e, acute accent)
$htmlEntities["&Ecirc;"] ="\xC3\x8A"; // &#202; (capital e, circumflex accent)
$htmlEntities["&Euml;"] ="\xC3\x8B"; // &#203; (capital e, umlaut mark)
$htmlEntities["&Igrave;"] ="\xC3\x8C"; // &#204; (capital i, grave accent)
$htmlEntities["&Iacute;"] ="\xC3\x8D"; // &#205; (capital i, acute accent)
$htmlEntities["&Icirc;"] ="\xC3\x8E"; // &#206; (capital i, circumflex accent)
$htmlEntities["&Iuml;"] ="\xC3\x8F"; // &#207; (capital i, umlaut mark)
$htmlEntities["&ETH;"] ="\xC3\x90"; // &#208; (capital eth, Icelandic)
$htmlEntities["&Ntilde;"] ="\xC3\x91"; // &#209; (capital n, tilde)
$htmlEntities["&Ograve;"] ="\xC3\x92"; // &#210; (capital o, grave accent)
$htmlEntities["&Oacute;"] ="\xC3\x93"; // &#211; (capital o, acute accent)
$htmlEntities["&Ocirc;"] ="\xC3\x94"; // &#212; (capital o, circumflex accent)
$htmlEntities["&Otilde;"] ="\xC3\x95"; // &#213; (capital o, tilde)
$htmlEntities["&Ouml;"] ="\xC3\x96"; // &#214; (capital o, umlaut mark)
$htmlEntities["&times;"] ="\xC3\x97"; // &#215; (multiplication)
$htmlEntities["&Oslash;"] ="\xC3\x98"; // &#216; (capital o, slash)
$htmlEntities["&Ugrave;"] ="\xC3\x99"; // &#217; (capital u, grave accent)
$htmlEntities["&Uacute;"] ="\xC3\x9A"; // &#218; (capital u, acute accent)
$htmlEntities["&Ucirc;"] ="\xC3\x9B"; // &#219; (capital u, circumflex accent)
$htmlEntities["&Uuml;"] ="\xC3\x9C"; // &#220; (capital u, umlaut mark)
$htmlEntities["&Yacute;"] ="\xC3\x9D"; // &#221; (capital y, acute accent)
$htmlEntities["&THORN;"] ="\xC3\x9E"; // &#222; (capital THORN, Icelandic)
$htmlEntities["&szlig;"] ="\xC3\x9F"; // &#223; (small sharp s, German)
$htmlEntities["&agrave;"] ="\xC3\xA0"; // &#224; (small a, grave accent)
$htmlEntities["&aacute;"] ="\xC3\xA1"; // &#225; (small a, acute accent)
$htmlEntities["&acirc;"] ="\xC3\xA2"; // &#226; (small a, circumflex accent)
$htmlEntities["&atilde;"] ="\xC3\xA3"; // &#227; (small a, tilde)
$htmlEntities["&auml;"] ="\xC3\xA4"; // &#228; (small a, umlaut mark)
$htmlEntities["&aring;"] ="\xC3\xA5"; // &#229; (small a, ring)
$htmlEntities["&aelig;"] ="\xC3\xA6"; // &#230; (small ae)
$htmlEntities["&ccedil;"] ="\xC3\xA7"; // &#231; (small c, cedilla)
$htmlEntities["&egrave;"] ="\xC3\xA8"; // &#232; (small e, grave accent)
$htmlEntities["&eacute;"] ="\xC3\xA9"; // &#233; (small e, acute accent)
$htmlEntities["&ecirc;"] ="\xC3\xAA"; // &#234; (small e, circumflex accent)
$htmlEntities["&euml;"] ="\xC3\xAB"; // &#235; (small e, umlaut mark)
$htmlEntities["&igrave;"] ="\xC3\xAC"; // &#236; (small i, grave accent)
$htmlEntities["&iacute;"] ="\xC3\xAD"; // &#237; (small i, acute accent)
$htmlEntities["&icirc;"] ="\xC3\xAE"; // &#238; (small i, circumflex accent)
$htmlEntities["&iuml;"] ="\xC3\xAF"; // &#239; (small i, umlaut mark)
$htmlEntities["&eth;"] ="\xC3\xB0"; // &#240; (small eth, Icelandic)
$htmlEntities["&ntilde;"] ="\xC3\xB1"; // &#241; (small n, tilde)
$htmlEntities["&ograve;"] ="\xC3\xB2"; // &#242; (small o, grave accent)
$htmlEntities["&oacute;"] ="\xC3\xB3"; // &#243; (small o, acute accent)
$htmlEntities["&ocirc;"] ="\xC3\xB4"; // &#244; (small o, circumflex accent)
$htmlEntities["&otilde;"] ="\xC3\xB5"; // &#245; (small o, tilde)
$htmlEntities["&ouml;"] ="\xC3\xB6"; // &#246; (small o, umlaut mark)
$htmlEntities["&divide;"] ="\xC3\xB7"; // &#247; (division)
$htmlEntities["&oslash;"] ="\xC3\xB8"; // &#248; (small o, slash)
$htmlEntities["&ugrave;"] ="\xC3\xB9"; // &#249; (small u, grave accent)
$htmlEntities["&uacute;"] ="\xC3\xBA"; // &#250; (small u, acute accent)
$htmlEntities["&ucirc;"] ="\xC3\xBB"; // &#251; (small u, circumflex accent)
$htmlEntities["&uuml;"] ="\xC3\xBC"; // &#252; (small u, umlaut mark)
$htmlEntities["&yacute;"] ="\xC3\xBD"; // &#253; (small y, acute accent)
$htmlEntities["&thorn;"] ="\xC3\xBE"; // &#254; (small thorn, Icelandic)
$htmlEntities["&yuml;"] ="\xC3\xBF"; // &#255; (small y, umlaut mark)
$htmlEntities["&OElig;"] ="\xC5\x92"; // &#338; (capital ligature OE)
$htmlEntities["&oelig;"] ="\xC5\x93"; // &#339; (small ligature oe)
$htmlEntities["&Scaron;"] ="\xC5\xA0"; // &#352; (capital S with caron)
$htmlEntities["&scaron;"] ="\xC5\xA1"; // &#353; (small S with caron)
$htmlEntities["&Yuml;"] ="\xC5\xB8"; // &#376; (capital Y with diaeres)
$htmlEntities["&fnof;"] ="\xC6\x92"; // &#402; (f with hook)
$htmlEntities["&circ;"] ="\xCB\x86"; // &#710; (modifier letter circumflex accent)
$htmlEntities["&tilde;"] ="\xCB\x9C"; // &#732; (small tilde)
$htmlEntities["&Alpha;"] ="\xCE\x91"; // &#913; (Alpha)
$htmlEntities["&Beta;"] ="\xCE\x92"; // &#914; (Beta)
$htmlEntities["&Gamma;"] ="\xCE\x93"; // &#915; (Gamma)
$htmlEntities["&Delta;"] ="\xCE\x94"; // &#916; (Delta)
$htmlEntities["&Epsilon;"] ="\xCE\x95"; // &#917; (Epsilon)
$htmlEntities["&Zeta;"] ="\xCE\x96"; // &#918; (Zeta)
$htmlEntities["&Eta;"] ="\xCE\x97"; // &#919; (Eta)
$htmlEntities["&Theta;"] ="\xCE\x98"; // &#920; (Theta)
$htmlEntities["&Iota;"] ="\xCE\x99"; // &#921; (Iota)
$htmlEntities["&Kappa;"] ="\xCE\x9A"; // &#922; (Kappa)
$htmlEntities["&Lambda;"] ="\xCE\x9B"; // &#923; (Lambda)
$htmlEntities["&Mu;"] ="\xCE\x9C"; // &#924; (Mu)
$htmlEntities["&Nu;"] ="\xCE\x9D"; // &#925; (Nu)
$htmlEntities["&Xi;"] ="\xCE\x9E"; // &#926; (Xi)
$htmlEntities["&Omicron;"] ="\xCE\x9F"; // &#927; (Omicron)
$htmlEntities["&Pi;"] ="\xCE\xA0"; // &#928; (Pi)
$htmlEntities["&Rho;"] ="\xCE\xA1"; // &#929; (Rho)
$htmlEntities["&Sigma;"] ="\xCE\xA3"; // &#931; (Sigma)
$htmlEntities["&Tau;"] ="\xCE\xA4"; // &#932; (Tau)
$htmlEntities["&Upsilon;"] ="\xCE\xA5"; // &#933; (Upsilon)
$htmlEntities["&Phi;"] ="\xCE\xA6"; // &#934; (Phi)
$htmlEntities["&Chi;"] ="\xCE\xA7"; // &#935; (Chi)
$htmlEntities["&Psi;"] ="\xCE\xA8"; // &#936; (Psi)
$htmlEntities["&Omega;"] ="\xCE\xA9"; // &#937; (Omega)
$htmlEntities["&alpha;"] ="\xCE\xB1"; // &#945; (alpha)
$htmlEntities["&beta;"] ="\xCE\xB2"; // &#946; (beta)
$htmlEntities["&gamma;"] ="\xCE\xB3"; // &#947; (gamma)
$htmlEntities["&delta;"] ="\xCE\xB4"; // &#948; (delta)
$htmlEntities["&epsilon;"] ="\xCE\xB5"; // &#949; (epsilon)
$htmlEntities["&zeta;"] ="\xCE\xB6"; // &#950; (zeta)
$htmlEntities["&eta;"] ="\xCE\xB7"; // &#951; (eta)
$htmlEntities["&theta;"] ="\xCE\xB8"; // &#952; (theta)
$htmlEntities["&iota;"] ="\xCE\xB9"; // &#953; (iota)
$htmlEntities["&kappa;"] ="\xCE\xBA"; // &#954; (kappa)
$htmlEntities["&lambda;"] ="\xCE\xBB"; // &#955; (lambda)
$htmlEntities["&mu;"] ="\xCE\xBC"; // &#956; (mu)
$htmlEntities["&nu;"] ="\xCE\xBD"; // &#957; (nu)
$htmlEntities["&xi;"] ="\xCE\xBE"; // &#958; (xi)
$htmlEntities["&omicron;"] ="\xCE\xBF"; // &#959; (omicron)
$htmlEntities["&pi;"] ="\xCF\x80"; // &#960; (pi)
$htmlEntities["&rho;"] ="\xCF\x81"; // &#961; (rho)
$htmlEntities["&sigmaf;"] ="\xCF\x82"; // &#962; (sigmaf)
$htmlEntities["&sigma;"] ="\xCF\x83"; // &#963; (sigma)
$htmlEntities["&tau;"] ="\xCF\x84"; // &#964; (tau)
$htmlEntities["&upsilon;"] ="\xCF\x85"; // &#965; (upsilon)
$htmlEntities["&phi;"] ="\xCF\x86"; // &#966; (phi)
$htmlEntities["&chi;"] ="\xCF\x87"; // &#967; (chi)
$htmlEntities["&psi;"] ="\xCF\x88"; // &#968; (psi)
$htmlEntities["&omega;"] ="\xCF\x89"; // &#969; (omega)
$htmlEntities["&thetasym;"] ="\xCF\x91"; // &#977; (theta symbol)
$htmlEntities["&upsih;"] ="\xCF\x92"; // &#978; (upsilon symbol)
$htmlEntities["&piv;"] ="\xCF\x96"; // &#982; (pi symbol)
$htmlEntities["&ensp;"] ="\xE2\x80\x82"; // &#8194; (en space)
$htmlEntities["&emsp;"] ="\xE2\x80\x83"; // &#8195; (em space)
$htmlEntities["&thinsp;"] ="\xE2\x80\x89"; // &#8201; (thin space)
$htmlEntities["&zwnj;"] ="\xE2\x80\x8C"; // &#8204; (zero width non-joiner)
$htmlEntities["&zwj;"] ="\xE2\x80\x8D"; // &#8205; (zero width joiner)
$htmlEntities["&lrm;"] ="\xE2\x80\x8E"; // &#8206; (left-to-right mark)
$htmlEntities["&rlm;"] ="\xE2\x80\x8F"; // &#8207; (right-to-left mark)
$htmlEntities["&ndash;"] ="\xE2\x80\x93"; // &#8211; (en dash)
$htmlEntities["&mdash;"] ="\xE2\x80\x94"; // &#8212; (em dash)
$htmlEntities["&lsquo;"] ="\xE2\x80\x98"; // &#8216; (left single quotation mark)
$htmlEntities["&rsquo;"] ="\xE2\x80\x99"; // &#8217; (right single quotation mark)
$htmlEntities["&sbquo;"] ="\xE2\x80\x9A"; // &#8218; (single low-9 quotation mark)
$htmlEntities["&ldquo;"] ="\xE2\x80\x9C"; // &#8220; (left double quotation mark)
$htmlEntities["&rdquo;"] ="\xE2\x80\x9D"; // &#8221; (right double quotation mark)
$htmlEntities["&bdquo;"] ="\xE2\x80\x9E"; // &#8222; (double low-9 quotation mark)
$htmlEntities["&dagger;"] ="\xE2\x80\xA0"; // &#8224; (dagger)
$htmlEntities["&Dagger;"] ="\xE2\x80\xA1"; // &#8225; (double dagger)
$htmlEntities["&bull;"] ="\xE2\x80\xA2"; // &#8226; (bullet)
$htmlEntities["&hellip;"] ="\xE2\x80\xA6"; // &#8230; (horizontal ellipsis)
$htmlEntities["&permil;"] ="\xE2\x80\xB0"; // &#8240; (per mille)
$htmlEntities["&prime;"] ="\xE2\x80\xB2"; // &#8242; (minutes or prime)
$htmlEntities["&Prime;"] ="\xE2\x80\xB3"; // &#8243; (seconds or Double Prime)
$htmlEntities["&lsaquo;"] ="\xE2\x80\xB9"; // &#8249; (single left angle quotation)
$htmlEntities["&rsaquo;"] ="\xE2\x80\xBA"; // &#8250; (single right angle quotation)
$htmlEntities["&oline;"] ="\xE2\x80\xBE"; // &#8254; (overline)
$htmlEntities["&frasl;"] ="\xE2\x81\x84"; // &#8260; (fraction slash)
$htmlEntities["&euro;"] ="\xE2\x82\xAC"; // &#8364; (euro)
$htmlEntities["&image;"] ="\xE2\x84\x91"; // &#8465; (blackletter capital I)
$htmlEntities["&weierp;"] ="\xE2\x84\x98"; // &#8472; (script capital P)
$htmlEntities["&real;"] ="\xE2\x84\x9C"; // &#8476; (blackletter capital R)
$htmlEntities["&trade;"] ="\xE2\x84\xA2"; // &#8482; (trademark)
$htmlEntities["&alefsym;"] ="\xE2\x84\xB5"; // &#8501; (alef)
$htmlEntities["&larr;"] ="\xE2\x86\x90"; // &#8592; (left arrow)
$htmlEntities["&uarr;"] ="\xE2\x86\x91"; // &#8593; (up arrow)
$htmlEntities["&rarr;"] ="\xE2\x86\x92"; // &#8594; (right arrow)
$htmlEntities["&darr;"] ="\xE2\x86\x93"; // &#8595; (down arrow)
$htmlEntities["&harr;"] ="\xE2\x86\x94"; // &#8596; (left right arrow)
$htmlEntities["&crarr;"] ="\xE2\x86\xB5"; // &#8629; (carriage return arrow)
$htmlEntities["&lArr;"] ="\xE2\x87\x90"; // &#8656; (left double arrow)
$htmlEntities["&uArr;"] ="\xE2\x87\x91"; // &#8657; (up double arrow)
$htmlEntities["&rArr;"] ="\xE2\x87\x92"; // &#8658; (right double arrow)
$htmlEntities["&dArr;"] ="\xE2\x87\x93"; // &#8659; (down double arrow)
$htmlEntities["&hArr;"] ="\xE2\x87\x94"; // &#8660; (left right double arrow)
$htmlEntities["&forall;"] ="\xE2\x88\x80"; // &#8704; (for all)
$htmlEntities["&part;"] ="\xE2\x88\x82"; // &#8706; (partial differential)
$htmlEntities["&exist;"] ="\xE2\x88\x83"; // &#8707; (there exists)
$htmlEntities["&empty;"] ="\xE2\x88\x85"; // &#8709; (empty set)
$htmlEntities["&nabla;"] ="\xE2\x88\x87"; // &#8711; (backward difference)
$htmlEntities["&isin;"] ="\xE2\x88\x88"; // &#8712; (element of)
$htmlEntities["&notin;"] ="\xE2\x88\x89"; // &#8713; (not an element of)
$htmlEntities["&ni;"] ="\xE2\x88\x8B"; // &#8715; (ni = contains as member)
$htmlEntities["&prod;"] ="\xE2\x88\x8F"; // &#8719; (n-ary product)
$htmlEntities["&sum;"] ="\xE2\x88\x91"; // &#8721; (n-ary sumation)
$htmlEntities["&minus;"] ="\xE2\x88\x92"; // &#8722; (minus)
$htmlEntities["&lowast;"] ="\xE2\x88\x97"; // &#8727; (asterisk operator)
$htmlEntities["&radic;"] ="\xE2\x88\x9A"; // &#8730; (square root)
$htmlEntities["&prop;"] ="\xE2\x88\x9D"; // &#8733; (proportional to)
$htmlEntities["&infin;"] ="\xE2\x88\x9E"; // &#8734; (infinity)
$htmlEntities["&ang;"] ="\xE2\x88\xA0"; // &#8736; (angle)
$htmlEntities["&and;"] ="\xE2\x88\xA7"; // &#8743; (logical and)
$htmlEntities["&or;"] ="\xE2\x88\xA8"; // &#8744; (logical or)
$htmlEntities["&cap;"] ="\xE2\x88\xA9"; // &#8745; (intersection)
$htmlEntities["&cup;"] ="\xE2\x88\xAA"; // &#8746; (union)
$htmlEntities["&int;"] ="\xE2\x88\xAB"; // &#8747; (integral)
$htmlEntities["&there4;"] ="\xE2\x88\xB4"; // &#8756; (therefore)
$htmlEntities["&sim;"] ="\xE2\x88\xBC"; // &#8764; (similar to)
$htmlEntities["&cong;"] ="\xE2\x89\x85"; // &#8773; (congruent to)
$htmlEntities["&asymp;"] ="\xE2\x89\x88"; // &#8776; (approximately equal)
$htmlEntities["&ne;"] ="\xE2\x89\xA0"; // &#8800; (not equal)
$htmlEntities["&equiv;"] ="\xE2\x89\xA1"; // &#8801; (equivalent)
$htmlEntities["&le;"] ="\xE2\x89\xA4"; // &#8804; (less or equal)
$htmlEntities["&ge;"] ="\xE2\x89\xA5"; // &#8805; (greater or equal)
$htmlEntities["&sub;"] ="\xE2\x8A\x82"; // &#8834; (subset of)
$htmlEntities["&sup;"] ="\xE2\x8A\x83"; // &#8835; (superset of)
$htmlEntities["&nsub;"] ="\xE2\x8A\x84"; // &#8836; (not subset of)
$htmlEntities["&sube;"] ="\xE2\x8A\x86"; // &#8838; (subset or equal)
$htmlEntities["&supe;"] ="\xE2\x8A\x87"; // &#8839; (superset or equal)
$htmlEntities["&oplus;"] ="\xE2\x8A\x95"; // &#8853; (circled plus)
$htmlEntities["&otimes;"] ="\xE2\x8A\x87"; // &#8855; (circled times)
$htmlEntities["&perp;"] ="\xE2\x8A\xA5"; // &#8869; (perpendicular)
$htmlEntities["&sdot;"] ="\xE2\x8C\x85"; // &#8901; (dot operator)
$htmlEntities["&lceil;"] ="\xE2\x8C\x88"; // &#8968; (left ceiling)
$htmlEntities["&rceil;"] ="\xE2\x8C\x89"; // &#8969; (right ceiling)
$htmlEntities["&lfloor;"] ="\xE2\x8C\x8A"; // &#8970; (left floor)
$htmlEntities["&rfloor;"] ="\xE2\x8C\x8B"; // &#8971; (right floor)
$htmlEntities["&lang;"] ="\xE2\x8C\xA9"; // &#9001; (left angle bracket = bra)
$htmlEntities["&rang;"] ="\xE2\x8C\xAA"; // &#9002; (right angle bracket = ket)
$htmlEntities["&loz;"] ="\xE2\x97\x8A"; // &#9674; (lozenge)
$htmlEntities["&spades;"] ="\xE2\x99\xA0"; // &#9824; (spade)
$htmlEntities["&clubs;"] ="\xE2\x99\xA3"; // &#9827; (club)
$htmlEntities["&hearts;"] ="\xE2\x99\xA5"; // &#9829; (heart)
$htmlEntities["&diams;"] ="\xE2\x99\xA6"; // &#9830; (diamond)
?>

View File

@ -0,0 +1,782 @@
<?php
/**
* ePub NCX file structure
*
* @author A. Grandt <php@grandt.com>
* @copyright 2009-2014 A. Grandt
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @version 3.20
*/
class Ncx {
const _VERSION = 3.20;
const MIMETYPE = "application/x-dtbncx+xml";
private $bookVersion = EPub::BOOK_VERSION_EPUB2;
private $navMap = NULL;
private $uid = NULL;
private $meta = array();
private $docTitle = NULL;
private $docAuthor = NULL;
private $currentLevel = NULL;
private $lastLevel = NULL;
private $languageCode = "en";
private $writingDirection = EPub::DIRECTION_LEFT_TO_RIGHT;
public $chapterList = array();
public $referencesTitle = "Guide";
public $referencesClass = "references";
public $referencesId = "references";
public $referencesList = array();
public $referencesName = array();
public $referencesOrder = NULL;
/**
* Class constructor.
*
* @param string $uid
* @param string $docTitle
* @param string $docAuthor
* @param string $languageCode
* @param string $writingDirection
*/
function __construct($uid = NULL, $docTitle = NULL, $docAuthor = NULL, $languageCode = "en", $writingDirection = EPub::DIRECTION_LEFT_TO_RIGHT) {
$this->navMap = new NavMap($writingDirection);
$this->currentLevel = $this->navMap;
$this->setUid($uid);
$this->setDocTitle($docTitle);
$this->setDocAuthor($docAuthor);
$this->setLanguageCode($languageCode);
$this->setWritingDirection($writingDirection);
}
/**
* Class destructor
*
* @return void
*/
function __destruct() {
unset($this->bookVersion, $this->navMap, $this->uid, $this->meta);
unset($this->docTitle, $this->docAuthor, $this->currentLevel, $this->lastLevel);
unset($this->languageCode, $this->writingDirection, $this->chapterList, $this->referencesTitle);
unset($this->referencesClass, $this->referencesId, $this->referencesList, $this->referencesName);
unset($this->referencesOrder);
}
/**
*
* Enter description here ...
*
* @param string $bookVersion
*/
function setVersion($bookVersion) {
$this->bookVersion = is_string($bookVersion) ? trim($bookVersion) : EPub::BOOK_VERSION_EPUB2;
}
/**
*
* @return bool TRUE if the book is set to type ePub 2
*/
function isEPubVersion2() {
return $this->bookVersion === EPub::BOOK_VERSION_EPUB2;
}
/**
*
* Enter description here ...
*
* @param string $uid
*/
function setUid($uid) {
$this->uid = is_string($uid) ? trim($uid) : NULL;
}
/**
*
* Enter description here ...
*
* @param string $docTitle
*/
function setDocTitle($docTitle) {
$this->docTitle = is_string($docTitle) ? trim($docTitle) : NULL;
}
/**
*
* Enter description here ...
*
* @param string $docAuthor
*/
function setDocAuthor($docAuthor) {
$this->docAuthor = is_string($docAuthor) ? trim($docAuthor) : NULL;
}
/**
*
* Enter description here ...
*
* @param string $languageCode
*/
function setLanguageCode($languageCode) {
$this->languageCode = is_string($languageCode) ? trim($languageCode) : "en";
}
/**
*
* Enter description here ...
*
* @param string $writingDirection
*/
function setWritingDirection($writingDirection) {
$this->writingDirection = is_string($writingDirection) ? trim($writingDirection) : EPub::DIRECTION_LEFT_TO_RIGHT;
}
/**
*
* Enter description here ...
*
* @param NavMap $navMap
*/
function setNavMap($navMap) {
if ($navMap != NULL && is_object($navMap) && get_class($navMap) === "NavMap") {
$this->navMap = $navMap;
}
}
/**
* Add one chapter level.
*
* Subsequent chapters will be added to this level.
*
* @param string $navTitle
* @param string $navId
* @param string $navClass
* @param string $isNavHidden
* @param string $writingDirection
* @return NavPoint
*/
function subLevel($navTitle = NULL, $navId = NULL, $navClass = NULL, $isNavHidden = FALSE, $writingDirection = NULL) {
$navPoint = FALSE;
if (isset($navTitle) && isset($navClass)) {
$navPoint = new NavPoint($navTitle, NULL, $navId, $navClass, $isNavHidden, $writingDirection);
$this->addNavPoint($navPoint);
}
if ($this->lastLevel !== NULL) {
$this->currentLevel = $this->lastLevel;
}
return $navPoint;
}
/**
* Step back one chapter level.
*
* Subsequent chapters will be added to this chapters parent level.
*/
function backLevel() {
$this->lastLevel = $this->currentLevel;
$this->currentLevel = $this->currentLevel->getParent();
}
/**
* Step back to the root level.
*
* Subsequent chapters will be added to the rooot NavMap.
*/
function rootLevel() {
$this->lastLevel = $this->currentLevel;
$this->currentLevel = $this->navMap;
}
/**
* Step back to the given level.
* Useful for returning to a previous level from deep within the structure.
* Values below 2 will have the same effect as rootLevel()
*
* @param int $newLevel
*/
function setCurrentLevel($newLevel) {
if ($newLevel <= 1) {
$this->rootLevel();
} else {
while ($this->currentLevel->getLevel() > $newLevel) {
$this->backLevel();
}
}
}
/**
* Get current level count.
* The indentation of the current structure point.
*
* @return current level count;
*/
function getCurrentLevel() {
return $this->currentLevel->getLevel();
}
/**
* Add child NavPoints to current level.
*
* @param NavPoint $navPoint
*/
function addNavPoint($navPoint) {
$this->lastLevel = $this->currentLevel->addNavPoint($navPoint);
}
/**
*
* Enter description here ...
*
* @return NavMap
*/
function getNavMap() {
return $this->navMap;
}
/**
*
* Enter description here ...
*
* @param string $name
* @param string $content
*/
function addMetaEntry($name, $content) {
$name = is_string($name) ? trim($name) : NULL;
$content = is_string($content) ? trim($content) : NULL;
if ($name != NULL && $content != NULL) {
$this->meta[] = array($name => $content);
}
}
/**
*
* Enter description here ...
*
* @return string
*/
function finalize() {
$nav = $this->navMap->finalize();
$ncx = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
if ($this->isEPubVersion2()) {
$ncx .= "<!DOCTYPE ncx PUBLIC \"-//NISO//DTD ncx 2005-1//EN\"\n"
. " \"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd\">\n";
}
$ncx .= "<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" version=\"2005-1\" xml:lang=\"" . $this->languageCode . "\" dir=\"" . $this->writingDirection . "\">\n"
. "\t<head>\n"
. "\t\t<meta name=\"dtb:uid\" content=\"" . $this->uid . "\" />\n"
. "\t\t<meta name=\"dtb:depth\" content=\"" . $this->navMap->getNavLevels() . "\" />\n"
. "\t\t<meta name=\"dtb:totalPageCount\" content=\"0\" />\n"
. "\t\t<meta name=\"dtb:maxPageNumber\" content=\"0\" />\n";
if (sizeof($this->meta)) {
foreach ($this->meta as $metaEntry) {
list($name, $content) = each($metaEntry);
$ncx .= "\t\t<meta name=\"" . $name . "\" content=\"" . $content . "\" />\n";
}
}
$ncx .= "\t</head>\n\n\t<docTitle>\n\t\t<text>"
. $this->docTitle
. "</text>\n\t</docTitle>\n\n\t<docAuthor>\n\t\t<text>"
. $this->docAuthor
. "</text>\n\t</docAuthor>\n\n"
. $nav;
return $ncx . "</ncx>\n";
}
/**
*
* @param string $title
* @param string $cssFileName
* @return string
*/
function finalizeEPub3($title = "Table of Contents", $cssFileName = NULL) {
$end = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
. "<html xmlns=\"http://www.w3.org/1999/xhtml\"\n"
. " xmlns:epub=\"http://www.idpf.org/2007/ops\"\n"
. " xml:lang=\"" . $this->languageCode . "\" lang=\"" . $this->languageCode . "\" dir=\"" . $this->writingDirection . "\">\n"
. "\t<head>\n"
. "\t\t<title>" . $this->docTitle . "</title>\n"
. "\t\t<meta http-equiv=\"default-style\" content=\"text/html; charset=utf-8\"/>\n";
if ($cssFileName !== NULL) {
$end .= "\t\t<link rel=\"stylesheet\" href=\"" . $cssFileName . "\" type=\"text/css\"/>\n";
}
$end .= "\t</head>\n"
. "\t<body epub:type=\"frontmatter toc\">\n"
. "\t\t<header>\n"
. "\t\t\t<h1>" . $title . "</h1>\n"
. "\t\t</header>\n"
. $this->navMap->finalizeEPub3()
. $this->finalizeEPub3Landmarks()
. "\t</body>\n"
. "</html>\n";
return $end;
}
/**
* Build the references for the ePub 2 toc.
* These are merely reference pages added to the end of the navMap though.
*
* @return string
*/
function finalizeReferences() {
if (isset($this->referencesList) && sizeof($this->referencesList) > 0) {
$this->rootLevel();
$this->subLevel($this->referencesTitle, $this->referencesId, $this->referencesClass);
$refId = 1;
while (list($item, $descriptive) = each($this->referencesOrder)) {
if (array_key_exists($item, $this->referencesList)) {
$name = (empty($this->referencesName[$item]) ? $descriptive : $this->referencesName[$item]);
$navPoint = new NavPoint($name, $this->referencesList[$item], "ref-" . $refId++);
$this->addNavPoint($navPoint);
}
}
}
}
/**
* Build the landmarks for the ePub 3 toc.
* @return string
*/
function finalizeEPub3Landmarks() {
$lm = "";
if (isset($this->referencesList) && sizeof($this->referencesList) > 0) {
$lm = "\t\t\t<nav epub:type=\"landmarks\">\n"
. "\t\t\t\t<h2"
. ($this->writingDirection === EPub::DIRECTION_RIGHT_TO_LEFT ? " dir=\"rtl\"" : "")
. ">" . $this->referencesTitle . "</h2>\n"
. "\t\t\t\t<ol>\n";
$li = "";
while (list($item, $descriptive) = each($this->referencesOrder)) {
if (array_key_exists($item, $this->referencesList)) {
$li .= "\t\t\t\t\t<li><a epub:type=\""
. $item
. "\" href=\"" . $this->referencesList[$item] . "\">"
. (empty($this->referencesName[$item]) ? $descriptive : $this->referencesName[$item])
. "</a></li>\n";
}
}
if (empty($li)) {
return "";
}
$lm .= $li
. "\t\t\t\t</ol>\n"
. "\t\t\t</nav>\n";
}
return $lm;
}
}
/**
* ePub NavMap class
*/
class NavMap {
const _VERSION = 3.00;
private $navPoints = array();
private $navLevels = 0;
private $writingDirection = NULL;
/**
* Class constructor.
*
* @return void
*/
function __construct($writingDirection = NULL) {
$this->setWritingDirection($writingDirection);
}
/**
* Class destructor
*
* @return void
*/
function __destruct() {
unset($this->navPoints, $this->navLevels, $this->writingDirection);
}
/**
* Set the writing direction to be used for this NavPoint.
*
* @param string $writingDirection
*/
function setWritingDirection($writingDirection) {
$this->writingDirection = isset($writingDirection) && is_string($writingDirection) ? trim($writingDirection) : NULL;
}
function getWritingDirection() {
return $this->writingDirection;
}
/**
* Add a navPoint to the root of the NavMap.
*
* @param NavPoint $navPoint
* @return NavMap
*/
function addNavPoint($navPoint) {
if ($navPoint != NULL && is_object($navPoint) && get_class($navPoint) === "NavPoint") {
$navPoint->setParent($this);
if ($navPoint->getWritingDirection() == NULL) {
$navPoint->setWritingDirection($this->writingDirection);
}
$this->navPoints[] = $navPoint;
return $navPoint;
}
return $this;
}
/**
* The final max depth for the "dtb:depth" meta attribute
* Only available after finalize have been called.
*
* @return number
*/
function getNavLevels() {
return $this->navLevels+1;
}
function getLevel() {
return 1;
}
function getParent() {
return $this;
}
/**
* Finalize the navMap, the final max depth for the "dtb:depth" meta attribute can be retrieved with getNavLevels after finalization
*
*/
function finalize() {
$playOrder = 0;
$this->navLevels = 0;
$nav = "\t<navMap>\n";
if (sizeof($this->navPoints) > 0) {
$this->navLevels++;
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalize($nav, $playOrder, 0);
if ($retLevel > $this->navLevels) {
$this->navLevels = $retLevel;
}
}
}
return $nav . "\t</navMap>\n";
}
/**
* Finalize the navMap, the final max depth for the "dtb:depth" meta attribute can be retrieved with getNavLevels after finalization
*
*/
function finalizeEPub3() {
$playOrder = 0;
$level = 0;
$this->navLevels = 0;
$nav = "\t\t<nav epub:type=\"toc\" id=\"toc\">\n";
if (sizeof($this->navPoints) > 0) {
$this->navLevels++;
$nav .= str_repeat("\t", $level) . "\t\t\t<ol epub:type=\"list\">\n";
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalizeEPub3($nav, $playOrder, 0);
if ($retLevel > $this->navLevels) {
$this->navLevels = $retLevel;
}
}
$nav .= str_repeat("\t", $level) . "\t\t\t</ol>\n";
}
return $nav . "\t\t</nav>\n";
}
}
/**
* ePub NavPoint class
*/
class NavPoint {
const _VERSION = 3.00;
private $label = NULL;
private $contentSrc = NULL;
private $id = NULL;
private $navClass = NULL;
private $isNavHidden = FALSE;
private $navPoints = array();
private $parent = NULL;
/**
* Class constructor.
*
* All three attributes are mandatory, though if ID is set to null (default) the value will be generated.
*
* @param string $label
* @param string $contentSrc
* @param string $id
* @param string $navClass
* @param bool $isNavHidden
* @param string $writingDirection
*/
function __construct($label, $contentSrc = NULL, $id = NULL, $navClass = NULL, $isNavHidden = FALSE, $writingDirection = NULL) {
$this->setLabel($label);
$this->setContentSrc($contentSrc);
$this->setId($id);
$this->setNavClass($navClass);
$this->setNavHidden($isNavHidden);
$this->setWritingDirection($writingDirection);
}
/**
* Class destructor
*
* @return void
*/
function __destruct() {
unset($this->label, $this->contentSrc, $this->id, $this->navClass);
unset($this->isNavHidden, $this->navPoints, $this->parent);
}
/**
* Set the Text label for the NavPoint.
*
* The label is mandatory.
*
* @param string $label
*/
function setLabel($label) {
$this->label = is_string($label) ? trim($label) : NULL;
}
/**
* Get the Text label for the NavPoint.
*
* @return string Label
*/
function getLabel() {
return $this->label;
}
/**
* Set the src reference for the NavPoint.
*
* The src is mandatory for ePub 2.
*
* @param string $contentSrc
*/
function setContentSrc($contentSrc) {
$this->contentSrc = isset($contentSrc) && is_string($contentSrc) ? trim($contentSrc) : NULL;
}
/**
* Get the src reference for the NavPoint.
*
* @return string content src url.
*/
function getContentSrc() {
return $this->contentSrc;
}
/**
* Set the parent for this NavPoint.
*
* @param NavPoint or NavMap $parent
*/
function setParent($parent) {
if ($parent != NULL && is_object($parent) &&
(get_class($parent) === "NavPoint" || get_class($parent) === "NavMap") ) {
$this->parent = $parent;
}
}
/**
* Get the parent to this NavPoint.
*
* @return NavPoint, or NavMap if the parent is the root.
*/
function getParent() {
return $this->parent;
}
/**
* Get the current level. 1 = document root.
*
* @return int level
*/
function getLevel() {
return $this->parent === NULL ? 1 : $this->parent->getLevel()+1;
}
/**
* Set the id for the NavPoint.
*
* The id must be unique, and is mandatory.
*
* @param string $id
*/
function setId($id) {
$this->id = is_string($id) ? trim($id) : NULL;
}
/**
* Set the class to be used for this NavPoint.
*
* @param string $navClass
*/
function setNavClass($navClass) {
$this->navClass = isset($navClass) && is_string($navClass) ? trim($navClass) : NULL;
}
/**
* Set the class to be used for this NavPoint.
*
* @param string $navClass
*/
function setNavHidden($isNavHidden) {
$this->isNavHidden = $isNavHidden === TRUE;
}
/**
* Set the writing direction to be used for this NavPoint.
*
* @param string $writingDirection
*/
function setWritingDirection($writingDirection) {
$this->writingDirection = isset($writingDirection) && is_string($writingDirection) ? trim($writingDirection) : NULL;
}
function getWritingDirection() {
return $this->writingDirection;
}
/**
* Add child NavPoints for multi level NavMaps.
*
* @param NavPoint $navPoint
*/
function addNavPoint($navPoint) {
if ($navPoint != NULL && is_object($navPoint) && get_class($navPoint) === "NavPoint") {
$navPoint->setParent($this);
if ($navPoint->getWritingDirection() == NULL) {
$navPoint->setWritingDirection($this->writingDirection);
}
$this->navPoints[] = $navPoint;
return $navPoint;
}
return $this;
}
/**
*
* Enter description here ...
*
* @param string $nav
* @param int $playOrder
* @param int $level
* @return int
*/
function finalize(&$nav = "", &$playOrder = 0, $level = 0) {
$maxLevel = $level;
$levelAdjust = 0;
if ($this->isNavHidden) {
return $maxLevel;
}
if (isset($this->contentSrc)) {
$playOrder++;
if ($this->id == NULL) {
$this->id = "navpoint-" . $playOrder;
}
$nav .= str_repeat("\t", $level) . "\t\t<navPoint id=\"" . $this->id . "\" playOrder=\"" . $playOrder . "\">\n"
. str_repeat("\t", $level) . "\t\t\t<navLabel>\n"
. str_repeat("\t", $level) . "\t\t\t\t<text>" . $this->label . "</text>\n"
. str_repeat("\t", $level) . "\t\t\t</navLabel>\n"
. str_repeat("\t", $level) . "\t\t\t<content src=\"" . $this->contentSrc . "\" />\n";
} else {
$levelAdjust++;
}
if (sizeof($this->navPoints) > 0) {
$maxLevel++;
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalize($nav, $playOrder, ($level+1+$levelAdjust));
if ($retLevel > $maxLevel) {
$maxLevel = $retLevel;
}
}
}
if (isset($this->contentSrc)) {
$nav .= str_repeat("\t", $level) . "\t\t</navPoint>\n";
}
return $maxLevel;
}
/**
*
* Enter description here ...
*
* @param string $nav
* @param int $playOrder
* @param int $level
* @return int
*/
function finalizeEPub3(&$nav = "", &$playOrder = 0, $level = 0, $subLevelClass = NULL, $subLevelHidden = FALSE) {
$maxLevel = $level;
if ($this->id == NULL) {
$this->id = "navpoint-" . $playOrder;
}
$indent = str_repeat("\t", $level) . "\t\t\t\t";
$nav .= $indent . "<li id=\"" . $this->id . "\"";
if (isset($this->writingDirection)) {
$nav .= " dir=\"" . $this->writingDirection . "\"";
}
$nav .= ">\n";
if (isset($this->contentSrc)) {
$nav .= $indent . "\t<a href=\"" . $this->contentSrc . "\">" . $this->label . "</a>\n";
} else {
$nav .= $indent . "\t<span>" . $this->label . "</span>\n";
}
if (sizeof($this->navPoints) > 0) {
$maxLevel++;
$nav .= $indent . "\t<ol epub:type=\"list\"";
if (isset($subLevelClass)) {
$nav .= " class=\"" . $subLevelClass . "\"";
}
if ($subLevelHidden) {
$nav .= " hidden=\"hidden\"";
}
$nav .= ">\n";
foreach ($this->navPoints as $navPoint) {
$retLevel = $navPoint->finalizeEPub3($nav, $playOrder, ($level+2), $subLevelClass, $subLevelHidden);
if ($retLevel > $maxLevel) {
$maxLevel = $retLevel;
}
}
$nav .= $indent . "\t</ol>\n";
}
$nav .= $indent . "</li>\n";
return $maxLevel;
}
}
?>

File diff suppressed because it is too large Load Diff

2432
inc/3rdparty/libraries/PHPePub/EPub.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
<?php
/**
* Split an HTML file into smaller html files, retaining the formatting and structure for the individual parts.
* What this splitter does is using DOM to try and retain any formatting in the file, including rebuilding the DOM tree for subsequent parts.
* Split size is considered max target size. The actual size is the result of an even split across the resulting files.
*
* @author A. Grandt <php@grandt.com>
* @copyright 2009-2014 A. Grandt
* @license GNU LGPL 2.1
* @link http://www.phpclasses.org/package/6115
* @link https://github.com/Grandt/PHPePub
* @version 3.20
*/
class EPubChapterSplitter {
const VERSION = 3.20;
private $splitDefaultSize = 250000;
private $bookVersion = EPub::BOOK_VERSION_EPUB2;
/**
*
* Enter description here ...
*
* @param unknown_type $ident
*/
function setVersion($bookVersion) {
$this->bookVersion = is_string($bookVersion) ? trim($bookVersion) : EPub::BOOK_VERSION_EPUB2;
}
/**
* Set default chapter target size.
* Default is 250000 bytes, and minimum is 10240 bytes.
*
* @param $size segment size in bytes
* @return void
*/
function setSplitSize($size) {
$this->splitDefaultSize = (int)$size;
if ($size < 10240) {
$this->splitDefaultSize = 10240; // Making the file smaller than 10k is not a good idea.
}
}
/**
* Get the chapter target size.
*
* @return $size
*/
function getSplitSize() {
return $this->splitDefaultSize;
}
/**
* Split $chapter into multiple parts.
*
* The search string can either be a regular string or a PHP PECL Regular Expression pattern as defined here: http://www.php.net/manual/en/pcre.pattern.php
* If the search string is a regular string, the matching will be for lines in the HTML starting with the string given
*
* @param String $chapter XHTML file
* @param Bool $splitOnSearchString Split on chapter boundaries, Splitting on search strings disables the split size check.
* @param String $searchString Chapter string to search for can be fixed text, or a regular expression pattern.
*
* @return array with 1 or more parts
*/
function splitChapter($chapter, $splitOnSearchString = false, $searchString = '/^Chapter\\ /i') {
$chapterData = array();
$isSearchRegexp = $splitOnSearchString && (preg_match('#^(\D|\S|\W).+\1[imsxeADSUXJu]*$#m', $searchString) == 1);
if ($splitOnSearchString && !$isSearchRegexp) {
$searchString = '#^<.+?>' . preg_quote($searchString, '#') . "#";
}
if (!$splitOnSearchString && strlen($chapter) <= $this->splitDefaultSize) {
return array($chapter);
}
$xmlDoc = new DOMDocument();
@$xmlDoc->loadHTML($chapter);
$head = $xmlDoc->getElementsByTagName("head");
$body = $xmlDoc->getElementsByTagName("body");
$htmlPos = stripos($chapter, "<html");
$htmlEndPos = stripos($chapter, ">", $htmlPos);
$newXML = substr($chapter, 0, $htmlEndPos+1) . "\n</html>";
if (strpos(trim($newXML), "<?xml ") === FALSE) {
$newXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" . $newXML;
}
$headerLength = strlen($newXML);
$files = array();
$chapterNames = array();
$domDepth = 0;
$domPath = array();
$domClonedPath = array();
$curFile = $xmlDoc->createDocumentFragment();
$files[] = $curFile;
$curParent = $curFile;
$curSize = 0;
$bodyLen = strlen($xmlDoc->saveXML($body->item(0)));
$headLen = strlen($xmlDoc->saveXML($head->item(0))) + $headerLength;
$partSize = $this->splitDefaultSize - $headLen;
if ($bodyLen > $partSize) {
$parts = ceil($bodyLen / $partSize);
$partSize = ($bodyLen / $parts) - $headLen;
}
$node = $body->item(0)->firstChild;
do {
$nodeData = $xmlDoc->saveXML($node);
$nodeLen = strlen($nodeData);
if ($nodeLen > $partSize && $node->hasChildNodes()) {
$domPath[] = $node;
$domClonedPath[] = $node->cloneNode(false);
$domDepth++;
$node = $node->firstChild;
}
$node2 = $node->nextSibling;
if ($node != null && $node->nodeName != "#text") {
$doSplit = false;
if ($splitOnSearchString) {
$doSplit = preg_match($searchString, $nodeData) == 1;
if ($doSplit) {
$chapterNames[] = trim($nodeData);
}
}
if ($curSize > 0 && ($doSplit || (!$splitOnSearchString && $curSize + $nodeLen > $partSize))) {
$curFile = $xmlDoc->createDocumentFragment();
$files[] = $curFile;
$curParent = $curFile;
if ($domDepth > 0) {
reset($domPath);
reset($domClonedPath);
$oneDomClonedPath = each($domClonedPath);
while ($oneDomClonedPath) {
list($k, $v) = $oneDomClonedPath;
$newParent = $v->cloneNode(false);
$curParent->appendChild($newParent);
$curParent = $newParent;
$oneDomClonedPath = each($domClonedPath);
}
}
$curSize = strlen($xmlDoc->saveXML($curFile));
}
$curParent->appendChild($node->cloneNode(true));
$curSize += $nodeLen;
}
$node = $node2;
while ($node == null && $domDepth > 0) {
$domDepth--;
$node = end($domPath)->nextSibling;
array_pop($domPath);
array_pop($domClonedPath);
$curParent = $curParent->parentNode;
}
} while ($node != null);
$curFile = null;
$curSize = 0;
$xml = new DOMDocument('1.0', $xmlDoc->xmlEncoding);
$xml->lookupPrefix("http://www.w3.org/1999/xhtml");
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
for ($idx = 0; $idx < count($files); $idx++) {
$xml2Doc = new DOMDocument('1.0', $xmlDoc->xmlEncoding);
$xml2Doc->lookupPrefix("http://www.w3.org/1999/xhtml");
$xml2Doc->loadXML($newXML);
$html = $xml2Doc->getElementsByTagName("html")->item(0);
$html->appendChild($xml2Doc->importNode($head->item(0), true));
$body = $xml2Doc->createElement("body");
$html->appendChild($body);
$body->appendChild($xml2Doc->importNode($files[$idx], true));
// force pretty printing and correct formatting, should not be needed, but it is.
$xml->loadXML($xml2Doc->saveXML());
$doc = $xml->saveXML();
if ($this->bookVersion === EPub::BOOK_VERSION_EPUB3) {
$doc = preg_replace('#^\s*<!DOCTYPE\ .+?>\s*#im', '', $doc);
}
$chapterData[$splitOnSearchString ? $chapterNames[$idx] : $idx] = $doc;
}
return $chapterData;
}
}
?>

View File

@ -0,0 +1,92 @@
<?php
/**
* Simple log line aggregator.
*
* @author A. Grandt <php@grandt.com>
* @copyright 2012-2013 A. Grandt
* @license GNU LGPL, Attribution required for commercial implementations, requested for everything else.
* @version 1.00
*/
class Logger {
const VERSION = 1.00;
private $log = "";
private $tStart;
private $tLast;
private $name = NULL;
private $isLogging = FALSE;
private $isDebugging = FALSE;
/**
* Class constructor.
*
* @return void
*/
function __construct($name = NULL, $isLogging = FALSE) {
if ($name === NULL) {
$this->name = "";
} else {
$this->name = $name . " : ";
}
$this->isLogging = $isLogging;
$this->start();
}
/**
* Class destructor
*
* @return void
* @TODO make sure elements in the destructor match the current class elements
*/
function __destruct() {
unset($this->log);
}
function start() {
/* Prepare Logging. Just in case it's used. later */
if ($this->isLogging) {
$this->tStart = gettimeofday();
$this->tLast = $this->tStart;
$this->log = "<h1>Log: " . $this->name . "</h1>\n<pre>Started: " . gmdate("D, d M Y H:i:s T", $this->tStart['sec']) . "\n &#916; Start ; &#916; Last ;";
$this->logLine("Start");
}
}
function dumpInstalledModules() {
if ($this->isLogging) {
$isCurlInstalled = extension_loaded('curl') && function_exists('curl_version');
$isGdInstalled = extension_loaded('gd') && function_exists('gd_info');
$isExifInstalled = extension_loaded('exif') && function_exists('exif_imagetype');
$isFileGetContentsInstalled = function_exists('file_get_contents');
$isFileGetContentsExtInstalled = $isFileGetContentsInstalled && ini_get('allow_url_fopen');
$this->logLine("isCurlInstalled...............: " . ($isCurlInstalled ? "Yes" : "No"));
$this->logLine("isGdInstalled.................: " . ($isGdInstalled ? "Yes" : "No"));
$this->logLine("isExifInstalled...............: " . ($isExifInstalled ? "Yes" : "No"));
$this->logLine("isFileGetContentsInstalled....: " . ($isFileGetContentsInstalled ? "Yes" : "No"));
$this->logLine("isFileGetContentsExtInstalled.: " . ($isFileGetContentsExtInstalled ? "Yes" : "No"));
}
}
function logLine($line) {
if ($this->isLogging) {
$tTemp = gettimeofday();
$tS = $this->tStart['sec'] + (((int)($this->tStart['usec']/100))/10000);
$tL = $this->tLast['sec'] + (((int)($this->tLast['usec']/100))/10000);
$tT = $tTemp['sec'] + (((int)($tTemp['usec']/100))/10000);
$logline = sprintf("\n+%08.04f; +%08.04f; ", ($tT-$tS), ($tT-$tL)) . $this->name . $line;
$this->log .= $logline;
$this->tLast = $tTemp;
if ($this->isDebugging) {
echo "<pre>" . $logline . "\n</pre>\n";
}
}
}
function getLog() {
return $this->log;
}
}
?>

818
inc/3rdparty/libraries/PHPePub/Zip.php vendored Normal file
View File

@ -0,0 +1,818 @@
<?php
/**
* Class to create and manage a Zip file.
*
* Initially inspired by CreateZipFile by Rochak Chauhan www.rochakchauhan.com (http://www.phpclasses.org/browse/package/2322.html)
* and
* http://www.pkware.com/documents/casestudies/APPNOTE.TXT Zip file specification.
*
* License: GNU LGPL, Attribution required for commercial implementations, requested for everything else.
*
* @author A. Grandt <php@grandt.com>
* @copyright 2009-2014 A. Grandt
* @license GNU LGPL 2.1
* @link http://www.phpclasses.org/package/6110
* @link https://github.com/Grandt/PHPZip
* @version 1.60
*/
class Zip {
const VERSION = 1.60;
const ZIP_LOCAL_FILE_HEADER = "\x50\x4b\x03\x04"; // Local file header signature
const ZIP_CENTRAL_FILE_HEADER = "\x50\x4b\x01\x02"; // Central file header signature
const ZIP_END_OF_CENTRAL_DIRECTORY = "\x50\x4b\x05\x06\x00\x00\x00\x00"; //end of Central directory record
const EXT_FILE_ATTR_DIR = 010173200020; // Permission 755 drwxr-xr-x = (((S_IFDIR | 0755) << 16) | S_DOS_D);
const EXT_FILE_ATTR_FILE = 020151000040; // Permission 644 -rw-r--r-- = (((S_IFREG | 0644) << 16) | S_DOS_A);
const ATTR_VERSION_TO_EXTRACT = "\x14\x00"; // Version needed to extract
const ATTR_MADE_BY_VERSION = "\x1E\x03"; // Made By Version
// Unix file types
const S_IFIFO = 0010000; // named pipe (fifo)
const S_IFCHR = 0020000; // character special
const S_IFDIR = 0040000; // directory
const S_IFBLK = 0060000; // block special
const S_IFREG = 0100000; // regular
const S_IFLNK = 0120000; // symbolic link
const S_IFSOCK = 0140000; // socket
// setuid/setgid/sticky bits, the same as for chmod:
const S_ISUID = 0004000; // set user id on execution
const S_ISGID = 0002000; // set group id on execution
const S_ISTXT = 0001000; // sticky bit
// And of course, the other 12 bits are for the permissions, the same as for chmod:
// When addding these up, you can also just write the permissions as a simgle octal number
// ie. 0755. The leading 0 specifies octal notation.
const S_IRWXU = 0000700; // RWX mask for owner
const S_IRUSR = 0000400; // R for owner
const S_IWUSR = 0000200; // W for owner
const S_IXUSR = 0000100; // X for owner
const S_IRWXG = 0000070; // RWX mask for group
const S_IRGRP = 0000040; // R for group
const S_IWGRP = 0000020; // W for group
const S_IXGRP = 0000010; // X for group
const S_IRWXO = 0000007; // RWX mask for other
const S_IROTH = 0000004; // R for other
const S_IWOTH = 0000002; // W for other
const S_IXOTH = 0000001; // X for other
const S_ISVTX = 0001000; // save swapped text even after use
// Filetype, sticky and permissions are added up, and shifted 16 bits left BEFORE adding the DOS flags.
// DOS file type flags, we really only use the S_DOS_D flag.
const S_DOS_A = 0000040; // DOS flag for Archive
const S_DOS_D = 0000020; // DOS flag for Directory
const S_DOS_V = 0000010; // DOS flag for Volume
const S_DOS_S = 0000004; // DOS flag for System
const S_DOS_H = 0000002; // DOS flag for Hidden
const S_DOS_R = 0000001; // DOS flag for Read Only
private $zipMemoryThreshold = 1048576; // Autocreate tempfile if the zip data exceeds 1048576 bytes (1 MB)
private $zipData = NULL;
private $zipFile = NULL;
private $zipComment = NULL;
private $cdRec = array(); // central directory
private $offset = 0;
private $isFinalized = FALSE;
private $addExtraField = TRUE;
private $streamChunkSize = 65536;
private $streamFilePath = NULL;
private $streamTimestamp = NULL;
private $streamFileComment = NULL;
private $streamFile = NULL;
private $streamData = NULL;
private $streamFileLength = 0;
private $streamExtFileAttr = null;
/**
* Constructor.
*
* @param boolean $useZipFile Write temp zip data to tempFile? Default FALSE
*/
function __construct($useZipFile = FALSE) {
if ($useZipFile) {
$this->zipFile = tmpfile();
} else {
$this->zipData = "";
}
}
function __destruct() {
if (is_resource($this->zipFile)) {
fclose($this->zipFile);
}
$this->zipData = NULL;
}
/**
* Extra fields on the Zip directory records are Unix time codes needed for compatibility on the default Mac zip archive tool.
* These are enabled as default, as they do no harm elsewhere and only add 26 bytes per file added.
*
* @param bool $setExtraField TRUE (default) will enable adding of extra fields, anything else will disable it.
*/
function setExtraField($setExtraField = TRUE) {
$this->addExtraField = ($setExtraField === TRUE);
}
/**
* Set Zip archive comment.
*
* @param string $newComment New comment. NULL to clear.
* @return bool $success
*/
public function setComment($newComment = NULL) {
if ($this->isFinalized) {
return FALSE;
}
$this->zipComment = $newComment;
return TRUE;
}
/**
* Set zip file to write zip data to.
* This will cause all present and future data written to this class to be written to this file.
* This can be used at any time, even after the Zip Archive have been finalized. Any previous file will be closed.
* Warning: If the given file already exists, it will be overwritten.
*
* @param string $fileName
* @return bool $success
*/
public function setZipFile($fileName) {
if (is_file($fileName)) {
unlink($fileName);
}
$fd=fopen($fileName, "x+b");
if (is_resource($this->zipFile)) {
rewind($this->zipFile);
while (!feof($this->zipFile)) {
fwrite($fd, fread($this->zipFile, $this->streamChunkSize));
}
fclose($this->zipFile);
} else {
fwrite($fd, $this->zipData);
$this->zipData = NULL;
}
$this->zipFile = $fd;
return TRUE;
}
/**
* Add an empty directory entry to the zip archive.
* Basically this is only used if an empty directory is added.
*
* @param string $directoryPath Directory Path and name to be added to the archive.
* @param int $timestamp (Optional) Timestamp for the added directory, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this directory. To use fileComment, timestamp must be given.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function addDirectory($directoryPath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_DIR) {
if ($this->isFinalized) {
return FALSE;
}
$directoryPath = str_replace("\\", "/", $directoryPath);
$directoryPath = rtrim($directoryPath, "/");
if (strlen($directoryPath) > 0) {
$this->buildZipEntry($directoryPath.'/', $fileComment, "\x00\x00", "\x00\x00", $timestamp, "\x00\x00\x00\x00", 0, 0, $extFileAttr);
return TRUE;
}
return FALSE;
}
/**
* Add a file to the archive at the specified location and file name.
*
* @param string $data File data.
* @param string $filePath Filepath and name to be used in the archive.
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
* @param bool $compress (Optional) Compress file, if set to FALSE the file will only be stored. Default TRUE.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function addFile($data, $filePath, $timestamp = 0, $fileComment = NULL, $compress = TRUE, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if ($this->isFinalized) {
return FALSE;
}
if (is_resource($data) && get_resource_type($data) == "stream") {
$this->addLargeFile($data, $filePath, $timestamp, $fileComment, $extFileAttr);
return FALSE;
}
$gzData = "";
$gzType = "\x08\x00"; // Compression type 8 = deflate
$gpFlags = "\x00\x00"; // General Purpose bit flags for compression type 8 it is: 0=Normal, 1=Maximum, 2=Fast, 3=super fast compression.
$dataLength = strlen($data);
$fileCRC32 = pack("V", crc32($data));
if ($compress) {
$gzTmp = gzcompress($data);
$gzData = substr(substr($gzTmp, 0, strlen($gzTmp) - 4), 2); // gzcompress adds a 2 byte header and 4 byte CRC we can't use.
// The 2 byte header does contain useful data, though in this case the 2 parameters we'd be interrested in will always be 8 for compression type, and 2 for General purpose flag.
$gzLength = strlen($gzData);
} else {
$gzLength = $dataLength;
}
if ($gzLength >= $dataLength) {
$gzLength = $dataLength;
$gzData = $data;
$gzType = "\x00\x00"; // Compression type 0 = stored
$gpFlags = "\x00\x00"; // Compression type 0 = stored
}
if (!is_resource($this->zipFile) && ($this->offset + $gzLength) > $this->zipMemoryThreshold) {
$this->zipflush();
}
$this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
$this->zipwrite($gzData);
return TRUE;
}
/**
* Add the content to a directory.
*
* @author Adam Schmalhofer <Adam.Schmalhofer@gmx.de>
* @author A. Grandt
*
* @param string $realPath Path on the file system.
* @param string $zipPath Filepath and name to be used in the archive.
* @param bool $recursive Add content recursively, default is TRUE.
* @param bool $followSymlinks Follow and add symbolic links, if they are accessible, default is TRUE.
* @param array &$addedFiles Reference to the added files, this is used to prevent duplicates, efault is an empty array.
* If you start the function by parsing an array, the array will be populated with the realPath
* and zipPath kay/value pairs added to the archive by the function.
* @param bool $overrideFilePermissions Force the use of the file/dir permissions set in the $extDirAttr
* and $extFileAttr parameters.
* @param int $extDirAttr Permissions for directories.
* @param int $extFileAttr Permissions for files.
*/
public function addDirectoryContent($realPath, $zipPath, $recursive = TRUE, $followSymlinks = TRUE, &$addedFiles = array(),
$overrideFilePermissions = FALSE, $extDirAttr = self::EXT_FILE_ATTR_DIR, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if (file_exists($realPath) && !isset($addedFiles[realpath($realPath)])) {
if (is_dir($realPath)) {
if ($overrideFilePermissions) {
$this->addDirectory($zipPath, 0, null, $extDirAttr);
} else {
$this->addDirectory($zipPath, 0, null, self::getFileExtAttr($realPath));
}
}
$addedFiles[realpath($realPath)] = $zipPath;
$iter = new DirectoryIterator($realPath);
foreach ($iter as $file) {
if ($file->isDot()) {
continue;
}
$newRealPath = $file->getPathname();
$newZipPath = self::pathJoin($zipPath, $file->getFilename());
if (file_exists($newRealPath) && ($followSymlinks === TRUE || !is_link($newRealPath))) {
if ($file->isFile()) {
$addedFiles[realpath($newRealPath)] = $newZipPath;
if ($overrideFilePermissions) {
$this->addLargeFile($newRealPath, $newZipPath, 0, null, $extFileAttr);
} else {
$this->addLargeFile($newRealPath, $newZipPath, 0, null, self::getFileExtAttr($newRealPath));
}
} else if ($recursive === TRUE) {
$this->addDirectoryContent($newRealPath, $newZipPath, $recursive, $followSymlinks, $addedFiles, $overrideFilePermissions, $extDirAttr, $extFileAttr);
} else {
if ($overrideFilePermissions) {
$this->addDirectory($zipPath, 0, null, $extDirAttr);
} else {
$this->addDirectory($zipPath, 0, null, self::getFileExtAttr($newRealPath));
}
}
}
}
}
}
/**
* Add a file to the archive at the specified location and file name.
*
* @param string $dataFile File name/path.
* @param string $filePath Filepath and name to be used in the archive.
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if ($this->isFinalized) {
return FALSE;
}
if (is_string($dataFile) && is_file($dataFile)) {
$this->processFile($dataFile, $filePath, $timestamp, $fileComment, $extFileAttr);
} else if (is_resource($dataFile) && get_resource_type($dataFile) == "stream") {
$fh = $dataFile;
$this->openStream($filePath, $timestamp, $fileComment, $extFileAttr);
while (!feof($fh)) {
$this->addStreamData(fread($fh, $this->streamChunkSize));
}
$this->closeStream($this->addExtraField);
}
return TRUE;
}
/**
* Create a stream to be used for large entries.
*
* @param string $filePath Filepath and name to be used in the archive.
* @param int $timestamp (Optional) Timestamp for the added file, if omitted or set to 0, the current time will be used.
* @param string $fileComment (Optional) Comment to be added to the archive for this file. To use fileComment, timestamp must be given.
* @param int $extFileAttr (Optional) The external file reference, use generateExtAttr to generate this.
* @return bool $success
*/
public function openStream($filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if (!function_exists('sys_get_temp_dir')) {
die ("ERROR: Zip " . self::VERSION . " requires PHP version 5.2.1 or above if large files are used.");
}
if ($this->isFinalized) {
return FALSE;
}
$this->zipflush();
if (strlen($this->streamFilePath) > 0) {
$this->closeStream();
}
$this->streamFile = tempnam(sys_get_temp_dir(), 'Zip');
$this->streamData = fopen($this->streamFile, "wb");
$this->streamFilePath = $filePath;
$this->streamTimestamp = $timestamp;
$this->streamFileComment = $fileComment;
$this->streamFileLength = 0;
$this->streamExtFileAttr = $extFileAttr;
return TRUE;
}
/**
* Add data to the open stream.
*
* @param string $data
* @return mixed length in bytes added or FALSE if the archive is finalized or there are no open stream.
*/
public function addStreamData($data) {
if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
return FALSE;
}
$length = fwrite($this->streamData, $data, strlen($data));
if ($length != strlen($data)) {
die ("<p>Length mismatch</p>\n");
}
$this->streamFileLength += $length;
return $length;
}
/**
* Close the current stream.
*
* @return bool $success
*/
public function closeStream() {
if ($this->isFinalized || strlen($this->streamFilePath) == 0) {
return FALSE;
}
fflush($this->streamData);
fclose($this->streamData);
$this->processFile($this->streamFile, $this->streamFilePath, $this->streamTimestamp, $this->streamFileComment, $this->streamExtFileAttr);
$this->streamData = null;
$this->streamFilePath = null;
$this->streamTimestamp = null;
$this->streamFileComment = null;
$this->streamFileLength = 0;
$this->streamExtFileAttr = null;
// Windows is a little slow at times, so a millisecond later, we can unlink this.
unlink($this->streamFile);
$this->streamFile = null;
return TRUE;
}
private function processFile($dataFile, $filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) {
if ($this->isFinalized) {
return FALSE;
}
$tempzip = tempnam(sys_get_temp_dir(), 'ZipStream');
$zip = new ZipArchive;
if ($zip->open($tempzip) === TRUE) {
$zip->addFile($dataFile, 'file');
$zip->close();
}
$file_handle = fopen($tempzip, "rb");
$stats = fstat($file_handle);
$eof = $stats['size']-72;
fseek($file_handle, 6);
$gpFlags = fread($file_handle, 2);
$gzType = fread($file_handle, 2);
fread($file_handle, 4);
$fileCRC32 = fread($file_handle, 4);
$v = unpack("Vval", fread($file_handle, 4));
$gzLength = $v['val'];
$v = unpack("Vval", fread($file_handle, 4));
$dataLength = $v['val'];
$this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr);
fseek($file_handle, 34);
$pos = 34;
while (!feof($file_handle) && $pos < $eof) {
$datalen = $this->streamChunkSize;
if ($pos + $this->streamChunkSize > $eof) {
$datalen = $eof-$pos;
}
$data = fread($file_handle, $datalen);
$pos += $datalen;
$this->zipwrite($data);
}
fclose($file_handle);
unlink($tempzip);
}
/**
* Close the archive.
* A closed archive can no longer have new files added to it.
*
* @return bool $success
*/
public function finalize() {
if (!$this->isFinalized) {
if (strlen($this->streamFilePath) > 0) {
$this->closeStream();
}
$cd = implode("", $this->cdRec);
$cdRecSize = pack("v", sizeof($this->cdRec));
$cdRec = $cd . self::ZIP_END_OF_CENTRAL_DIRECTORY
. $cdRecSize . $cdRecSize
. pack("VV", strlen($cd), $this->offset);
if (!empty($this->zipComment)) {
$cdRec .= pack("v", strlen($this->zipComment)) . $this->zipComment;
} else {
$cdRec .= "\x00\x00";
}
$this->zipwrite($cdRec);
$this->isFinalized = TRUE;
$this->cdRec = NULL;
return TRUE;
}
return FALSE;
}
/**
* Get the handle ressource for the archive zip file.
* If the zip haven't been finalized yet, this will cause it to become finalized
*
* @return zip file handle
*/
public function getZipFile() {
if (!$this->isFinalized) {
$this->finalize();
}
$this->zipflush();
rewind($this->zipFile);
return $this->zipFile;
}
/**
* Get the zip file contents
* If the zip haven't been finalized yet, this will cause it to become finalized
*
* @return zip data
*/
public function getZipData() {
if (!$this->isFinalized) {
$this->finalize();
}
if (!is_resource($this->zipFile)) {
return $this->zipData;
} else {
rewind($this->zipFile);
$filestat = fstat($this->zipFile);
return fread($this->zipFile, $filestat['size']);
}
}
/**
* Send the archive as a zip download
*
* @param String $fileName The name of the Zip archive, in ISO-8859-1 (or ASCII) encoding, ie. "archive.zip". Optional, defaults to NULL, which means that no ISO-8859-1 encoded file name will be specified.
* @param String $contentType Content mime type. Optional, defaults to "application/zip".
* @param String $utf8FileName The name of the Zip archive, in UTF-8 encoding. Optional, defaults to NULL, which means that no UTF-8 encoded file name will be specified.
* @param bool $inline Use Content-Disposition with "inline" instead of "attached". Optional, defaults to FALSE.
* @return bool $success
*/
function sendZip($fileName = null, $contentType = "application/zip", $utf8FileName = null, $inline = false) {
if (!$this->isFinalized) {
$this->finalize();
}
$headerFile = null;
$headerLine = null;
if (!headers_sent($headerFile, $headerLine) or die("<p><strong>Error:</strong> Unable to send file $fileName. HTML Headers have already been sent from <strong>$headerFile</strong> in line <strong>$headerLine</strong></p>")) {
if ((ob_get_contents() === FALSE || ob_get_contents() == '') or die("\n<p><strong>Error:</strong> Unable to send file <strong>$fileName</strong>. Output buffer contains the following text (typically warnings or errors):<br>" . htmlentities(ob_get_contents()) . "</p>")) {
if (ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
header("Pragma: public");
header("Last-Modified: " . gmdate("D, d M Y H:i:s T"));
header("Expires: 0");
header("Accept-Ranges: bytes");
header("Connection: close");
header("Content-Type: " . $contentType);
$cd = "Content-Disposition: ";
if ($inline) {
$cd .= "inline";
} else{
$cd .= "attached";
}
if ($fileName) {
$cd .= '; filename="' . $fileName . '"';
}
if ($utf8FileName) {
$cd .= "; filename*=UTF-8''" . rawurlencode($utf8FileName);
}
header($cd);
header("Content-Length: ". $this->getArchiveSize());
if (!is_resource($this->zipFile)) {
echo $this->zipData;
} else {
rewind($this->zipFile);
while (!feof($this->zipFile)) {
echo fread($this->zipFile, $this->streamChunkSize);
}
}
}
return TRUE;
}
return FALSE;
}
/**
* Return the current size of the archive
*
* @return $size Size of the archive
*/
public function getArchiveSize() {
if (!is_resource($this->zipFile)) {
return strlen($this->zipData);
}
$filestat = fstat($this->zipFile);
return $filestat['size'];
}
/**
* Calculate the 2 byte dostime used in the zip entries.
*
* @param int $timestamp
* @return 2-byte encoded DOS Date
*/
private function getDosTime($timestamp = 0) {
$timestamp = (int)$timestamp;
$oldTZ = @date_default_timezone_get();
date_default_timezone_set('UTC');
$date = ($timestamp == 0 ? getdate() : getdate($timestamp));
date_default_timezone_set($oldTZ);
if ($date["year"] >= 1980) {
return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"]-1980) << 9)) << 16) |
(($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11)));
}
return "\x00\x00\x00\x00";
}
/**
* Build the Zip file structures
*
* @param string $filePath
* @param string $fileComment
* @param string $gpFlags
* @param string $gzType
* @param int $timestamp
* @param string $fileCRC32
* @param int $gzLength
* @param int $dataLength
* @param int $extFileAttr Use self::EXT_FILE_ATTR_FILE for files, self::EXT_FILE_ATTR_DIR for Directories.
*/
private function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) {
$filePath = str_replace("\\", "/", $filePath);
$fileCommentLength = (empty($fileComment) ? 0 : strlen($fileComment));
$timestamp = (int)$timestamp;
$timestamp = ($timestamp == 0 ? time() : $timestamp);
$dosTime = $this->getDosTime($timestamp);
$tsPack = pack("V", $timestamp);
$ux = "\x75\x78\x0B\x00\x01\x04\xE8\x03\x00\x00\x04\x00\x00\x00\x00";
if (!isset($gpFlags) || strlen($gpFlags) != 2) {
$gpFlags = "\x00\x00";
}
$isFileUTF8 = mb_check_encoding($filePath, "UTF-8") && !mb_check_encoding($filePath, "ASCII");
$isCommentUTF8 = !empty($fileComment) && mb_check_encoding($fileComment, "UTF-8") && !mb_check_encoding($fileComment, "ASCII");
if ($isFileUTF8 || $isCommentUTF8) {
$flag = 0;
$gpFlagsV = unpack("vflags", $gpFlags);
if (isset($gpFlagsV['flags'])) {
$flag = $gpFlagsV['flags'];
}
$gpFlags = pack("v", $flag | (1 << 11));
}
$header = $gpFlags . $gzType . $dosTime. $fileCRC32
. pack("VVv", $gzLength, $dataLength, strlen($filePath)); // File name length
$zipEntry = self::ZIP_LOCAL_FILE_HEADER;
$zipEntry .= self::ATTR_VERSION_TO_EXTRACT;
$zipEntry .= $header;
$zipEntry .= pack("v", ($this->addExtraField ? 28 : 0)); // Extra field length
$zipEntry .= $filePath; // FileName
// Extra fields
if ($this->addExtraField) {
$zipEntry .= "\x55\x54\x09\x00\x03" . $tsPack . $tsPack . $ux;
}
$this->zipwrite($zipEntry);
$cdEntry = self::ZIP_CENTRAL_FILE_HEADER;
$cdEntry .= self::ATTR_MADE_BY_VERSION;
$cdEntry .= ($dataLength === 0 ? "\x0A\x00" : self::ATTR_VERSION_TO_EXTRACT);
$cdEntry .= $header;
$cdEntry .= pack("v", ($this->addExtraField ? 24 : 0)); // Extra field length
$cdEntry .= pack("v", $fileCommentLength); // File comment length
$cdEntry .= "\x00\x00"; // Disk number start
$cdEntry .= "\x00\x00"; // internal file attributes
$cdEntry .= pack("V", $extFileAttr); // External file attributes
$cdEntry .= pack("V", $this->offset); // Relative offset of local header
$cdEntry .= $filePath; // FileName
// Extra fields
if ($this->addExtraField) {
$cdEntry .= "\x55\x54\x05\x00\x03" . $tsPack . $ux;
}
if (!empty($fileComment)) {
$cdEntry .= $fileComment; // Comment
}
$this->cdRec[] = $cdEntry;
$this->offset += strlen($zipEntry) + $gzLength;
}
private function zipwrite($data) {
if (!is_resource($this->zipFile)) {
$this->zipData .= $data;
} else {
fwrite($this->zipFile, $data);
fflush($this->zipFile);
}
}
private function zipflush() {
if (!is_resource($this->zipFile)) {
$this->zipFile = tmpfile();
fwrite($this->zipFile, $this->zipData);
$this->zipData = NULL;
}
}
/**
* Join $file to $dir path, and clean up any excess slashes.
*
* @param string $dir
* @param string $file
*/
public static function pathJoin($dir, $file) {
if (empty($dir) || empty($file)) {
return self::getRelativePath($dir . $file);
}
return self::getRelativePath($dir . '/' . $file);
}
/**
* Clean up a path, removing any unnecessary elements such as /./, // or redundant ../ segments.
* If the path starts with a "/", it is deemed an absolute path and any /../ in the beginning is stripped off.
* The returned path will not end in a "/".
*
* Sometimes, when a path is generated from multiple fragments,
* you can get something like "../data/html/../images/image.jpeg"
* This will normalize that example path to "../data/images/image.jpeg"
*
* @param string $path The path to clean up
* @return string the clean path
*/
public static function getRelativePath($path) {
$path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path));
$dirs = explode("/", rtrim(preg_replace('#^(?:\./)+#', '', $path), '/'));
$offset = 0;
$sub = 0;
$subOffset = 0;
$root = "";
if (empty($dirs[0])) {
$root = "/";
$dirs = array_splice($dirs, 1);
} else if (preg_match("#[A-Za-z]:#", $dirs[0])) {
$root = strtoupper($dirs[0]) . "/";
$dirs = array_splice($dirs, 1);
}
$newDirs = array();
foreach ($dirs as $dir) {
if ($dir !== "..") {
$subOffset--;
$newDirs[++$offset] = $dir;
} else {
$subOffset++;
if (--$offset < 0) {
$offset = 0;
if ($subOffset > $sub) {
$sub++;
}
}
}
}
if (empty($root)) {
$root = str_repeat("../", $sub);
}
return $root . implode("/", array_slice($newDirs, 0, $offset));
}
/**
* Create the file permissions for a file or directory, for use in the extFileAttr parameters.
*
* @param int $owner Unix permisions for owner (octal from 00 to 07)
* @param int $group Unix permisions for group (octal from 00 to 07)
* @param int $other Unix permisions for others (octal from 00 to 07)
* @param bool $isFile
* @return EXTRERNAL_REF field.
*/
public static function generateExtAttr($owner = 07, $group = 05, $other = 05, $isFile = true) {
$fp = $isFile ? self::S_IFREG : self::S_IFDIR;
$fp |= (($owner & 07) << 6) | (($group & 07) << 3) | ($other & 07);
return ($fp << 16) | ($isFile ? self::S_DOS_A : self::S_DOS_D);
}
/**
* Get the file permissions for a file or directory, for use in the extFileAttr parameters.
*
* @param string $filename
* @return external ref field, or FALSE if the file is not found.
*/
public static function getFileExtAttr($filename) {
if (file_exists($filename)) {
$fp = fileperms($filename) << 16;
return $fp | (is_dir($filename) ? self::S_DOS_D : self::S_DOS_A);
}
return FALSE;
}
}
?>

View File

@ -0,0 +1,31 @@
DrUUID RFC4122 library for PHP5
by J. King (http://jkingweb.ca/)
Licensed under MIT license
See http://jkingweb.ca/code/php/lib.uuid/
for documentation
Last revised 2010-02-15
Copyright (c) 2009 J. King
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,314 @@
<?php
/*
DrUUID RFC4122 library for PHP5
by J. King (http://jkingweb.ca/)
Licensed under MIT license
See http://jkingweb.ca/code/php/lib.uuid/
for documentation
Last revised 2010-02-15
*/
/*
Copyright (c) 2009 J. King
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
class UUID {
const MD5 = 3;
const SHA1 = 5;
const clearVer = 15; // 00001111 Clears all bits of version byte with AND
const clearVar = 63; // 00111111 Clears all relevant bits of variant byte with AND
const varRes = 224; // 11100000 Variant reserved for future use
const varMS = 192; // 11000000 Microsft GUID variant
const varRFC = 128; // 10000000 The RFC 4122 variant (this variant)
const varNCS = 0; // 00000000 The NCS compatibility variant
const version1 = 16; // 00010000
const version3 = 48; // 00110000
const version4 = 64; // 01000000
const version5 = 80; // 01010000
const interval = 0x01b21dd213814000; // Time (in 100ns steps) between the start of the UTC and Unix epochs
const nsDNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
const nsURL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
const nsOID = '6ba7b812-9dad-11d1-80b4-00c04fd430c8';
const nsX500 = '6ba7b814-9dad-11d1-80b4-00c04fd430c8';
protected static $randomFunc = 'randomTwister';
protected static $randomSource = NULL;
//instance properties
protected $bytes;
protected $hex;
protected $string;
protected $urn;
protected $version;
protected $variant;
protected $node;
protected $time;
public static function mint($ver = 1, $node = NULL, $ns = NULL) {
/* Create a new UUID based on provided data. */
switch((int) $ver) {
case 1:
return new self(self::mintTime($node));
case 2:
// Version 2 is not supported
throw new UUIDException("Version 2 is unsupported.");
case 3:
return new self(self::mintName(self::MD5, $node, $ns));
case 4:
return new self(self::mintRand());
case 5:
return new self(self::mintName(self::SHA1, $node, $ns));
default:
throw new UUIDException("Selected version is invalid or unsupported.");
}
}
public static function import($uuid) {
/* Import an existing UUID. */
return new self(self::makeBin($uuid, 16));
}
public static function compare($a, $b) {
/* Compares the binary representations of two UUIDs.
The comparison will return true if they are bit-exact,
or if neither is valid. */
if (self::makeBin($a, 16)==self::makeBin($b, 16)) {
return TRUE;
} else {
return FALSE;
}
}
public function __toString() {
return $this->string;
}
public function __get($var) {
switch($var) {
case "bytes":
return $this->bytes;
case "hex":
return bin2hex($this->bytes);
case "string":
return $this->__toString();
case "urn":
return "urn:uuid:".$this->__toString();
case "version":
return ord($this->bytes[6]) >> 4;
case "variant":
$byte = ord($this->bytes[8]);
if ($byte >= self::varRes) {
return 3;
}
if ($byte >= self::varMS) {
return 2;
}
if ($byte >= self::varRFC) {
return 1;
}
return 0;
case "node":
if (ord($this->bytes[6])>>4==1) {
return bin2hex(substr($this->bytes,10));
} else {
return NULL;
}
case "time":
if (ord($this->bytes[6])>>4==1) {
// Restore contiguous big-endian byte order
$time = bin2hex($this->bytes[6].$this->bytes[7].$this->bytes[4].$this->bytes[5].$this->bytes[0].$this->bytes[1].$this->bytes[2].$this->bytes[3]);
// Clear version flag
$time[0] = "0";
// Do some reverse arithmetic to get a Unix timestamp
$time = (hexdec($time) - self::interval) / 10000000;
return $time;
} else {
return NULL;
}
default:
return NULL;
}
}
protected function __construct($uuid) {
if (strlen($uuid) != 16) {
throw new UUIDException("Input must be a 128-bit integer.");
}
$this->bytes = $uuid;
// Optimize the most common use
$this->string =
bin2hex(substr($uuid,0,4))."-".
bin2hex(substr($uuid,4,2))."-".
bin2hex(substr($uuid,6,2))."-".
bin2hex(substr($uuid,8,2))."-".
bin2hex(substr($uuid,10,6));
}
protected static function mintTime($node = NULL) {
/* Generates a Version 1 UUID.
These are derived from the time at which they were generated. */
// Get time since Gregorian calendar reform in 100ns intervals
// This is exceedingly difficult because of PHP's (and pack()'s)
// integer size limits.
// Note that this will never be more accurate than to the microsecond.
$time = microtime(1) * 10000000 + self::interval;
// Convert to a string representation
$time = sprintf("%F", $time);
preg_match("/^\d+/", $time, $time); //strip decimal point
// And now to a 64-bit binary representation
$time = base_convert($time[0], 10, 16);
$time = pack("H*", str_pad($time, 16, "0", STR_PAD_LEFT));
// Reorder bytes to their proper locations in the UUID
$uuid = $time[4].$time[5].$time[6].$time[7].$time[2].$time[3].$time[0].$time[1];
// Generate a random clock sequence
$uuid .= self::randomBytes(2);
// set variant
$uuid[8] = chr(ord($uuid[8]) & self::clearVar | self::varRFC);
// set version
$uuid[6] = chr(ord($uuid[6]) & self::clearVer | self::version1);
// Set the final 'node' parameter, a MAC address
if ($node) {
$node = self::makeBin($node, 6);
}
if (!$node) {
// If no node was provided or if the node was invalid,
// generate a random MAC address and set the multicast bit
$node = self::randomBytes(6);
$node[0] = pack("C", ord($node[0]) | 1);
}
$uuid .= $node;
return $uuid;
}
protected static function mintRand() {
/* Generate a Version 4 UUID.
These are derived soly from random numbers. */
// generate random fields
$uuid = self::randomBytes(16);
// set variant
$uuid[8] = chr(ord($uuid[8]) & self::clearVar | self::varRFC);
// set version
$uuid[6] = chr(ord($uuid[6]) & self::clearVer | self::version4);
return $uuid;
}
protected static function mintName($ver, $node, $ns) {
/* Generates a Version 3 or Version 5 UUID.
These are derived from a hash of a name and its namespace, in binary form. */
if (!$node) {
throw new UUIDException("A name-string is required for Version 3 or 5 UUIDs.");
}
// if the namespace UUID isn't binary, make it so
$ns = self::makeBin($ns, 16);
if (!$ns) {
throw new UUIDException("A binary namespace is required for Version 3 or 5 UUIDs.");
}
$uuid = null;
$version = self::version3;
switch($ver) {
case self::MD5:
$version = self::version3;
$uuid = md5($ns.$node,1);
break;
case self::SHA1:
$version = self::version5;
$uuid = substr(sha1($ns.$node,1),0, 16);
break;
}
// set variant
$uuid[8] = chr(ord($uuid[8]) & self::clearVar | self::varRFC);
// set version
$uuid[6] = chr(ord($uuid[6]) & self::clearVer | $version);
return ($uuid);
}
protected static function makeBin($str, $len) {
/* Insure that an input string is either binary or hexadecimal.
Returns binary representation, or false on failure. */
if ($str instanceof self) {
return $str->bytes;
}
if (strlen($str)==$len) {
return $str;
} else {
$str = preg_replace("/^urn:uuid:/is", "", $str); // strip URN scheme and namespace
}
$str = preg_replace("/[^a-f0-9]/is", "", $str); // strip non-hex characters
if (strlen($str) != ($len * 2)) {
return FALSE;
} else {
return pack("H*", $str);
}
}
public static function initRandom() {
/* Look for a system-provided source of randomness, which is usually crytographically secure.
/dev/urandom is tried first simply out of bias for Linux systems. */
if (is_readable('/dev/urandom')) {
self::$randomSource = fopen('/dev/urandom', 'rb');
self::$randomFunc = 'randomFRead';
}
else if (class_exists('COM', 0)) {
try {
self::$randomSource = new COM('CAPICOM.Utilities.1'); // See http://msdn.microsoft.com/en-us/library/aa388182(VS.85).aspx
self::$randomFunc = 'randomCOM';
}
catch(Exception $e) {
}
}
return self::$randomFunc;
}
public static function randomBytes($bytes) {
return call_user_func(array('self', self::$randomFunc), $bytes);
}
protected static function randomTwister($bytes) {
/* Get the specified number of random bytes, using mt_rand().
Randomness is returned as a string of bytes. */
$rand = "";
for ($a = 0; $a < $bytes; $a++) {
$rand .= chr(mt_rand(0, 255));
}
return $rand;
}
protected static function randomFRead($bytes) {
/* Get the specified number of random bytes using a file handle
previously opened with UUID::initRandom().
Randomness is returned as a string of bytes. */
return fread(self::$randomSource, $bytes);
}
protected static function randomCOM($bytes) {
/* Get the specified number of random bytes using Windows'
randomness source via a COM object previously created by UUID::initRandom().
Randomness is returned as a string of bytes. */
return base64_decode(self::$randomSource->GetRandom($bytes,0)); // straight binary mysteriously doesn't work, hence the base64
}
}
class UUIDException extends Exception {
}

View File

@ -1149,4 +1149,121 @@ class Poche
return new HTMLPurifier($config);
}
/**
* handle epub
*/
public function createEpub() {
switch ($_GET['method']) {
case 'id':
$entryID = filter_var($_GET['id'],FILTER_SANITIZE_NUMBER_INT);
$entry = $this->store->retrieveOneById($entryID, $this->user->getId());
$entries = array($entry);
$bookTitle = $entry['title'];
$bookFileName = substr($bookTitle, 0, 200);
break;
case 'all':
$entries = $this->store->retrieveAll($this->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'));
break;
case 'tag':
$tag = filter_var($_GET['tag'],FILTER_SANITIZE_STRING);
$tags_id = $this->store->retrieveAllTags($this->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->store->retrieveEntriesByTag($tag_id,$this->user->getId());
$bookTitle = sprintf(_('Articles tagged %s'),$tag);
$bookFileName = substr(sprintf(_('Tag %s'),$tag), 0, 200);
break;
case 'category':
$category = filter_var($_GET['category'],FILTER_SANITIZE_STRING);
$entries = $this->store->getEntriesByView($category,$this->user->getId());
$bookTitle = sprintf(_('All articles in category %s'), $category);
$bookFileName = substr(sprintf(_('Category %s'),$category), 0, 200);
break;
case 'search':
$search = filter_var($_GET['search'],FILTER_SANITIZE_STRING);
$entries = $this->store->search($search,$this->user->getId());
$bookTitle = sprintf(_('All articles for search %s'), $search);
$bookFileName = substr(sprintf(_('Search %s'), $search), 0, 200);
break;
case 'default':
die(_('Uh, there is a problem while generating epub.'));
}
$content_start =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
. "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:epub=\"http://www.idpf.org/2007/ops\">\n"
. "<head>"
. "<meta http-equiv=\"Default-Style\" content=\"text/html; charset=utf-8\" />\n"
. "<title>wallabag articles book</title>\n"
. "</head>\n"
. "<body>\n";
$bookEnd = "</body>\n</html>\n";
$log = new Logger("wallabag", TRUE);
$fileDir = CACHE;
$book = new EPub(EPub::BOOK_VERSION_EPUB3);
$log->logLine("new EPub()");
$log->logLine("EPub class version: " . EPub::VERSION);
$log->logLine("EPub Req. Zip version: " . EPub::REQ_ZIP_VERSION);
$log->logLine("Zip version: " . Zip::VERSION);
$log->logLine("getCurrentServerURL: " . $book->getCurrentServerURL());
$log->logLine("getCurrentPageURL..: " . $book->getCurrentPageURL());
$book->setTitle(_('wallabag\'s articles'));
$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"));
$book->setAuthor("wallabag","wallabag");
$book->setPublisher("wallabag","wallabag"); // I hope this is a non existant address :)
$book->setDate(time()); // Strictly not needed as the book date defaults to time().
//$book->setRights("Copyright and licence information specific for the book."); // As this is generated, this _could_ contain the name or licence information of the user who purchased the book, if needed. If this is used that way, the identifier must also be made unique for the book.
$book->setSourceURL("http://$_SERVER[HTTP_HOST]");
$book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, "PHP");
$book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, "wallabag");
$cssData = "body {\n margin-left: .5em;\n margin-right: .5em;\n text-align: justify;\n}\n\np {\n font-family: serif;\n font-size: 10pt;\n text-align: justify;\n text-indent: 1em;\n margin-top: 0px;\n margin-bottom: 1ex;\n}\n\nh1, h2 {\n font-family: sans-serif;\n font-style: italic;\n text-align: center;\n background-color: #6b879c;\n color: white;\n width: 100%;\n}\n\nh1 {\n margin-bottom: 2px;\n}\n\nh2 {\n margin-top: -2px;\n margin-bottom: 2px;\n}\n";
$log->logLine("Add Cover");
$fullTitle = "<h1> " . $bookTitle . "</h1>\n";
$book->setCoverImage("Cover.png", file_get_contents("themes/baggy/img/apple-touch-icon-152.png"), "image/png", $fullTitle);
$cover = $content_start . _('<span style="text-align:center;display:block;">Produced by wallabag with PHPePub</span>') . $bookEnd;
//$book->addChapter("Table of Contents", "TOC.xhtml", NULL, false, EPub::EXTERNAL_REF_IGNORE);
$book->addChapter("Notices", "Cover2.html", $cover);
$book->buildTOC();
foreach ($entries as $entry) {
$tags = $this->store->retrieveTagsByEntry($entry['id']);
foreach ($tags as $tag) {
$book->setSubject($tag['value']);
}
$log->logLine("Set up parameters");
$chapter = $content_start . $entry['content'] . $bookEnd;
$book->addChapter($entry['title'], htmlspecialchars($entry['title']) . ".html", $chapter, true, EPub::EXTERNAL_REF_ADD);
$log->logLine("Added chapter " . $entry['title']);
}
if (DEBUG_POCHE) {
$epuplog = $book->getLog();
$book->addChapter("Log", "Log.html", $content_start . $log->getLog() . "\n</pre>" . $bookEnd); // generation log
// Only used in case we need to debug EPub.php.
//$book->addChapter("ePubLog", "ePubLog.html", $content_start . $epuplog . "\n</pre>" . $bookEnd);
}
$book->finalize();
$zipData = $book->sendBook($bookFileName);
}
}

View File

@ -31,6 +31,11 @@ require_once INCLUDES . '/3rdparty/FlattrItem.class.php';
require_once INCLUDES . '/3rdparty/htmlpurifier/HTMLPurifier.auto.php';
# epub library
require_once INCLUDES . '/3rdparty/libraries/PHPePub/Logger.php';
require_once INCLUDES . '/3rdparty/libraries/PHPePub/EPub.php';
require_once INCLUDES . '/3rdparty/libraries/PHPePub/EPubChapterSplitter.php';
# Composer its autoloader for automatically loading Twig
if (! file_exists(ROOT . '/vendor/autoload.php')) {
Poche::$canRenderTemplates = false;

View File

@ -70,6 +70,8 @@ if (isset($_GET['login'])) {
$poche->createNewUser();
} elseif (isset($_GET['deluser'])) {
$poche->deleteUser();
} elseif (isset($_GET['epub'])) {
$poche->createEpub();
} elseif (isset($_GET['import'])) {
$import = $poche->import();
$tpl_vars = array_merge($tpl_vars, $import);

View File

@ -1,19 +1,19 @@
msgid ""
msgstr ""
"Project-Id-Version: wallabag 1.6.0\n"
"Project-Id-Version: wallabag 1.6.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-25 18:33+0300\n"
"POT-Creation-Date: 2014-05-10 20:09+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: Amaury Carrade <amaury.public@carrade.eu>\n"
"Last-Translator: Mickaël RAYBAUD-ROIG <raybaudroigm@gmail.com>\n"
"Language-Team: \n"
"Language: fr_FR\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-SourceCharset: UTF-8\n"
"X-Generator: Poedit 1.6.4\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language: fr_FR\n"
"X-Generator: Poedit 1.5.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "wallabag, a read it later open source system"
msgstr "wallabag, un système open source de lecture différé"
@ -21,9 +21,97 @@ msgstr "wallabag, un système open source de lecture différé"
msgid "login failed: user doesn't exist"
msgstr "échec de l'identification : cet utilisateur n'existe pas"
msgid "return home"
msgid "save link!"
msgstr "enregistrer le lien !"
msgid "plop"
msgstr "plop"
msgid "powered by"
msgstr "propulsé par"
msgid "debug mode is on so cache is off."
msgstr "le mode de debug est actif, le cache est donc désactivé."
msgid "your wallabag version:"
msgstr "votre version de wallabag :"
msgid "storage:"
msgstr "stockage :"
msgid "login to your wallabag"
msgstr "se connecter à votre wallabag"
msgid "Login to wallabag"
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."
msgid "Username"
msgstr "Nom d'utilisateur"
msgid "Password"
msgstr "Mot de passe"
msgid "Stay signed in"
msgstr "Rester connecté"
msgid "(Do not check on public computers)"
msgstr "(Ne pas cocher sur un ordinateur public)"
msgid "Sign in"
msgstr "Se connecter"
msgid "back to home"
msgstr "retour à l'accueil"
msgid "favorites"
msgstr "favoris"
msgid "archive"
msgstr "archive"
msgid "unread"
msgstr "non lus"
msgid "Tag"
msgstr "Tag"
msgid "No articles found."
msgstr "Aucun article trouvé."
msgid "estimated reading time:"
msgstr "temps de lecture estimé :"
msgid "estimated reading time :"
msgstr "temps de lecture estimé :"
msgid "Toggle mark as read"
msgstr "Marquer comme lu / non lu"
msgid "toggle favorite"
msgstr "marquer / enlever comme favori"
msgid "delete"
msgstr "supprimer"
msgid "original"
msgstr "original"
msgid "Mark all the entries as read"
msgstr "Marquer tous les articles comme lus"
msgid "results"
msgstr "résultats"
msgid " found for « "
msgstr "trouvé pour « "
msgid "Only one result found for "
msgstr "Seulement un résultat trouvé pour "
msgid "config"
msgstr "configuration"
@ -75,17 +163,29 @@ msgstr "Une version stable plus récente est disponible."
msgid "You are up to date."
msgstr "Vous êtes à jour."
msgid "Last check:"
msgstr "Dernière vérification: "
msgid "Latest dev version"
msgstr "Dernière version de développement"
msgid "A more recent development version is available."
msgstr "Une version de développement plus récente est disponible."
msgid "You can clear cache to check the latest release."
msgstr ""
"Vous pouvez vider le cache pour vérifier que vous avez la dernière version."
msgid "Feeds"
msgstr "Flux"
msgid "Your feed token is currently empty and must first be generated to enable feeds. Click <a href='?feed&amp;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&amp;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&amp;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&amp;action=generate'>ici</a> pour "
"le générer."
msgid "Unread feed"
msgstr "Flux des non lus"
@ -102,8 +202,12 @@ msgstr "Votre jeton :"
msgid "Your user id:"
msgstr "Votre ID utilisateur :"
msgid "You can regenerate your token: <a href='?feed&amp;action=generate'>generate!</a>."
msgstr "Vous pouvez regénérer votre jeton : <a href='?feed&amp;action=generate'>génération !</a>."
msgid ""
"You can regenerate your token: <a href='?feed&amp;action=generate'>generate!"
"</a>."
msgstr ""
"Vous pouvez regénérer votre jeton : <a href='?feed&amp;"
"action=generate'>génération !</a>."
msgid "Change your theme"
msgstr "Changer votre thème"
@ -126,36 +230,40 @@ msgstr "Modifier votre mot de passe"
msgid "New password:"
msgstr "Nouveau mot de passe :"
msgid "Password"
msgstr "Mot de passe"
msgid "Repeat your new password:"
msgstr "Répétez votre nouveau mot de passe :"
msgid "Import"
msgstr "Importer"
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 ""
"You can import your Pocket, Readability, Instapaper, Wallabag or any data in "
"appropriate json or html format."
msgstr ""
"Vous pouvez importer depuis Pocket, Readability, Instapaper, Wallabag, ou "
"n'importe quel fichier au format JSON ou HTML approprié."
msgid "More info in the official documentation:"
msgstr "Plus d'infos dans la documentation officielle :"
msgid ""
"Please select export file on your computer and press \"Import\" button below."
"<br>Wallabag will parse your file, insert all URLs and start fetching of "
"articles if required.<br>Fetching process is controlled by two constants in "
"your config file: IMPORT_LIMIT (how many articles are fetched at once) and "
"IMPORT_DELAY (delay between fetch of next batch of articles)."
msgstr ""
"Sélectionner le fichier à importer sur votre disque dur, et pressez la "
"bouton « Importer » ci-dessous.<br />Wallabag analysera votre fichier, "
"ajoutera toutes les URL trouvées et commencera à télécharger les contenus si "
"nécessaire.<br />Le processus de téléchargement est contrôlé par deux "
"constantes dans votre fichier de configuration:<wbr /><code>IMPORT_LIMIT</"
"code> (nombre d'éléments téléchargés à la fois) et <code>IMPORT_DELAY</code> "
"(le délai d'attente entre deux séquences de téléchargement)."
msgid "Import from Pocket"
msgstr "Import depuis Pocket"
msgid "File:"
msgstr "Fichier: "
#, php-format
msgid "(you must have a %s file on your server)"
msgstr "(le fichier %s doit être présent sur le serveur)"
msgid "Import from Readability"
msgstr "Importer depuis Readability"
msgid "Import from Instapaper"
msgstr "Importer depuis Instapaper"
msgid "Import from wallabag"
msgstr "Importer depuis wallabag"
msgid "You can click here to fetch content for articles with no content."
msgstr ""
"Vous pouvez cliquer ici pour télécharger le contenu des articles vides."
msgid "Export your wallabag data"
msgstr "Exporter vos données de wallabag"
@ -175,110 +283,50 @@ msgstr "Cache"
msgid "to delete cache."
msgstr "pour effacer le cache."
msgid "You can enter multiple tags, separated by commas."
msgstr "Vous pouvez entrer plusieurs tags, séparés par des virgules."
msgid "Add user"
msgstr "Ajouter un utilisateur"
msgid "return to article"
msgstr "retourner à l'article"
msgid "Add a new user :"
msgstr "Ajouter un nouvel utilisateur: "
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 "favoris"
msgstr "favoris"
msgid "archive"
msgstr "archive"
msgid "unread"
msgstr "non lus"
msgid "by date asc"
msgstr "par date asc"
msgid "by date"
msgstr "par date"
msgid "by date desc"
msgstr "par date desc"
msgid "by title asc"
msgstr "par titre asc"
msgid "by title"
msgstr "par titre"
msgid "by title desc"
msgstr "par titre desc"
msgid "Tag"
msgstr "Tag"
msgid "No articles found."
msgstr "Aucun article trouvé."
msgid "Toggle mark as read"
msgstr "Marquer comme lu / non lu"
msgid "toggle favorite"
msgstr "marquer / enlever comme favori"
msgid "delete"
msgstr "supprimer"
msgid "original"
msgstr "original"
msgid "estimated reading time:"
msgstr "temps de lecture estimé :"
msgid "mark all the entries as read"
msgstr "marquer tous les articles comme lus"
msgid "results"
msgstr "résultats"
msgid "installation"
msgstr "installation"
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 "Login for new user"
msgstr "Identifiant du nouvel utilisateur"
msgid "Login"
msgstr "Nom d'utilisateur"
msgid "Repeat your password"
msgstr "Répétez votre mot de passe"
msgid "Password for new user"
msgstr "Mot de passe du nouvel utilisateur: "
msgid "Install"
msgstr "Installer"
msgid "Send"
msgstr "Imvoyer"
msgid "login to your wallabag"
msgstr "se connecter à votre wallabag"
msgid "Delete account"
msgstr "Supprimer le compte"
msgid "Login to wallabag"
msgstr "Se connecter à wallabag"
msgid "You can delete your account by entering your password and validating."
msgstr ""
"Vous pouvez supprimer votre compte en entrant votre mot de passe et en "
"validant."
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."
msgid "Be careful, data will be erased forever (that is a very long time)."
msgstr "Attention, les données seront perdues pour toujours."
msgid "Username"
msgstr "Nom d'utilisateur"
msgid "Type here your password"
msgstr "Entrez votre mot de passe ici"
msgid "Stay signed in"
msgstr "Rester connecté"
msgid "You are the only user, you cannot delete your own account."
msgstr ""
"Vous êtes l'unique utilisateur, vous ne pouvez pas supprimer votre compte."
msgid "(Do not check on public computers)"
msgstr "(Ne pas cocher sur un ordinateur public)"
msgid ""
"To completely remove wallabag, delete the wallabag folder on your web server."
msgstr ""
"Pour déinstaller complètement Wallabag, supprimez le répertoire "
"<code>wallabag</code> de votre serveur Web."
msgid "Sign in"
msgstr "Se connecter"
msgid "Save a link"
msgstr "Ajouter un lien"
msgid "Return home"
msgstr "Retour accueil"
@ -310,6 +358,9 @@ msgstr "Shaarli"
msgid "flattr"
msgstr "Flattr"
msgid "Print"
msgstr "Imprimer"
msgid "Does this article appear wrong?"
msgstr "Cet article s'affiche mal ?"
@ -319,54 +370,18 @@ msgstr "tags :"
msgid "Edit tags"
msgstr "Modifier les tags"
msgid "save link!"
msgstr "enregistrer le lien !"
msgid "powered by"
msgstr "propulsé par"
msgid "debug mode is on so cache is off."
msgstr "le mode de debug est actif, le cache est donc désactivé."
msgid "your wallabag version:"
msgstr "votre version de wallabag :"
msgid "storage:"
msgstr "stockage :"
msgid "home"
msgstr "accueil"
msgid "favorites"
msgid "favoris"
msgstr "favoris"
msgid "tags"
msgstr "tags"
msgid "mark all the entries as read"
msgstr "marquer tous les articles comme lus"
msgid "save a link"
msgstr "sauver un lien"
msgid "toggle view mode"
msgstr "changer de mode de visualisation"
msgid "logout"
msgstr "déconnexion"
msgid "back to home"
msgid "return home"
msgstr "retour à l'accueil"
msgid "toggle mark as read"
msgstr "marquer comme lu / non lu"
msgid "tweet"
msgstr "tweet"
msgid "email"
msgstr "e-mail"
msgid "this article appears wrong?"
msgstr "cet article s'affiche mal ?"
msgid "No link available here!"
msgstr "Aucun lien n'est disponible ici !"
msgid "Poching a link"
msgstr "Enregistrer un lien"
@ -395,7 +410,9 @@ msgid "a more recent development version is available."
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 le script d'importation 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 :"
@ -403,21 +420,146 @@ msgstr "Plus d'infos dans la documentation officielle :"
msgid "import from Pocket"
msgstr "importation depuis Pocket"
#, php-format
msgid "(you must have a %s file on your server)"
msgstr "(le fichier %s doit être présent sur le serveur)"
msgid "import from Readability"
msgstr "importation depuis Readability"
msgid "import from Instapaper"
msgstr "importation depuis Instapaper"
msgid "estimated reading time :"
msgstr "temps de lecture estimé :"
msgid "Start typing for auto complete."
msgstr "Commencez à taper pour activer l'auto-complétion."
msgid "Mark all the entries as read"
msgstr "Marquer tous les articles comme lus"
msgid "You can enter multiple tags, separated by commas."
msgstr "Vous pouvez entrer plusieurs tags, séparés par des virgules."
msgid "return to article"
msgstr "retourner à l'article"
msgid "by date asc"
msgstr "par date asc"
msgid "by date"
msgstr "par date"
msgid "by date desc"
msgstr "par date desc"
msgid "by title asc"
msgstr "par titre asc"
msgid "by title"
msgstr "par titre"
msgid "by title desc"
msgstr "par titre desc"
msgid "home"
msgstr "accueil"
msgid "tags"
msgstr "tags"
msgid "save a link"
msgstr "sauver un lien"
msgid "search"
msgstr "rechercher"
msgid "logout"
msgstr "déconnexion"
msgid "installation"
msgstr "installation"
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 "Repeat your password"
msgstr "Répétez votre mot de passe"
msgid "Install"
msgstr "Installer"
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 "Tags"
msgstr "Tags"
msgid "No link available here!"
msgstr "Aucun lien n'est disponible ici !"
msgid "toggle mark as read"
msgstr "marquer comme lu / non lu"
msgid "tweet"
msgstr "tweet"
msgid "email"
msgstr "e-mail"
msgid "this article appears wrong?"
msgstr "cet article s'affiche mal ?"
msgid "Search"
msgstr "Rechercher"
msgid "Download required for "
msgstr "Téléchargement requis pour "
msgid "records"
msgstr " éléments."
msgid "Downloading next "
msgstr "Téléchargement des "
msgid "articles, please wait"
msgstr " prochains éléments, veuillez patienter"
msgid "Enter your search here"
msgstr "Entrez votre recherche ici"
#, php-format
msgid ""
"The new user %s has been installed. Do you want to <a href=\"?logout"
"\">logout ?</a>"
msgstr ""
"Le nouvel utilisateur « %s » a été ajouté. Voulez-vous vous <a href=\"?"
"logout\">déconnecter ?</a>"
#, php-format
msgid "Error : An user with the name %s already exists !"
msgstr "Erreur: Un utilisateur avec le nom « %s » existe déjà."
#, php-format
msgid "User %s has been successfully deleted !"
msgstr "L'utilisateur « %s » a bien été supprimé !"
msgid "Error : The password is wrong !"
msgstr "Erreur: Le mot de passe est incorrect !"
msgid "Error : You are the only user, you cannot delete your account !"
msgstr ""
"Erreur: Vous êtes l'unique utilisateur, vous ne pouvez pas supprimer votre "
"compte !"
msgid "Untitled"
msgstr "Sans titre"
@ -448,11 +590,15 @@ msgstr "en mode démo, vous ne pouvez pas mettre à jour le mot de passe"
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 "Vous utilisez toujours \""
msgid "that theme does not seem to be installed"
msgstr "ce thème ne semble pas installé"
@ -475,26 +621,26 @@ msgstr "bienvenue dans votre wallabag"
msgid "login failed: bad login or password"
msgstr "échec de l'identification : mauvais identifiant ou mot de passe"
msgid "import from instapaper completed"
msgstr "Importation depuis Instapaper achevée"
msgid "Untitled - Import - "
msgstr "Sans titre - Importer - "
msgid "import from pocket completed"
msgstr "Importation depuis Pocket achevée"
msgid "click to finish import"
msgstr "cliquez pour terminer l'importation"
msgid "import from Readability completed. "
msgstr "Importation depuis Readability achevée"
msgid "Articles inserted: "
msgstr "Articles ajoutés: "
msgid "import from Poche completed. "
msgstr "Importation depuis Pocket achevée"
msgid ". Please note, that some may be marked as \"read\"."
msgstr ". Notez que certains pourraient être marqués comme lus."
msgid "Unknown import provider."
msgstr "Format d'importation inconnu."
msgid "Import finished."
msgstr "Importation terminée."
msgid "Incomplete inc/poche/define.inc.php file, please define \""
msgstr "Fichier inc/poche/define.inc.php incomplet, merci de définir \""
msgid "Undefined"
msgstr "Non définit"
msgid "Could not find required \""
msgstr "Impossible de trouver \""
msgid "User with this id ("
msgstr "Utilisateur avec cet identifiant ("
msgid "Uh, there is a problem while generating feeds."
msgstr "Hum, il y a un problème lors de la génération des flux."
@ -505,11 +651,47 @@ msgstr "Cache effacé."
msgid "Oops, it seems you don't have PHP 5."
msgstr "Oups, vous ne semblez pas avoir PHP 5."
msgid "search"
msgstr "rechercher"
#~ 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 "Search"
msgstr "Rechercher"
#~ msgid "More info in the official documentation:"
#~ msgstr "Plus d'infos dans la documentation officielle :"
#~ msgid "Import from Pocket"
#~ msgstr "Import depuis Pocket"
#~ msgid "Import from Readability"
#~ msgstr "Importer depuis Readability"
#~ msgid "Import from Instapaper"
#~ msgstr "Importer depuis Instapaper"
#~ msgid "Import from wallabag"
#~ msgstr "Importer depuis wallabag"
#~ msgid "import from instapaper completed"
#~ msgstr "Importation depuis Instapaper achevée"
#~ msgid "import from pocket completed"
#~ msgstr "Importation depuis Pocket achevée"
#~ msgid "import from Readability completed. "
#~ msgstr "Importation depuis Readability achevée"
#~ msgid "import from Poche completed. "
#~ msgstr "Importation depuis Pocket achevée"
#~ msgid "Unknown import provider."
#~ 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 \""
#~ msgid "Could not find required \""
#~ msgstr "Impossible de trouver \""
#~ msgid "poche it!"
#~ msgstr "pochez-le !"

View File

@ -124,6 +124,10 @@
{% if constant('STORAGE') == 'sqlite' %}
<p><a href="?download" target="_blank">{% trans "Click here" %}</a> {% trans "to download your database." %}</p>{% endif %}
<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&amp;method=all\" title=\"Generate ePub\">this link</a> to get all your articles in one ebook (ePub 3 format)." %}
<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>
<p><a href="?empty-cache">{% trans "Click here" %}</a> {% trans "to delete cache." %}</p>

View File

@ -56,8 +56,14 @@
{% endfor %}
</div>
{% 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 %}
{% endif %}
{{ 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 tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ 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&amp;method=search&amp;search={{ 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&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
{% endif %}
{% endblock %}

View File

@ -16,6 +16,7 @@
{% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %}
{% 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&amp;method=id&amp;id={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
<li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;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>

View File

@ -12,6 +12,7 @@
{% if constant('SHARE_MAIL') == 1 %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email" title="{% trans "email" %}"><span>{% trans "email" %}</span></a></li>{% endif %}
{% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %}
{% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li class="flattrli"><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool 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" target="_blank" title="{% trans "flattr" %}"><span>{% trans "flattr" %}</span>{{ flattr.numflattrs }}</a></li>{% endif %}{% endif %}
<li><a href="./?epub&amp;method=id&amp;id={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
<li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "this article appears wrong?" %}" class="tool bad-display"><span>{% trans "this article appears wrong?" %}</span></a></li>
</ul>
</div>

View File

@ -81,6 +81,9 @@
<h2>{% trans "Export your wallabag data" %}</h2>
<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&amp;method=all\" title=\"Generate ePub\">this link</a> to get all your articles in one ebook (ePub 3 format)." %}
<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 'Add user' %}</h2>
<p>{% trans 'Add a new user :' %}</p>

View File

@ -50,6 +50,13 @@
<p>{{ entry.content|striptags|slice(0, 300) }}...</p>
</div>
{% endfor %}
{% endif %}
{{ block('pager') }}
{% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ 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&amp;method=search&amp;search={{ 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&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
{% endif %}
{% endblock %}

View File

@ -127,6 +127,10 @@
<h2>{% trans "Cache" %}</h2>
<p><a href="?empty-cache">{% trans "Click here" %}</a> {% trans "to delete cache." %}</p>
<h2>{% trans "Fancy an E-Book ?" %}</h2>
<p>{% trans "Click on <a href=\"./?epub&amp;method=all\" title=\"Generate ePub\">this link</a> to get all your articles in one ebook (ePub 3 format)." %}
<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 'Add user' %}</h2>
<p>{% trans 'Add a new user :' %}</p>
<form method="post" action="?newuser">

View File

@ -55,7 +55,14 @@
<p>{{ entry.content|striptags|slice(0, 300) }}...</p>
</div>
{% endfor %}
{% endif %}
{{ block('pager') }}
{% if view == 'home' %}{% if nb_results > 1 %}<a title="{% trans "mark all the entries as read" %}" href="./?action=archive_all">{% trans "mark all the entries as read" %}</a>{% endif %}{% endif %}
{% if tag %}<a title="{% trans "Download the articles from this tag in an epub" %}" href="./?epub&amp;method=tag&amp;tag={{ 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&amp;method=search&amp;search={{ 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&amp;method=category&amp;category={{ view }}">{% trans "Download the articles from this category in an epub" %}</a>{% endif %}
{% endif %}
{% endblock %}

View File

@ -15,6 +15,7 @@
{% if constant('SHARE_SHAARLI') == 1 %}<li><a href="{{ constant('SHAARLI_URL') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}" target="_blank" class="tool shaarli" title="{% trans "shaarli" %}"><span>{% trans "shaarli" %}</span></a></li>{% endif %}
{% if constant('FLATTR') == 1 %}{% if flattr.status == constant('FLATTRABLE') %}<li><a href="http://flattr.com/submit/auto?url={{ entry.url }}" class="tool 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" 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 print" href="javascript: window.print();"><span>{% trans "Print" %}</span></a></li>{% endif %}
<li><a href="./?epub&amp;method=id&amp;id={{ entry.id|e }}" title="Generate epub file">EPUB</a></li>
<li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{% trans "Does this article appear wrong?" %}" class="tool bad-display"><span>{% trans "Does this article appear wrong?" %}</span></a></li>
{% if constant('SHOW_READPERCENT') == 1 %}<li><div id="readLeftPercent">0%</div></li>{% endif %}
</ul>