update 1.14
|
@ -4,7 +4,7 @@ Tiny Tiny RSS
|
||||||
Web-based news feed aggregator, designed to allow you to read news from
|
Web-based news feed aggregator, designed to allow you to read news from
|
||||||
any location, while feeling as close to a real desktop application as possible.
|
any location, while feeling as close to a real desktop application as possible.
|
||||||
|
|
||||||
http://tt-rss.org
|
http://tt-rss.org (http://mirror.tt-rss.org)
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
0
source/cache/export/.empty
vendored
Executable file
0
source/cache/images/.empty
vendored
Executable file
0
source/cache/js/.empty
vendored
Executable file
0
source/cache/simplepie/.empty
vendored
Executable file
0
source/cache/upload/.empty
vendored
Normal file
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class API extends Handler {
|
class API extends Handler {
|
||||||
|
|
||||||
const API_LEVEL = 7;
|
const API_LEVEL = 9;
|
||||||
|
|
||||||
const STATUS_OK = 0;
|
const STATUS_OK = 0;
|
||||||
const STATUS_ERR = 1;
|
const STATUS_ERR = 1;
|
||||||
|
@ -77,6 +77,7 @@ class API extends Handler {
|
||||||
$this->wrap(self::STATUS_OK, array("session_id" => session_id(),
|
$this->wrap(self::STATUS_OK, array("session_id" => session_id(),
|
||||||
"api_level" => self::API_LEVEL));
|
"api_level" => self::API_LEVEL));
|
||||||
} else { // else we are not logged in
|
} else { // else we are not logged in
|
||||||
|
user_error("Failed login attempt for $login from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
|
||||||
$this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
|
$this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -199,9 +200,13 @@ class API extends Handler {
|
||||||
$include_nested = sql_bool_to_bool($_REQUEST["include_nested"]);
|
$include_nested = sql_bool_to_bool($_REQUEST["include_nested"]);
|
||||||
$sanitize_content = !isset($_REQUEST["sanitize"]) ||
|
$sanitize_content = !isset($_REQUEST["sanitize"]) ||
|
||||||
sql_bool_to_bool($_REQUEST["sanitize"]);
|
sql_bool_to_bool($_REQUEST["sanitize"]);
|
||||||
|
$force_update = sql_bool_to_bool($_REQUEST["force_update"]);
|
||||||
|
|
||||||
$override_order = false;
|
$override_order = false;
|
||||||
switch ($_REQUEST["order_by"]) {
|
switch ($_REQUEST["order_by"]) {
|
||||||
|
case "title":
|
||||||
|
$override_order = "ttrss_entries.title";
|
||||||
|
break;
|
||||||
case "date_reverse":
|
case "date_reverse":
|
||||||
$override_order = "score DESC, date_entered, updated";
|
$override_order = "score DESC, date_entered, updated";
|
||||||
break;
|
break;
|
||||||
|
@ -218,7 +223,7 @@ class API extends Handler {
|
||||||
$headlines = $this->api_get_headlines($feed_id, $limit, $offset,
|
$headlines = $this->api_get_headlines($feed_id, $limit, $offset,
|
||||||
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
|
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
|
||||||
$include_attachments, $since_id, $search, $search_mode,
|
$include_attachments, $since_id, $search, $search_mode,
|
||||||
$include_nested, $sanitize_content);
|
$include_nested, $sanitize_content, $force_update);
|
||||||
|
|
||||||
$this->wrap(self::STATUS_OK, $headlines);
|
$this->wrap(self::STATUS_OK, $headlines);
|
||||||
} else {
|
} else {
|
||||||
|
@ -310,7 +315,7 @@ class API extends Handler {
|
||||||
if ($article_id) {
|
if ($article_id) {
|
||||||
|
|
||||||
$query = "SELECT id,title,link,content,feed_id,comments,int_id,
|
$query = "SELECT id,title,link,content,feed_id,comments,int_id,
|
||||||
marked,unread,published,score,
|
marked,unread,published,score,note,lang,
|
||||||
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
|
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
|
||||||
author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title
|
author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title
|
||||||
FROM ttrss_entries,ttrss_user_entries
|
FROM ttrss_entries,ttrss_user_entries
|
||||||
|
@ -342,7 +347,9 @@ class API extends Handler {
|
||||||
"feed_id" => $line["feed_id"],
|
"feed_id" => $line["feed_id"],
|
||||||
"attachments" => $attachments,
|
"attachments" => $attachments,
|
||||||
"score" => (int)$line["score"],
|
"score" => (int)$line["score"],
|
||||||
"feed_title" => $line["feed_title"]
|
"feed_title" => $line["feed_title"],
|
||||||
|
"note" => $line["note"],
|
||||||
|
"lang" => $line["lang"]
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
||||||
|
@ -423,7 +430,7 @@ class API extends Handler {
|
||||||
|
|
||||||
$checked = false;
|
$checked = false;
|
||||||
foreach ($article_labels as $al) {
|
foreach ($article_labels as $al) {
|
||||||
if ($al[0] == $line['id']) {
|
if (feed_to_label_id($al[0]) == $line['id']) {
|
||||||
$checked = true;
|
$checked = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -447,7 +454,7 @@ class API extends Handler {
|
||||||
$assign = (bool) $this->dbh->escape_string($_REQUEST['assign']) == "true";
|
$assign = (bool) $this->dbh->escape_string($_REQUEST['assign']) == "true";
|
||||||
|
|
||||||
$label = $this->dbh->escape_string(label_find_caption(
|
$label = $this->dbh->escape_string(label_find_caption(
|
||||||
$label_id, $_SESSION["uid"]));
|
feed_to_label_id($label_id), $_SESSION["uid"]));
|
||||||
|
|
||||||
$num_updated = 0;
|
$num_updated = 0;
|
||||||
|
|
||||||
|
@ -511,7 +518,7 @@ class API extends Handler {
|
||||||
if ($unread || !$unread_only) {
|
if ($unread || !$unread_only) {
|
||||||
|
|
||||||
$row = array(
|
$row = array(
|
||||||
"id" => $cv["id"],
|
"id" => (int) $cv["id"],
|
||||||
"title" => $cv["description"],
|
"title" => $cv["description"],
|
||||||
"unread" => $cv["counter"],
|
"unread" => $cv["counter"],
|
||||||
"cat_id" => -2,
|
"cat_id" => -2,
|
||||||
|
@ -557,7 +564,7 @@ class API extends Handler {
|
||||||
|
|
||||||
if ($unread || !$unread_only) {
|
if ($unread || !$unread_only) {
|
||||||
$row = array(
|
$row = array(
|
||||||
"id" => $line["id"],
|
"id" => (int) $line["id"],
|
||||||
"title" => $line["title"],
|
"title" => $line["title"],
|
||||||
"unread" => $unread,
|
"unread" => $unread,
|
||||||
"is_cat" => true,
|
"is_cat" => true,
|
||||||
|
@ -626,7 +633,28 @@ class API extends Handler {
|
||||||
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
|
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
|
||||||
$include_attachments, $since_id,
|
$include_attachments, $since_id,
|
||||||
$search = "", $search_mode = "",
|
$search = "", $search_mode = "",
|
||||||
$include_nested = false, $sanitize_content = true) {
|
$include_nested = false, $sanitize_content = true, $force_update = false) {
|
||||||
|
|
||||||
|
if ($force_update && $feed_id > 0 && is_numeric($feed_id)) {
|
||||||
|
// Update the feed if required with some basic flood control
|
||||||
|
|
||||||
|
$result = db_query(
|
||||||
|
"SELECT cache_images,".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
|
||||||
|
FROM ttrss_feeds WHERE id = '$feed_id'");
|
||||||
|
|
||||||
|
if (db_num_rows($result) != 0) {
|
||||||
|
$last_updated = strtotime(db_fetch_result($result, 0, "last_updated"));
|
||||||
|
$cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
|
||||||
|
|
||||||
|
if (!$cache_images && time() - $last_updated > 120) {
|
||||||
|
include "rssfuncs.php";
|
||||||
|
update_rss_feed($feed_id, true, true);
|
||||||
|
} else {
|
||||||
|
db_query("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
|
||||||
|
WHERE id = '$feed_id'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$qfh_ret = queryFeedHeadlines($feed_id, $limit,
|
$qfh_ret = queryFeedHeadlines($feed_id, $limit,
|
||||||
$view_mode, $is_cat, $search, $search_mode,
|
$view_mode, $is_cat, $search, $search_mode,
|
||||||
|
@ -638,7 +666,7 @@ class API extends Handler {
|
||||||
$headlines = array();
|
$headlines = array();
|
||||||
|
|
||||||
while ($line = db_fetch_assoc($result)) {
|
while ($line = db_fetch_assoc($result)) {
|
||||||
$line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100);
|
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100);
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line, 100, true);
|
$line = $p->hook_query_headlines($line, 100, true);
|
||||||
}
|
}
|
||||||
|
@ -700,6 +728,8 @@ class API extends Handler {
|
||||||
$headline_row["author"] = $line["author"];
|
$headline_row["author"] = $line["author"];
|
||||||
|
|
||||||
$headline_row["score"] = (int)$line["score"];
|
$headline_row["score"] = (int)$line["score"];
|
||||||
|
$headline_row["note"] = $line["note"];
|
||||||
|
$headline_row["lang"] = $line["lang"];
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
|
||||||
$headline_row = $p->hook_render_article_api(array("headline" => $headline_row));
|
$headline_row = $p->hook_render_article_api(array("headline" => $headline_row));
|
||||||
|
|
|
@ -30,7 +30,6 @@ class Article extends Handler_Protected {
|
||||||
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
||||||
$cids = explode(",", $this->dbh->escape_string($_REQUEST["cids"]));
|
$cids = explode(",", $this->dbh->escape_string($_REQUEST["cids"]));
|
||||||
$mode = $this->dbh->escape_string($_REQUEST["mode"]);
|
$mode = $this->dbh->escape_string($_REQUEST["mode"]);
|
||||||
$omode = $this->dbh->escape_string($_REQUEST["omode"]);
|
|
||||||
|
|
||||||
// in prefetch mode we only output requested cids, main article
|
// in prefetch mode we only output requested cids, main article
|
||||||
// just gets marked as read (it already exists in client cache)
|
// just gets marked as read (it already exists in client cache)
|
||||||
|
@ -108,7 +107,7 @@ class Article extends Handler_Protected {
|
||||||
|
|
||||||
// only check for our user data here, others might have shared this with different content etc
|
// only check for our user data here, others might have shared this with different content etc
|
||||||
$result = db_query("SELECT id FROM ttrss_entries, ttrss_user_entries WHERE
|
$result = db_query("SELECT id FROM ttrss_entries, ttrss_user_entries WHERE
|
||||||
link = '$url' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1");
|
guid = '$guid' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1");
|
||||||
|
|
||||||
if (db_num_rows($result) != 0) {
|
if (db_num_rows($result) != 0) {
|
||||||
$ref_id = db_fetch_result($result, 0, "id");
|
$ref_id = db_fetch_result($result, 0, "id");
|
||||||
|
|
|
@ -16,7 +16,6 @@ class Dlg extends Handler_Protected {
|
||||||
print __("If you have imported labels and/or filters, you might need to reload preferences to see your new data.") . "</p>";
|
print __("If you have imported labels and/or filters, you might need to reload preferences to see your new data.") . "</p>";
|
||||||
|
|
||||||
print "<div class=\"prefFeedOPMLHolder\">";
|
print "<div class=\"prefFeedOPMLHolder\">";
|
||||||
$owner_uid = $_SESSION["uid"];
|
|
||||||
|
|
||||||
$this->dbh->query("BEGIN");
|
$this->dbh->query("BEGIN");
|
||||||
|
|
||||||
|
@ -176,7 +175,7 @@ class Dlg extends Handler_Protected {
|
||||||
|
|
||||||
while ($row = $this->dbh->fetch_assoc($result)) {
|
while ($row = $this->dbh->fetch_assoc($result)) {
|
||||||
$tmp = htmlspecialchars($row["tag_name"]);
|
$tmp = htmlspecialchars($row["tag_name"]);
|
||||||
print "<option value=\"" . str_replace(" ", "%20", $tmp) . "\">$tmp</option>";
|
print "<option value=\"$tmp\">$tmp</option>";
|
||||||
}
|
}
|
||||||
|
|
||||||
print "</select>";
|
print "</select>";
|
||||||
|
|
|
@ -4,5 +4,7 @@ class FeedEnclosure {
|
||||||
public $type;
|
public $type;
|
||||||
public $length;
|
public $length;
|
||||||
public $title;
|
public $title;
|
||||||
|
public $height;
|
||||||
|
public $width;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -43,9 +43,9 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
$base = $this->xpath->evaluate("string(ancestor-or-self::*[@xml:base][1]/@xml:base)", $link);
|
$base = $this->xpath->evaluate("string(ancestor-or-self::*[@xml:base][1]/@xml:base)", $link);
|
||||||
|
|
||||||
if ($base)
|
if ($base)
|
||||||
return rewrite_relative_url($base, $link->getAttribute("href"));
|
return rewrite_relative_url($base, trim($link->getAttribute("href")));
|
||||||
else
|
else
|
||||||
return $link->getAttribute("href");
|
return trim($link->getAttribute("href"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
$title = $this->elem->getElementsByTagName("title")->item(0);
|
$title = $this->elem->getElementsByTagName("title")->item(0);
|
||||||
|
|
||||||
if ($title) {
|
if ($title) {
|
||||||
return $title->nodeValue;
|
return trim($title->nodeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,13 +106,13 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
if ($cat->hasAttribute("term"))
|
if ($cat->hasAttribute("term"))
|
||||||
array_push($cats, $cat->getAttribute("term"));
|
array_push($cats, trim($cat->getAttribute("term")));
|
||||||
}
|
}
|
||||||
|
|
||||||
$categories = $this->xpath->query("dc:subject", $this->elem);
|
$categories = $this->xpath->query("dc:subject", $this->elem);
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
array_push($cats, $cat->nodeValue);
|
array_push($cats, trim($cat->nodeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $cats;
|
return $cats;
|
||||||
|
@ -137,7 +137,7 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$enclosures = $this->xpath->query("media:content | media:group/media:content", $this->elem);
|
$enclosures = $this->xpath->query("media:content", $this->elem);
|
||||||
|
|
||||||
foreach ($enclosures as $enclosure) {
|
foreach ($enclosures as $enclosure) {
|
||||||
$enc = new FeedEnclosure();
|
$enc = new FeedEnclosure();
|
||||||
|
@ -145,6 +145,8 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
$enc->type = $enclosure->getAttribute("type");
|
$enc->type = $enclosure->getAttribute("type");
|
||||||
$enc->link = $enclosure->getAttribute("url");
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
$enc->length = $enclosure->getAttribute("length");
|
$enc->length = $enclosure->getAttribute("length");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
@ -152,6 +154,46 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||||
array_push($encs, $enc);
|
array_push($encs, $enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:group", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$content = $this->xpath->query("media:content", $enclosure)->item(0);
|
||||||
|
|
||||||
|
if ($content) {
|
||||||
|
$enc->type = $content->getAttribute("type");
|
||||||
|
$enc->link = $content->getAttribute("url");
|
||||||
|
$enc->length = $content->getAttribute("length");
|
||||||
|
$enc->height = $content->getAttribute("height");
|
||||||
|
$enc->width = $content->getAttribute("width");
|
||||||
|
|
||||||
|
$desc = $this->xpath->query("media:description", $content)->item(0);
|
||||||
|
if ($desc) {
|
||||||
|
$enc->title = strip_tags($desc->nodeValue);
|
||||||
|
} else {
|
||||||
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:thumbnail", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$enc->type = "image/generic";
|
||||||
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
|
||||||
return $encs;
|
return $encs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,13 +44,26 @@ abstract class FeedItem_Common extends FeedItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo
|
|
||||||
function get_comments_url() {
|
function get_comments_url() {
|
||||||
|
//RSS only. Use a query here to avoid namespace clashes (e.g. with slash).
|
||||||
|
//might give a wrong result if a default namespace was declared (possible with XPath 2.0)
|
||||||
|
$com_url = $this->xpath->query("comments", $this->elem)->item(0);
|
||||||
|
|
||||||
|
if($com_url)
|
||||||
|
return $com_url->nodeValue;
|
||||||
|
|
||||||
|
//Atom Threading Extension (RFC 4685) stuff. Could be used in RSS feeds, so it's in common.
|
||||||
|
//'text/html' for type is too restrictive?
|
||||||
|
$com_url = $this->xpath->query("atom:link[@rel='replies' and contains(@type,'text/html')]/@href", $this->elem)->item(0);
|
||||||
|
|
||||||
|
if($com_url)
|
||||||
|
return $com_url->nodeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_comments_count() {
|
function get_comments_count() {
|
||||||
$comments = $this->xpath->query("slash:comments", $this->elem)->item(0);
|
//also query for ATE stuff here
|
||||||
|
$query = "slash:comments|thread:total|atom:link[@rel='replies']/@thread:count";
|
||||||
|
$comments = $this->xpath->query($query, $this->elem)->item(0);
|
||||||
|
|
||||||
if ($comments) {
|
if ($comments) {
|
||||||
return $comments->nodeValue;
|
return $comments->nodeValue;
|
||||||
|
|
|
@ -33,20 +33,20 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
|| $link->getAttribute("rel") == "alternate"
|
|| $link->getAttribute("rel") == "alternate"
|
||||||
|| $link->getAttribute("rel") == "standout")) {
|
|| $link->getAttribute("rel") == "standout")) {
|
||||||
|
|
||||||
return $link->getAttribute("href");
|
return trim($link->getAttribute("href"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$link = $this->elem->getElementsByTagName("guid")->item(0);
|
$link = $this->elem->getElementsByTagName("guid")->item(0);
|
||||||
|
|
||||||
if ($link && $link->hasAttributes() && $link->getAttribute("isPermaLink") == "true") {
|
if ($link && $link->hasAttributes() && $link->getAttribute("isPermaLink") == "true") {
|
||||||
return $link->nodeValue;
|
return trim($link->nodeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
$link = $this->elem->getElementsByTagName("link")->item(0);
|
$link = $this->elem->getElementsByTagName("link")->item(0);
|
||||||
|
|
||||||
if ($link) {
|
if ($link) {
|
||||||
return $link->nodeValue;
|
return trim($link->nodeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,21 +54,26 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$title = $this->elem->getElementsByTagName("title")->item(0);
|
$title = $this->elem->getElementsByTagName("title")->item(0);
|
||||||
|
|
||||||
if ($title) {
|
if ($title) {
|
||||||
return $title->nodeValue;
|
return trim($title->nodeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_content() {
|
function get_content() {
|
||||||
$content = $this->xpath->query("content:encoded", $this->elem)->item(0);
|
$contentA = $this->xpath->query("content:encoded", $this->elem)->item(0);
|
||||||
|
$contentB = $this->elem->getElementsByTagName("description")->item(0);
|
||||||
|
|
||||||
if ($content) {
|
if ($contentA && !$contentB) {
|
||||||
return $content->nodeValue;
|
return $contentA->nodeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$content = $this->elem->getElementsByTagName("description")->item(0);
|
|
||||||
|
|
||||||
if ($content) {
|
if ($contentB && !$contentA) {
|
||||||
return $content->nodeValue;
|
return $contentB->nodeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contentA && $contentB) {
|
||||||
|
return mb_strlen($contentA->nodeValue) > mb_strlen($contentB->nodeValue) ?
|
||||||
|
$contentA->nodeValue : $contentB->nodeValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,13 +90,13 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$cats = array();
|
$cats = array();
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
array_push($cats, $cat->nodeValue);
|
array_push($cats, trim($cat->nodeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
$categories = $this->xpath->query("dc:subject", $this->elem);
|
$categories = $this->xpath->query("dc:subject", $this->elem);
|
||||||
|
|
||||||
foreach ($categories as $cat) {
|
foreach ($categories as $cat) {
|
||||||
array_push($cats, $cat->nodeValue);
|
array_push($cats, trim($cat->nodeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $cats;
|
return $cats;
|
||||||
|
@ -108,11 +113,13 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$enc->type = $enclosure->getAttribute("type");
|
$enc->type = $enclosure->getAttribute("type");
|
||||||
$enc->link = $enclosure->getAttribute("url");
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
$enc->length = $enclosure->getAttribute("length");
|
$enc->length = $enclosure->getAttribute("length");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
array_push($encs, $enc);
|
array_push($encs, $enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
$enclosures = $this->xpath->query("media:content | media:group/media:content", $this->elem);
|
$enclosures = $this->xpath->query("media:content", $this->elem);
|
||||||
|
|
||||||
foreach ($enclosures as $enclosure) {
|
foreach ($enclosures as $enclosure) {
|
||||||
$enc = new FeedEnclosure();
|
$enc = new FeedEnclosure();
|
||||||
|
@ -120,6 +127,8 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
$enc->type = $enclosure->getAttribute("type");
|
$enc->type = $enclosure->getAttribute("type");
|
||||||
$enc->link = $enclosure->getAttribute("url");
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
$enc->length = $enclosure->getAttribute("length");
|
$enc->length = $enclosure->getAttribute("length");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
@ -127,6 +136,46 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||||
array_push($encs, $enc);
|
array_push($encs, $enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:group", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$content = $this->xpath->query("media:content", $enclosure)->item(0);
|
||||||
|
|
||||||
|
if ($content) {
|
||||||
|
$enc->type = $content->getAttribute("type");
|
||||||
|
$enc->link = $content->getAttribute("url");
|
||||||
|
$enc->length = $content->getAttribute("length");
|
||||||
|
$enc->height = $content->getAttribute("height");
|
||||||
|
$enc->width = $content->getAttribute("width");
|
||||||
|
|
||||||
|
$desc = $this->xpath->query("media:description", $content)->item(0);
|
||||||
|
if ($desc) {
|
||||||
|
$enc->title = strip_tags($desc->nodeValue);
|
||||||
|
} else {
|
||||||
|
$desc = $this->xpath->query("media:description", $enclosure)->item(0);
|
||||||
|
if ($desc) $enc->title = strip_tags($desc->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$enclosures = $this->xpath->query("media:thumbnail", $this->elem);
|
||||||
|
|
||||||
|
foreach ($enclosures as $enclosure) {
|
||||||
|
$enc = new FeedEnclosure();
|
||||||
|
|
||||||
|
$enc->type = "image/generic";
|
||||||
|
$enc->link = $enclosure->getAttribute("url");
|
||||||
|
$enc->height = $enclosure->getAttribute("height");
|
||||||
|
$enc->width = $enclosure->getAttribute("width");
|
||||||
|
|
||||||
|
array_push($encs, $enc);
|
||||||
|
}
|
||||||
|
|
||||||
return $encs;
|
return $encs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
class FeedParser {
|
class FeedParser {
|
||||||
private $doc;
|
private $doc;
|
||||||
private $error;
|
private $error;
|
||||||
|
private $libxml_errors = array();
|
||||||
private $items;
|
private $items;
|
||||||
private $link;
|
private $link;
|
||||||
private $title;
|
private $title;
|
||||||
|
@ -12,6 +13,16 @@ class FeedParser {
|
||||||
const FEED_RSS = 1;
|
const FEED_RSS = 1;
|
||||||
const FEED_ATOM = 2;
|
const FEED_ATOM = 2;
|
||||||
|
|
||||||
|
function normalize_encoding($data) {
|
||||||
|
if (preg_match('/^(<\?xml[\t\n\r ].*?encoding[\t\n\r ]*=[\t\n\r ]*["\'])(.+?)(["\'].*?\?>)/s', $data, $matches) === 1) {
|
||||||
|
$data = mb_convert_encoding($data, 'UTF-8', $matches[2]);
|
||||||
|
|
||||||
|
$data = preg_replace('/^<\?xml[\t\n\r ].*?\?>/s', $matches[1] . "UTF-8" . $matches[3] , $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
function __construct($data) {
|
function __construct($data) {
|
||||||
libxml_use_internal_errors(true);
|
libxml_use_internal_errors(true);
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
@ -23,32 +34,8 @@ class FeedParser {
|
||||||
$error = libxml_get_last_error();
|
$error = libxml_get_last_error();
|
||||||
|
|
||||||
// libxml compiled without iconv?
|
// libxml compiled without iconv?
|
||||||
if ($error && ($error->code == 32 || $error->code == 9)) {
|
if ($error && $error->code == 32) {
|
||||||
if (preg_match('/^(<\?xml[\t\n\r ].*?encoding=["\'])(.+?)(["\'].*?\?>)/s', $data, $matches) === 1) {
|
$data = $this->normalize_encoding($data);
|
||||||
$enc = $matches[2];
|
|
||||||
|
|
||||||
$data = mb_convert_encoding($data, 'UTF-8', $enc);
|
|
||||||
|
|
||||||
$data = preg_replace('/^<\?xml[\t\n\r ].*?\?>/s', $matches[1] . "UTF-8" . $matches[3] , $data);
|
|
||||||
|
|
||||||
|
|
||||||
// apparently not all UTF-8 characters are valid for XML
|
|
||||||
$data = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $data);
|
|
||||||
|
|
||||||
if ($data) {
|
|
||||||
libxml_clear_errors();
|
|
||||||
|
|
||||||
$this->doc = new DOMDocument();
|
|
||||||
$this->doc->loadXML($data);
|
|
||||||
|
|
||||||
$error = libxml_get_last_error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// some terrible invalid unicode entity?
|
|
||||||
if ($error && $error->code == 9) {
|
|
||||||
$data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
|
|
||||||
|
|
||||||
if ($data) {
|
if ($data) {
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
@ -60,7 +47,41 @@ class FeedParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->error = $this->format_error($error);
|
// some terrible invalid unicode entity?
|
||||||
|
if ($error) {
|
||||||
|
foreach (libxml_get_errors() as $err) {
|
||||||
|
if ($err->code == 9) {
|
||||||
|
// if the source feed is not in utf8, next conversion will fail
|
||||||
|
$data = $this->normalize_encoding($data);
|
||||||
|
|
||||||
|
// remove dangling bytes
|
||||||
|
$data = mb_convert_encoding($data, 'UTF-8', 'UTF-8');
|
||||||
|
|
||||||
|
// apparently not all UTF-8 characters are valid for XML
|
||||||
|
$data = preg_replace('/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u', ' ', $data);
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
libxml_clear_errors();
|
||||||
|
|
||||||
|
$this->doc = new DOMDocument();
|
||||||
|
$this->doc->loadXML($data);
|
||||||
|
|
||||||
|
$error = libxml_get_last_error();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
foreach (libxml_get_errors() as $error) {
|
||||||
|
if ($error->level == LIBXML_ERR_FATAL) {
|
||||||
|
if(!isset($this->error)) //currently only the first error is reported
|
||||||
|
$this->error = $this->format_error($error);
|
||||||
|
$this->libxml_errors [] = $this->format_error($error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
libxml_clear_errors();
|
libxml_clear_errors();
|
||||||
|
|
||||||
$this->items = array();
|
$this->items = array();
|
||||||
|
@ -76,12 +97,13 @@ class FeedParser {
|
||||||
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
|
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
|
||||||
$xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
|
$xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
|
||||||
$xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/');
|
$xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/');
|
||||||
|
$xpath->registerNamespace('thread', 'http://purl.org/syndication/thread/1.0');
|
||||||
|
|
||||||
$this->xpath = $xpath;
|
$this->xpath = $xpath;
|
||||||
|
|
||||||
$root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)");
|
$root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)");
|
||||||
|
|
||||||
if ($root) {
|
if ($root && $root->length > 0) {
|
||||||
$root = $root->item(0);
|
$root = $root->item(0);
|
||||||
|
|
||||||
if ($root) {
|
if ($root) {
|
||||||
|
@ -183,6 +205,10 @@ class FeedParser {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->title) $this->title = trim($this->title);
|
||||||
|
if ($this->link) $this->link = trim($this->link);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if( !isset($this->error) ){
|
if( !isset($this->error) ){
|
||||||
$this->error = "Unknown/unsupported feed type";
|
$this->error = "Unknown/unsupported feed type";
|
||||||
|
@ -205,6 +231,10 @@ class FeedParser {
|
||||||
return $this->error;
|
return $this->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function errors() {
|
||||||
|
return $this->libxml_errors;
|
||||||
|
}
|
||||||
|
|
||||||
function get_link() {
|
function get_link() {
|
||||||
return $this->link;
|
return $this->link;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +256,7 @@ class FeedParser {
|
||||||
|
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
||||||
array_push($rv, $link->getAttribute('href'));
|
array_push($rv, trim($link->getAttribute('href')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -235,7 +265,7 @@ class FeedParser {
|
||||||
|
|
||||||
foreach ($links as $link) {
|
foreach ($links as $link) {
|
||||||
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
|
||||||
array_push($rv, $link->getAttribute('href'));
|
array_push($rv, trim($link->getAttribute('href')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -13,12 +13,6 @@ class Feeds extends Handler_Protected {
|
||||||
$feed_id, $is_cat, $search,
|
$feed_id, $is_cat, $search,
|
||||||
$search_mode, $view_mode, $error, $feed_last_updated) {
|
$search_mode, $view_mode, $error, $feed_last_updated) {
|
||||||
|
|
||||||
$page_prev_link = "viewFeedGoPage(-1)";
|
|
||||||
$page_next_link = "viewFeedGoPage(1)";
|
|
||||||
$page_first_link = "viewFeedGoPage(0)";
|
|
||||||
|
|
||||||
$catchup_page_link = "catchupPage()";
|
|
||||||
$catchup_feed_link = "catchupCurrentFeed()";
|
|
||||||
$catchup_sel_link = "catchupSelection()";
|
$catchup_sel_link = "catchupSelection()";
|
||||||
|
|
||||||
$archive_sel_link = "archiveSelection()";
|
$archive_sel_link = "archiveSelection()";
|
||||||
|
@ -43,6 +37,8 @@ class Feeds extends Handler_Protected {
|
||||||
$search_q = "";
|
$search_q = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$reply .= "<span class=\"holder\">";
|
||||||
|
|
||||||
$rss_link = htmlspecialchars(get_self_url_prefix() .
|
$rss_link = htmlspecialchars(get_self_url_prefix() .
|
||||||
"/public.php?op=rss&id=$feed_id$cat_q$search_q");
|
"/public.php?op=rss&id=$feed_id$cat_q$search_q");
|
||||||
|
|
||||||
|
@ -50,8 +46,14 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$error_class = $error ? "error" : "";
|
$error_class = $error ? "error" : "";
|
||||||
|
|
||||||
$reply .= "<span class='r'>";
|
$reply .= "<span class='r'>
|
||||||
$reply .= "<span id='selected_prompt'></span>";
|
<a href=\"#\"
|
||||||
|
title=\"".__("View as RSS feed")."\"
|
||||||
|
onclick=\"displayDlg('".__("View as RSS")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">
|
||||||
|
<img class=\"noborder\" src=\"images/pub_set.png\"></a>";
|
||||||
|
|
||||||
|
|
||||||
|
# $reply .= "<span>";
|
||||||
$reply .= "<span id='feed_title' class='$error_class'>";
|
$reply .= "<span id='feed_title' class='$error_class'>";
|
||||||
|
|
||||||
if ($feed_site_url) {
|
if ($feed_site_url) {
|
||||||
|
@ -60,11 +62,11 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$target = "target=\"_blank\"";
|
$target = "target=\"_blank\"";
|
||||||
$reply .= "<a title=\"$last_updated\" $target href=\"$feed_site_url\">".
|
$reply .= "<a title=\"$last_updated\" $target href=\"$feed_site_url\">".
|
||||||
truncate_string($feed_title,30)."</a>";
|
truncate_string($feed_title, 30)."</a>";
|
||||||
|
|
||||||
if ($error) {
|
if ($error) {
|
||||||
$error = htmlspecialchars($error);
|
$error = htmlspecialchars($error);
|
||||||
$reply .= " <img title=\"$error\" src='images/error.png' alt='error' class=\"noborder\" style=\"vertical-align : middle\">";
|
$reply .= " <img title=\"$error\" src='images/error.png' alt='error' class=\"noborder\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,17 +75,16 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply .= "</span>";
|
$reply .= "</span>";
|
||||||
|
|
||||||
$reply .= "
|
|
||||||
<a href=\"#\"
|
|
||||||
title=\"".__("View as RSS feed")."\"
|
|
||||||
onclick=\"displayDlg('".__("View as RSS")."','generatedFeed', '$feed_id:$is_cat:$rss_link')\">
|
|
||||||
<img class=\"noborder\" style=\"vertical-align : middle\" src=\"images/pub_set.png\"></a>";
|
|
||||||
|
|
||||||
$reply .= "</span>";
|
$reply .= "</span>";
|
||||||
|
|
||||||
|
# $reply .= "</span>";
|
||||||
|
|
||||||
// left part
|
// left part
|
||||||
|
|
||||||
$reply .= __('Select:')."
|
$reply .= "<span class=\"main\">";
|
||||||
|
$reply .= "<span id='selected_prompt'></span>";
|
||||||
|
|
||||||
|
$reply .= "
|
||||||
<a href=\"#\" onclick=\"$sel_all_link\">".__('All')."</a>,
|
<a href=\"#\" onclick=\"$sel_all_link\">".__('All')."</a>,
|
||||||
<a href=\"#\" onclick=\"$sel_unread_link\">".__('Unread')."</a>,
|
<a href=\"#\" onclick=\"$sel_unread_link\">".__('Unread')."</a>,
|
||||||
<a href=\"#\" onclick=\"$sel_inv_link\">".__('Invert')."</a>,
|
<a href=\"#\" onclick=\"$sel_inv_link\">".__('Invert')."</a>,
|
||||||
|
@ -132,14 +133,14 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply .= "</select>";
|
$reply .= "</select>";
|
||||||
|
|
||||||
//$reply .= "</div>";
|
|
||||||
|
|
||||||
//$reply .= "</h2";
|
//$reply .= "</h2";
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON) as $p) {
|
||||||
echo $p->hook_headline_toolbar_button($feed_id, $is_cat);
|
$reply .= $p->hook_headline_toolbar_button($feed_id, $is_cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$reply .= "</span></span>";
|
||||||
|
|
||||||
return $reply;
|
return $reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ class Feeds extends Handler_Protected {
|
||||||
$override_order = false, $include_children = false) {
|
$override_order = false, $include_children = false) {
|
||||||
|
|
||||||
if (isset($_REQUEST["DevForceUpdate"]))
|
if (isset($_REQUEST["DevForceUpdate"]))
|
||||||
header("Content-Type: text/plain");
|
header("Content-Type: text/plain; charset=utf-8");
|
||||||
|
|
||||||
$disable_cache = false;
|
$disable_cache = false;
|
||||||
|
|
||||||
|
@ -247,6 +248,8 @@ class Feeds extends Handler_Protected {
|
||||||
false, 0, $include_children);
|
false, 0, $include_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$vfeed_group_enabled = get_pref("VFEED_GROUP_BY_FEED") && $feed != -6;
|
||||||
|
|
||||||
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H1", $timing_info);
|
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H1", $timing_info);
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
|
@ -278,6 +281,12 @@ class Feeds extends Handler_Protected {
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
if ($offset == 0) {
|
||||||
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_HEADLINES_BEFORE) as $p) {
|
||||||
|
$reply['content'] .= $p->hook_headlines_before($feed, $cat_view, $qfh_ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) > 0) {
|
if ($this->dbh->num_rows($result) > 0) {
|
||||||
|
|
||||||
$lnum = $offset;
|
$lnum = $offset;
|
||||||
|
@ -285,14 +294,12 @@ class Feeds extends Handler_Protected {
|
||||||
$num_unread = 0;
|
$num_unread = 0;
|
||||||
$cur_feed_title = '';
|
$cur_feed_title = '';
|
||||||
|
|
||||||
$fresh_intl = get_pref("FRESH_ARTICLE_MAX_AGE") * 60 * 60;
|
|
||||||
|
|
||||||
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info);
|
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info);
|
||||||
|
|
||||||
$expand_cdm = get_pref('CDM_EXPANDED');
|
$expand_cdm = get_pref('CDM_EXPANDED');
|
||||||
|
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
$line["content_preview"] = "— " . truncate_string(strip_tags($line["content_preview"]), 250);
|
$line["content_preview"] = "— " . truncate_string(strip_tags($line["content"]), 250);
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line, 250, false);
|
$line = $p->hook_query_headlines($line, 250, false);
|
||||||
|
@ -422,7 +429,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
if (!get_pref('COMBINED_DISPLAY_MODE')) {
|
if (!get_pref('COMBINED_DISPLAY_MODE')) {
|
||||||
|
|
||||||
if (get_pref('VFEED_GROUP_BY_FEED')) {
|
if ($vfeed_group_enabled) {
|
||||||
if ($feed_id != $vgroup_last_feed && $line["feed_title"]) {
|
if ($feed_id != $vgroup_last_feed && $line["feed_title"]) {
|
||||||
|
|
||||||
$cur_feed_title = $line["feed_title"];
|
$cur_feed_title = $line["feed_title"];
|
||||||
|
@ -430,12 +437,12 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
||||||
|
|
||||||
$vf_catchup_link = "(<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('Mark as read')."</a>)";
|
$vf_catchup_link = "<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||||
|
|
||||||
$reply['content'] .= "<div class='cdmFeedTitle'>".
|
$reply['content'] .= "<div id='FTITLE-$feed_id' class='cdmFeedTitle'>".
|
||||||
"<div style=\"float : right\">$feed_icon_img</div>".
|
"<div style='float : right'>$feed_icon_img</div>".
|
||||||
"<a class='title' href=\"#\" onclick=\"viewfeed($feed_id)\">".
|
"<a class='title' href=\"#\" onclick=\"viewfeed($feed_id)\">". $line["feed_title"]."</a>
|
||||||
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
$vf_catchup_link</div>";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,7 +450,7 @@ class Feeds extends Handler_Protected {
|
||||||
$mouseover_attrs = "onmouseover='postMouseIn(event, $id)'
|
$mouseover_attrs = "onmouseover='postMouseIn(event, $id)'
|
||||||
onmouseout='postMouseOut($id)'";
|
onmouseout='postMouseOut($id)'";
|
||||||
|
|
||||||
$reply['content'] .= "<div class='hl $class' id='RROW-$id' $mouseover_attrs>";
|
$reply['content'] .= "<div class='hl $class' orig-feed-id='$feed_id' id='RROW-$id' $mouseover_attrs>";
|
||||||
|
|
||||||
$reply['content'] .= "<div class='hlLeft'>";
|
$reply['content'] .= "<div class='hlLeft'>";
|
||||||
|
|
||||||
|
@ -473,17 +480,18 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
$reply['content'] .= "<span class=\"hlUpdated\">";
|
if (!$vfeed_group_enabled) {
|
||||||
|
|
||||||
if (!get_pref('VFEED_GROUP_BY_FEED')) {
|
|
||||||
if (@$line["feed_title"]) {
|
if (@$line["feed_title"]) {
|
||||||
$rgba = @$rgba_cache[$feed_id];
|
$rgba = @$rgba_cache[$feed_id];
|
||||||
|
|
||||||
$reply['content'] .= "<a class=\"hlFeed\" style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"viewfeed($feed_id)\">".
|
$reply['content'] .= "<span class=\"hlFeed\"><a style=\"background : rgba($rgba, 0.3)\" href=\"#\" onclick=\"viewfeed($feed_id)\">".
|
||||||
truncate_string($line["feed_title"],30)."</a>";
|
truncate_string($line["feed_title"],30)."</a></span>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$reply['content'] .= "<span class=\"hlUpdated\">";
|
||||||
|
|
||||||
$reply['content'] .= "<div title='$date_entered_fmt'>$updated_fmt</div>
|
$reply['content'] .= "<div title='$date_entered_fmt'>$updated_fmt</div>
|
||||||
</span>";
|
</span>";
|
||||||
|
|
||||||
|
@ -491,12 +499,12 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply['content'] .= $score_pic;
|
$reply['content'] .= $score_pic;
|
||||||
|
|
||||||
if ($line["feed_title"] && !get_pref('VFEED_GROUP_BY_FEED')) {
|
if ($line["feed_title"] && !$vfeed_group_enabled) {
|
||||||
|
|
||||||
$reply['content'] .= "<span onclick=\"viewfeed($feed_id)\"
|
$reply['content'] .= "<span onclick=\"viewfeed($feed_id)\"
|
||||||
style=\"cursor : pointer\"
|
style=\"cursor : pointer\"
|
||||||
title=\"".htmlspecialchars($line['feed_title'])."\">
|
title=\"".htmlspecialchars($line['feed_title'])."\">
|
||||||
$feed_icon_img<span>";
|
$feed_icon_img</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
@ -516,7 +524,7 @@ class Feeds extends Handler_Protected {
|
||||||
$line = $p->hook_render_article_cdm($line);
|
$line = $p->hook_render_article_cdm($line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_pref('VFEED_GROUP_BY_FEED') && $line["feed_title"]) {
|
if ($vfeed_group_enabled && $line["feed_title"]) {
|
||||||
if ($feed_id != $vgroup_last_feed) {
|
if ($feed_id != $vgroup_last_feed) {
|
||||||
|
|
||||||
$cur_feed_title = $line["feed_title"];
|
$cur_feed_title = $line["feed_title"];
|
||||||
|
@ -524,7 +532,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
$cur_feed_title = htmlspecialchars($cur_feed_title);
|
||||||
|
|
||||||
$vf_catchup_link = "(<a class='catchup' onclick='javascript:catchupFeedInGroup($feed_id);' href='#'>".__('mark as read')."</a>)";
|
$vf_catchup_link = "<a class='catchup' onclick='catchupFeedInGroup($feed_id);' href='#'>".__('mark feed as read')."</a>";
|
||||||
|
|
||||||
$has_feed_icon = feed_has_icon($feed_id);
|
$has_feed_icon = feed_has_icon($feed_id);
|
||||||
|
|
||||||
|
@ -534,7 +542,7 @@ class Feeds extends Handler_Protected {
|
||||||
//$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\" alt=\"\">";
|
//$feed_icon_img = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\" alt=\"\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
$reply['content'] .= "<div class='cdmFeedTitle'>".
|
$reply['content'] .= "<div id='FTITLE-$feed_id' class='cdmFeedTitle'>".
|
||||||
"<div style=\"float : right\">$feed_icon_img</div>".
|
"<div style=\"float : right\">$feed_icon_img</div>".
|
||||||
"<a href=\"#\" class='title' onclick=\"viewfeed($feed_id)\">".
|
"<a href=\"#\" class='title' onclick=\"viewfeed($feed_id)\">".
|
||||||
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
$line["feed_title"]."</a> $vf_catchup_link</div>";
|
||||||
|
@ -547,9 +555,9 @@ class Feeds extends Handler_Protected {
|
||||||
$expanded_class = $expand_cdm ? "expanded" : "expandable";
|
$expanded_class = $expand_cdm ? "expanded" : "expandable";
|
||||||
|
|
||||||
$reply['content'] .= "<div class=\"cdm $hlc_suffix $expanded_class $class\"
|
$reply['content'] .= "<div class=\"cdm $hlc_suffix $expanded_class $class\"
|
||||||
id=\"RROW-$id\" $mouseover_attrs>";
|
id=\"RROW-$id\" orig-feed-id='$feed_id' $mouseover_attrs>";
|
||||||
|
|
||||||
$reply['content'] .= "<div class=\"cdmHeader\" style=\"$row_background\">";
|
$reply['content'] .= "<div class=\"cdmHeader\">";
|
||||||
$reply['content'] .= "<div style=\"vertical-align : middle\">";
|
$reply['content'] .= "<div style=\"vertical-align : middle\">";
|
||||||
|
|
||||||
$reply['content'] .= "<input dojoType=\"dijit.form.CheckBox\"
|
$reply['content'] .= "<input dojoType=\"dijit.form.CheckBox\"
|
||||||
|
@ -592,7 +600,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
$reply['content'] .= "</span>";
|
$reply['content'] .= "</span>";
|
||||||
|
|
||||||
if (!get_pref('VFEED_GROUP_BY_FEED')) {
|
if (!$vfeed_group_enabled) {
|
||||||
if (@$line["feed_title"]) {
|
if (@$line["feed_title"]) {
|
||||||
$rgba = @$rgba_cache[$feed_id];
|
$rgba = @$rgba_cache[$feed_id];
|
||||||
|
|
||||||
|
@ -725,7 +733,7 @@ class Feeds extends Handler_Protected {
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
$reply['content'] .= "</div><hr/>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
$reply['content'] .= "</div>";
|
$reply['content'] .= "</div>";
|
||||||
|
|
||||||
|
@ -803,8 +811,6 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info);
|
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info);
|
||||||
|
|
||||||
$omode = $this->dbh->escape_string($_REQUEST["omode"]);
|
|
||||||
|
|
||||||
$feed = $this->dbh->escape_string($_REQUEST["feed"]);
|
$feed = $this->dbh->escape_string($_REQUEST["feed"]);
|
||||||
$method = $this->dbh->escape_string($_REQUEST["m"]);
|
$method = $this->dbh->escape_string($_REQUEST["m"]);
|
||||||
$view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]);
|
$view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]);
|
||||||
|
@ -897,7 +903,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
//$topmost_article_ids = $ret[0];
|
//$topmost_article_ids = $ret[0];
|
||||||
$headlines_count = $ret[1];
|
$headlines_count = $ret[1];
|
||||||
$returned_feed = $ret[2];
|
/* $returned_feed = $ret[2]; */
|
||||||
$disable_cache = $ret[3];
|
$disable_cache = $ret[3];
|
||||||
$vgroup_last_feed = $ret[4];
|
$vgroup_last_feed = $ret[4];
|
||||||
|
|
||||||
|
@ -978,6 +984,10 @@ class Feeds extends Handler_Protected {
|
||||||
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
|
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"rpc\">";
|
||||||
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"addfeed\">";
|
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"addfeed\">";
|
||||||
|
|
||||||
|
print "<div id='fadd_multiple_notify' style='display : none'>";
|
||||||
|
print_notice("Provided URL is a HTML page referencing multiple feeds, please select required feed from the dropdown menu below.");
|
||||||
|
print "<p></div>";
|
||||||
|
|
||||||
print "<div class=\"dlgSec\">".__("Feed or site URL")."</div>";
|
print "<div class=\"dlgSec\">".__("Feed or site URL")."</div>";
|
||||||
print "<div class=\"dlgSecCont\">";
|
print "<div class=\"dlgSecCont\">";
|
||||||
|
|
||||||
|
@ -1073,20 +1083,18 @@ class Feeds extends Handler_Protected {
|
||||||
print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">";
|
print " <select dojoType=\"dijit.form.Select\" name=\"limit\" onchange=\"dijit.byId('feedBrowserDlg').update()\">";
|
||||||
|
|
||||||
foreach (array(25, 50, 100, 200) as $l) {
|
foreach (array(25, 50, 100, 200) as $l) {
|
||||||
$issel = ($l == $limit) ? "selected=\"1\"" : "";
|
//$issel = ($l == $limit) ? "selected=\"1\"" : "";
|
||||||
print "<option $issel value=\"$l\">$l</option>";
|
print "<option value=\"$l\">$l</option>";
|
||||||
}
|
}
|
||||||
|
|
||||||
print "</select> ";
|
print "</select> ";
|
||||||
|
|
||||||
print "</div>";
|
print "</div>";
|
||||||
|
|
||||||
$owner_uid = $_SESSION["uid"];
|
|
||||||
|
|
||||||
require_once "feedbrowser.php";
|
require_once "feedbrowser.php";
|
||||||
|
|
||||||
print "<ul class='browseFeedList' id='browseFeedList'>";
|
print "<ul class='browseFeedList' id='browseFeedList'>";
|
||||||
print make_feed_browser($search, 25);
|
print make_feed_browser("", 25);
|
||||||
print "</ul>";
|
print "</ul>";
|
||||||
|
|
||||||
print "<div align='center'>
|
print "<div align='center'>
|
||||||
|
@ -1145,7 +1153,7 @@ class Feeds extends Handler_Protected {
|
||||||
|
|
||||||
print "<div class=\"dlgButtons\">";
|
print "<div class=\"dlgButtons\">";
|
||||||
|
|
||||||
if (!SPHINX_ENABLED) {
|
if (count(PluginHost::getInstance()->get_hooks(PluginHost::HOOK_SEARCH)) == 0) {
|
||||||
print "<div style=\"float : left\">
|
print "<div style=\"float : left\">
|
||||||
<a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/wiki/SearchSyntax\">".__("Search syntax")."</a>
|
<a class=\"visibleLink\" target=\"_blank\" href=\"http://tt-rss.org/wiki/SearchSyntax\">".__("Search syntax")."</a>
|
||||||
</div>";
|
</div>";
|
||||||
|
|
|
@ -3,7 +3,7 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
|
private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
|
||||||
$limit, $offset, $search, $search_mode,
|
$limit, $offset, $search, $search_mode,
|
||||||
$view_mode = false, $format = 'atom', $order = false, $orig_guid = false) {
|
$view_mode = false, $format = 'atom', $order = false, $orig_guid = false, $start_ts = false) {
|
||||||
|
|
||||||
require_once "lib/MiniTemplator.class.php";
|
require_once "lib/MiniTemplator.class.php";
|
||||||
|
|
||||||
|
@ -15,11 +15,15 @@ class Handler_Public extends Handler {
|
||||||
if (!$limit) $limit = 60;
|
if (!$limit) $limit = 60;
|
||||||
|
|
||||||
$date_sort_field = "date_entered DESC, updated DESC";
|
$date_sort_field = "date_entered DESC, updated DESC";
|
||||||
|
$date_check_field = "date_entered";
|
||||||
|
|
||||||
if ($feed == -2)
|
if ($feed == -2 && !$is_cat) {
|
||||||
$date_sort_field = "last_published DESC";
|
$date_sort_field = "last_published DESC";
|
||||||
else if ($feed == -1)
|
$date_check_field = "last_published";
|
||||||
|
} else if ($feed == -1 && !$is_cat) {
|
||||||
$date_sort_field = "last_marked DESC";
|
$date_sort_field = "last_marked DESC";
|
||||||
|
$date_check_field = "last_marked";
|
||||||
|
}
|
||||||
|
|
||||||
switch ($order) {
|
switch ($order) {
|
||||||
case "title":
|
case "title":
|
||||||
|
@ -33,15 +37,18 @@ class Handler_Public extends Handler {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//function queryFeedHeadlines($feed, $limit, $view_mode, $cat_view, $search, $search_mode, $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0, $include_children = false, $ignore_vfeed_group = false, $override_strategy = false, $override_vfeed = false, $start_ts = false) {
|
||||||
|
|
||||||
$qfh_ret = queryFeedHeadlines($feed,
|
$qfh_ret = queryFeedHeadlines($feed,
|
||||||
1, $view_mode, $is_cat, $search, $search_mode,
|
1, $view_mode, $is_cat, $search, $search_mode,
|
||||||
$date_sort_field, $offset, $owner_uid,
|
$date_sort_field, $offset, $owner_uid,
|
||||||
false, 0, false, true);
|
false, 0, true, true, false, false, $start_ts);
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) != 0) {
|
if ($this->dbh->num_rows($result) != 0) {
|
||||||
$ts = strtotime($this->dbh->fetch_result($result, 0, "date_entered"));
|
|
||||||
|
$ts = strtotime($this->dbh->fetch_result($result, 0, $date_check_field));
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
||||||
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $ts) {
|
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $ts) {
|
||||||
|
@ -56,13 +63,13 @@ class Handler_Public extends Handler {
|
||||||
$qfh_ret = queryFeedHeadlines($feed,
|
$qfh_ret = queryFeedHeadlines($feed,
|
||||||
$limit, $view_mode, $is_cat, $search, $search_mode,
|
$limit, $view_mode, $is_cat, $search, $search_mode,
|
||||||
$date_sort_field, $offset, $owner_uid,
|
$date_sort_field, $offset, $owner_uid,
|
||||||
false, 0, false, true);
|
false, 0, true, true, false, false, $start_ts);
|
||||||
|
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
$feed_title = htmlspecialchars($qfh_ret[1]);
|
$feed_title = htmlspecialchars($qfh_ret[1]);
|
||||||
$feed_site_url = $qfh_ret[2];
|
$feed_site_url = $qfh_ret[2];
|
||||||
$last_error = $qfh_ret[3];
|
/* $last_error = $qfh_ret[3]; */
|
||||||
|
|
||||||
$feed_self_url = get_self_url_prefix() .
|
$feed_self_url = get_self_url_prefix() .
|
||||||
"/public.php?op=rss&id=$feed&key=" .
|
"/public.php?op=rss&id=$feed&key=" .
|
||||||
|
@ -86,7 +93,7 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
$tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
|
$tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
$line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100, '...');
|
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100, '...');
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line);
|
$line = $p->hook_query_headlines($line);
|
||||||
|
@ -100,7 +107,8 @@ class Handler_Public extends Handler {
|
||||||
$tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
|
$tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
|
||||||
$tpl->setVariable('ARTICLE_EXCERPT', $line["content_preview"], true);
|
$tpl->setVariable('ARTICLE_EXCERPT', $line["content_preview"], true);
|
||||||
|
|
||||||
$content = sanitize($line["content"], false, $owner_uid);
|
$content = sanitize($line["content"], false, $owner_uid,
|
||||||
|
$feed_site_url);
|
||||||
|
|
||||||
if ($line['note']) {
|
if ($line['note']) {
|
||||||
$content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
|
$content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
|
||||||
|
@ -118,7 +126,7 @@ class Handler_Public extends Handler {
|
||||||
$tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
|
$tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
|
||||||
|
|
||||||
$tpl->setVariable('ARTICLE_SOURCE_LINK', htmlspecialchars($line['site_url']), true);
|
$tpl->setVariable('ARTICLE_SOURCE_LINK', htmlspecialchars($line['site_url']), true);
|
||||||
$tpl->setVariable('ARTICLE_SOURCE_TITLE', htmlspecialchars($line['feed_title']), true);
|
$tpl->setVariable('ARTICLE_SOURCE_TITLE', htmlspecialchars($line['feed_title'] ? $line['feed_title'] : $feed_title), true);
|
||||||
|
|
||||||
$tags = get_article_tags($line["id"], $owner_uid);
|
$tags = get_article_tags($line["id"], $owner_uid);
|
||||||
|
|
||||||
|
@ -269,16 +277,22 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
function pubsub() {
|
function pubsub() {
|
||||||
$mode = $this->dbh->escape_string($_REQUEST['hub_mode']);
|
$mode = $this->dbh->escape_string($_REQUEST['hub_mode']);
|
||||||
|
if (!$mode) $mode = $this->dbh->escape_string($_REQUEST['hub.mode']);
|
||||||
|
|
||||||
$feed_id = (int) $this->dbh->escape_string($_REQUEST['id']);
|
$feed_id = (int) $this->dbh->escape_string($_REQUEST['id']);
|
||||||
$feed_url = $this->dbh->escape_string($_REQUEST['hub_topic']);
|
$feed_url = $this->dbh->escape_string($_REQUEST['hub_topic']);
|
||||||
|
|
||||||
|
if (!$feed_url) $feed_url = $this->dbh->escape_string($_REQUEST['hub.topic']);
|
||||||
|
|
||||||
if (!PUBSUBHUBBUB_ENABLED) {
|
if (!PUBSUBHUBBUB_ENABLED) {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
echo "404 Not found";
|
echo "404 Not found (Disabled by server)";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement hub_verifytoken checking
|
// TODO: implement hub_verifytoken checking
|
||||||
|
// TODO: store requested rel=self or whatever for verification
|
||||||
|
// (may be different from stored feed url) e.g. http://url/ or http://url
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT feed_url FROM ttrss_feeds
|
$result = $this->dbh->query("SELECT feed_url FROM ttrss_feeds
|
||||||
WHERE id = '$feed_id'");
|
WHERE id = '$feed_id'");
|
||||||
|
@ -287,7 +301,8 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
$check_feed_url = $this->dbh->fetch_result($result, 0, "feed_url");
|
$check_feed_url = $this->dbh->fetch_result($result, 0, "feed_url");
|
||||||
|
|
||||||
if ($check_feed_url && ($check_feed_url == $feed_url || !$feed_url)) {
|
// ignore url checking for the time being
|
||||||
|
if ($check_feed_url && (true || $check_feed_url == $feed_url || !$feed_url)) {
|
||||||
if ($mode == "subscribe") {
|
if ($mode == "subscribe") {
|
||||||
|
|
||||||
$this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 2
|
$this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 2
|
||||||
|
@ -316,11 +331,11 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
echo "404 Not found";
|
echo "404 Not found (URL check failed)";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.0 404 Not Found');
|
header('HTTP/1.0 404 Not Found');
|
||||||
echo "404 Not found";
|
echo "404 Not found (Feed not found)";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -363,9 +378,10 @@ class Handler_Public extends Handler {
|
||||||
$search_mode = $this->dbh->escape_string($_REQUEST["smode"]);
|
$search_mode = $this->dbh->escape_string($_REQUEST["smode"]);
|
||||||
$view_mode = $this->dbh->escape_string($_REQUEST["view-mode"]);
|
$view_mode = $this->dbh->escape_string($_REQUEST["view-mode"]);
|
||||||
$order = $this->dbh->escape_string($_REQUEST["order"]);
|
$order = $this->dbh->escape_string($_REQUEST["order"]);
|
||||||
|
$start_ts = $this->dbh->escape_string($_REQUEST["ts"]);
|
||||||
|
|
||||||
$format = $this->dbh->escape_string($_REQUEST['format']);
|
$format = $this->dbh->escape_string($_REQUEST['format']);
|
||||||
$orig_guid = !sql_bool_to_bool($_REQUEST["no_orig_guid"]);
|
$orig_guid = sql_bool_to_bool($_REQUEST["orig_guid"]);
|
||||||
|
|
||||||
if (!$format) $format = 'atom';
|
if (!$format) $format = 'atom';
|
||||||
|
|
||||||
|
@ -385,24 +401,24 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
if ($owner_id) {
|
if ($owner_id) {
|
||||||
$this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
|
$this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
|
||||||
$offset, $search, $search_mode, $view_mode, $format, $order, $orig_guid);
|
$offset, $search, $search_mode, $view_mode, $format, $order, $orig_guid, $start_ts);
|
||||||
} else {
|
} else {
|
||||||
header('HTTP/1.1 403 Forbidden');
|
header('HTTP/1.1 403 Forbidden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTask() {
|
function updateTask() {
|
||||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
|
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function housekeepingTask() {
|
function housekeepingTask() {
|
||||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_HOUSE_KEEPING, "hook_house_keeping", $op);
|
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_HOUSE_KEEPING, "hook_house_keeping", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalUpdateFeeds() {
|
function globalUpdateFeeds() {
|
||||||
RPC::updaterandomfeed_real($this->dbh);
|
RPC::updaterandomfeed_real($this->dbh);
|
||||||
|
|
||||||
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
|
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sharepopup() {
|
function sharepopup() {
|
||||||
|
@ -411,11 +427,14 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
print "<html><head><title>Tiny Tiny RSS</title>";
|
print "<html><head><title>Tiny Tiny RSS</title>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
|
||||||
|
|
||||||
stylesheet_tag("css/utility.css");
|
echo stylesheet_tag("css/utility.css");
|
||||||
javascript_tag("lib/prototype.js");
|
echo stylesheet_tag("css/dijit.css");
|
||||||
javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls");
|
echo javascript_tag("lib/prototype.js");
|
||||||
|
echo javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,controls");
|
||||||
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||||
</head><body id='sharepopup'>";
|
</head><body id='sharepopup'>";
|
||||||
|
|
||||||
|
@ -561,7 +580,7 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$_SESSION["login_error_msg"] = __("Incorrect username or password");
|
$_SESSION["login_error_msg"] = __("Incorrect username or password");
|
||||||
user_error("Failed login attempt from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
|
user_error("Failed login attempt for $login from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_REQUEST['return']) {
|
if ($_REQUEST['return']) {
|
||||||
|
@ -572,6 +591,18 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* function subtest() {
|
||||||
|
header("Content-type: text/plain; charset=utf-8");
|
||||||
|
|
||||||
|
$url = $_REQUEST["url"];
|
||||||
|
|
||||||
|
print "$url\n\n";
|
||||||
|
|
||||||
|
|
||||||
|
print_r(get_feeds_from_html($url, fetch_file_contents($url)));
|
||||||
|
|
||||||
|
} */
|
||||||
|
|
||||||
function subscribe() {
|
function subscribe() {
|
||||||
if (SINGLE_USER_MODE) {
|
if (SINGLE_USER_MODE) {
|
||||||
login_sequence();
|
login_sequence();
|
||||||
|
@ -587,6 +618,9 @@ class Handler_Public extends Handler {
|
||||||
<title>Tiny Tiny RSS</title>
|
<title>Tiny Tiny RSS</title>
|
||||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"css/utility.css\">
|
<link rel=\"stylesheet\" type=\"text/css\" href=\"css/utility.css\">
|
||||||
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<img class=\"floatingLogo\" src=\"images/logo_small.png\"
|
<img class=\"floatingLogo\" src=\"images/logo_small.png\"
|
||||||
|
@ -671,93 +705,6 @@ class Handler_Public extends Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function subscribe2() {
|
|
||||||
$feed_url = $this->dbh->escape_string(trim($_REQUEST["feed_url"]));
|
|
||||||
$cat_id = $this->dbh->escape_string($_REQUEST["cat_id"]);
|
|
||||||
$from = $this->dbh->escape_string($_REQUEST["from"]);
|
|
||||||
$feed_urls = array();
|
|
||||||
|
|
||||||
/* only read authentication information from POST */
|
|
||||||
|
|
||||||
$auth_login = $this->dbh->escape_string(trim($_POST["auth_login"]));
|
|
||||||
$auth_pass = $this->dbh->escape_string(trim($_POST["auth_pass"]));
|
|
||||||
|
|
||||||
$rc = subscribe_to_feed($feed_url, $cat_id, $auth_login, $auth_pass);
|
|
||||||
|
|
||||||
switch ($rc) {
|
|
||||||
case 1:
|
|
||||||
print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
print_notice(__("Multiple feed URLs found."));
|
|
||||||
$contents = @fetch_file_contents($url, false, $auth_login, $auth_pass);
|
|
||||||
if (is_html($contents)) {
|
|
||||||
$feed_urls = get_feeds_from_html($url, $contents);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($feed_urls) {
|
|
||||||
print "<form action=\"backend.php\">";
|
|
||||||
print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
|
|
||||||
print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
|
|
||||||
print "<input type=\"hidden\" name=\"method\" value=\"add\">";
|
|
||||||
|
|
||||||
print "<select name=\"feed_url\">";
|
|
||||||
|
|
||||||
foreach ($feed_urls as $url => $name) {
|
|
||||||
$url = htmlspecialchars($url);
|
|
||||||
$name = htmlspecialchars($name);
|
|
||||||
print "<option value=\"$url\">$name</option>";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<input type=\"submit\" value=\"".__("Subscribe to selected feed")."\">";
|
|
||||||
print "</form>";
|
|
||||||
}
|
|
||||||
|
|
||||||
$tp_uri = get_self_url_prefix() . "/prefs.php";
|
|
||||||
$tt_uri = get_self_url_prefix();
|
|
||||||
|
|
||||||
if ($rc <= 2){
|
|
||||||
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
|
|
||||||
feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
|
|
||||||
|
|
||||||
$feed_id = $this->dbh->fetch_result($result, 0, "id");
|
|
||||||
} else {
|
|
||||||
$feed_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<p>";
|
|
||||||
|
|
||||||
if ($feed_id) {
|
|
||||||
print "<form method=\"GET\" style='display: inline'
|
|
||||||
action=\"$tp_uri\">
|
|
||||||
<input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
|
|
||||||
<input type=\"hidden\" name=\"method\" value=\"editFeed\">
|
|
||||||
<input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
|
|
||||||
<input type=\"submit\" value=\"".__("Edit subscription options")."\">
|
|
||||||
</form>";
|
|
||||||
}
|
|
||||||
|
|
||||||
print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
|
|
||||||
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
|
||||||
</form></p>";
|
|
||||||
|
|
||||||
print "</body></html>";
|
|
||||||
}
|
|
||||||
|
|
||||||
function index() {
|
function index() {
|
||||||
header("Content-Type: text/plain");
|
header("Content-Type: text/plain");
|
||||||
print json_encode(array("error" => array("code" => 7)));
|
print json_encode(array("error" => array("code" => 7)));
|
||||||
|
@ -766,11 +713,15 @@ class Handler_Public extends Handler {
|
||||||
function forgotpass() {
|
function forgotpass() {
|
||||||
startup_gettext();
|
startup_gettext();
|
||||||
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
@$hash = $_REQUEST["hash"];
|
||||||
print "<html><head><title>Tiny Tiny RSS</title>";
|
|
||||||
|
|
||||||
stylesheet_tag("css/utility.css");
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
javascript_tag("lib/prototype.js");
|
print "<html><head><title>Tiny Tiny RSS</title>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
|
||||||
|
|
||||||
|
echo stylesheet_tag("css/utility.css");
|
||||||
|
echo javascript_tag("lib/prototype.js");
|
||||||
|
|
||||||
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||||
</head><body id='forgotpass'>";
|
</head><body id='forgotpass'>";
|
||||||
|
@ -781,8 +732,45 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
@$method = $_POST['method'];
|
@$method = $_POST['method'];
|
||||||
|
|
||||||
if (!$method) {
|
if ($hash) {
|
||||||
print_notice(__("You will need to provide valid account name and email. New password will be sent on your email address."));
|
$login = $_REQUEST["login"];
|
||||||
|
|
||||||
|
if ($login) {
|
||||||
|
$result = $this->dbh->query("SELECT id, resetpass_token FROM ttrss_users
|
||||||
|
WHERE login = '$login'");
|
||||||
|
|
||||||
|
if ($this->dbh->num_rows($result) != 0) {
|
||||||
|
$id = $this->dbh->fetch_result($result, 0, "id");
|
||||||
|
$resetpass_token_full = $this->dbh->fetch_result($result, 0, "resetpass_token");
|
||||||
|
list($timestamp, $resetpass_token) = explode(":", $resetpass_token_full);
|
||||||
|
|
||||||
|
if ($timestamp && $resetpass_token &&
|
||||||
|
$timestamp >= time() - 15*60*60 &&
|
||||||
|
$resetpass_token == $hash) {
|
||||||
|
|
||||||
|
$result = $this->dbh->query("UPDATE ttrss_users SET resetpass_token = NULL
|
||||||
|
WHERE id = $id");
|
||||||
|
|
||||||
|
Pref_Users::resetUserPassword($id, true);
|
||||||
|
|
||||||
|
print "<p>"."Completed."."</p>";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print_error("Some of the information provided is missing or incorrect.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_error("Some of the information provided is missing or incorrect.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_error("Some of the information provided is missing or incorrect.");
|
||||||
|
}
|
||||||
|
|
||||||
|
print "<form method=\"GET\" action=\"index.php\">
|
||||||
|
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
||||||
|
</form>";
|
||||||
|
|
||||||
|
} else if (!$method) {
|
||||||
|
print_notice(__("You will need to provide valid account name and email. A password reset link will be sent to your email address."));
|
||||||
|
|
||||||
print "<form method='POST' action='public.php'>";
|
print "<form method='POST' action='public.php'>";
|
||||||
print "<input type='hidden' name='method' value='do'>";
|
print "<input type='hidden' name='method' value='do'>";
|
||||||
|
@ -823,17 +811,57 @@ class Handler_Public extends Handler {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
print_notice("Password reset instructions are being sent to your email address.");
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT id FROM ttrss_users
|
$result = $this->dbh->query("SELECT id FROM ttrss_users
|
||||||
WHERE login = '$login' AND email = '$email'");
|
WHERE login = '$login' AND email = '$email'");
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) != 0) {
|
if ($this->dbh->num_rows($result) != 0) {
|
||||||
$id = $this->dbh->fetch_result($result, 0, "id");
|
$id = $this->dbh->fetch_result($result, 0, "id");
|
||||||
|
|
||||||
Pref_Users::resetUserPassword($id, false);
|
if ($id) {
|
||||||
|
$resetpass_token = sha1(get_random_bytes(128));
|
||||||
|
$resetpass_link = get_self_url_prefix() . "/public.php?op=forgotpass&hash=" . $resetpass_token .
|
||||||
|
"&login=" . urlencode($login);
|
||||||
|
|
||||||
print "<p>";
|
require_once 'classes/ttrssmailer.php';
|
||||||
|
require_once "lib/MiniTemplator.class.php";
|
||||||
|
|
||||||
print "<p>"."Completed."."</p>";
|
$tpl = new MiniTemplator;
|
||||||
|
|
||||||
|
$tpl->readTemplateFromFile("templates/resetpass_link_template.txt");
|
||||||
|
|
||||||
|
$tpl->setVariable('LOGIN', $login);
|
||||||
|
$tpl->setVariable('RESETPASS_LINK', $resetpass_link);
|
||||||
|
|
||||||
|
$tpl->addBlock('message');
|
||||||
|
|
||||||
|
$message = "";
|
||||||
|
|
||||||
|
$tpl->generateOutputToString($message);
|
||||||
|
|
||||||
|
$mail = new ttrssMailer();
|
||||||
|
|
||||||
|
$rc = $mail->quickMail($email, $login,
|
||||||
|
__("[tt-rss] Password reset request"),
|
||||||
|
$message, false);
|
||||||
|
|
||||||
|
if (!$rc) print_error($mail->ErrorInfo);
|
||||||
|
|
||||||
|
$resetpass_token_full = $this->dbh->escape_string(time() . ":" . $resetpass_token);
|
||||||
|
|
||||||
|
$result = $this->dbh->query("UPDATE ttrss_users
|
||||||
|
SET resetpass_token = '$resetpass_token_full'
|
||||||
|
WHERE login = '$login' AND email = '$email'");
|
||||||
|
|
||||||
|
//Pref_Users::resetUserPassword($id, false);
|
||||||
|
|
||||||
|
print "<p>";
|
||||||
|
|
||||||
|
print "<p>"."Completed."."</p>";
|
||||||
|
} else {
|
||||||
|
print_error("User ID not found.");
|
||||||
|
}
|
||||||
|
|
||||||
print "<form method=\"GET\" action=\"index.php\">
|
print "<form method=\"GET\" action=\"index.php\">
|
||||||
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
|
||||||
|
@ -872,6 +900,8 @@ class Handler_Public extends Handler {
|
||||||
<title>Database Updater</title>
|
<title>Database Updater</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<link rel="stylesheet" type="text/css" href="css/utility.css"/>
|
<link rel="stylesheet" type="text/css" href="css/utility.css"/>
|
||||||
|
<link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
|
||||||
|
<link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">
|
||||||
</head>
|
</head>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
span.ok { color : #009000; font-weight : bold; }
|
span.ok { color : #009000; font-weight : bold; }
|
||||||
|
|
|
@ -257,8 +257,8 @@ class Opml extends Handler_Protected {
|
||||||
$feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('text')->nodeValue, 0, 250));
|
$feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('text')->nodeValue, 0, 250));
|
||||||
if (!$feed_title) $feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('title')->nodeValue, 0, 250));
|
if (!$feed_title) $feed_title = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('title')->nodeValue, 0, 250));
|
||||||
|
|
||||||
$feed_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('xmlUrl')->nodeValue, 0, 250));
|
$feed_url = $this->dbh->escape_string($attrs->getNamedItem('xmlUrl')->nodeValue);
|
||||||
if (!$feed_url) $feed_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('xmlURL')->nodeValue, 0, 250));
|
if (!$feed_url) $feed_url = $this->dbh->escape_string($attrs->getNamedItem('xmlURL')->nodeValue);
|
||||||
|
|
||||||
$site_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('htmlUrl')->nodeValue, 0, 250));
|
$site_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('htmlUrl')->nodeValue, 0, 250));
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,10 @@ class PluginHost {
|
||||||
const HOOK_FETCH_FEED = 22;
|
const HOOK_FETCH_FEED = 22;
|
||||||
const HOOK_QUERY_HEADLINES = 23;
|
const HOOK_QUERY_HEADLINES = 23;
|
||||||
const HOOK_HOUSE_KEEPING = 24;
|
const HOOK_HOUSE_KEEPING = 24;
|
||||||
|
const HOOK_SEARCH = 25;
|
||||||
|
const HOOK_FORMAT_ENCLOSURES = 26;
|
||||||
|
const HOOK_SUBSCRIBE_FEED = 27;
|
||||||
|
const HOOK_HEADLINES_BEFORE = 28;
|
||||||
|
|
||||||
const KIND_ALL = 1;
|
const KIND_ALL = 1;
|
||||||
const KIND_SYSTEM = 2;
|
const KIND_SYSTEM = 2;
|
||||||
|
@ -75,6 +79,16 @@ class PluginHost {
|
||||||
return $this->dbh;
|
return $this->dbh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_plugin_names() {
|
||||||
|
$names = array();
|
||||||
|
|
||||||
|
foreach ($this->plugins as $p) {
|
||||||
|
array_push($names, get_class($p));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
|
||||||
function get_plugins() {
|
function get_plugins() {
|
||||||
return $this->plugins;
|
return $this->plugins;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +113,7 @@ class PluginHost {
|
||||||
|
|
||||||
function del_hook($type, $sender) {
|
function del_hook($type, $sender) {
|
||||||
if (is_array($this->hooks[$type])) {
|
if (is_array($this->hooks[$type])) {
|
||||||
$key = array_Search($this->hooks[$type], $sender);
|
$key = array_Search($sender, $this->hooks[$type]);
|
||||||
if ($key !== FALSE) {
|
if ($key !== FALSE) {
|
||||||
unset($this->hooks[$type][$key]);
|
unset($this->hooks[$type][$key]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$cat['unread'] = 0;
|
$cat['unread'] = 0;
|
||||||
$cat['child_unread'] = 0;
|
$cat['child_unread'] = 0;
|
||||||
$cat['auxcounter'] = 0;
|
$cat['auxcounter'] = 0;
|
||||||
|
$cat['parent_id'] = $cat_id;
|
||||||
|
|
||||||
$cat['items'] = $this->get_category_items($line['id']);
|
$cat['items'] = $this->get_category_items($line['id']);
|
||||||
|
|
||||||
|
@ -395,7 +396,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
# print_r($data['items']);
|
# print_r($data['items']);
|
||||||
|
|
||||||
if (is_array($data) && is_array($data['items'])) {
|
if (is_array($data) && is_array($data['items'])) {
|
||||||
$cat_order_id = 0;
|
# $cat_order_id = 0;
|
||||||
|
|
||||||
$data_map = array();
|
$data_map = array();
|
||||||
$root_item = false;
|
$root_item = false;
|
||||||
|
@ -494,7 +495,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
|
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
|
||||||
|
|
||||||
if (is_file($icon_file) && $feed_id) {
|
if (is_file($icon_file) && $feed_id) {
|
||||||
if (filesize($icon_file) < 20000) {
|
if (filesize($icon_file) < 65535) {
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT id FROM ttrss_feeds
|
$result = $this->dbh->query("SELECT id FROM ttrss_feeds
|
||||||
WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
|
WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
|
||||||
|
@ -737,9 +738,9 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
|
<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
|
||||||
<input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
|
<input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
|
||||||
<input type=\"hidden\" name=\"method\" value=\"uploadicon\">
|
<input type=\"hidden\" name=\"method\" value=\"uploadicon\">
|
||||||
<button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
|
<button class=\"small\" dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
|
||||||
type=\"submit\">".__('Replace')."</button>
|
type=\"submit\">".__('Replace')."</button>
|
||||||
<button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
|
<button class=\"small\" dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
|
||||||
type=\"submit\">".__('Remove')."</button>
|
type=\"submit\">".__('Remove')."</button>
|
||||||
</form>";
|
</form>";
|
||||||
|
|
||||||
|
@ -962,7 +963,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
|
|
||||||
if (!$batch) {
|
if (!$batch) {
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_feeds SET
|
$this->dbh->query("UPDATE ttrss_feeds SET
|
||||||
$category_qpart
|
$category_qpart
|
||||||
title = '$feed_title', feed_url = '$feed_link',
|
title = '$feed_title', feed_url = '$feed_link',
|
||||||
update_interval = '$upd_intl',
|
update_interval = '$upd_intl',
|
||||||
|
@ -1259,13 +1260,18 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
$interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
|
$interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->dbh->query("SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
|
// could be performance-intensive and prevent feeds pref-panel from showing
|
||||||
|
if (!defined('_DISABLE_INACTIVE_FEEDS') || !_DISABLE_INACTIVE_FEEDS) {
|
||||||
|
$result = $this->dbh->query("SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
|
||||||
(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
|
(SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
|
||||||
ttrss_entries.id = ref_id AND
|
ttrss_entries.id = ref_id AND
|
||||||
ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
|
ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
|
||||||
ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
|
ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
|
||||||
|
|
||||||
$num_inactive = $this->dbh->fetch_result($result, 0, "num_inactive");
|
$num_inactive = $this->dbh->fetch_result($result, 0, "num_inactive");
|
||||||
|
} else {
|
||||||
|
$num_inactive = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ($num_inactive > 0) {
|
if ($num_inactive > 0) {
|
||||||
$inactive_button = "<button dojoType=\"dijit.form.Button\"
|
$inactive_button = "<button dojoType=\"dijit.form.Button\"
|
||||||
|
@ -1573,8 +1579,6 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
# class needed for selectTableRows()
|
# class needed for selectTableRows()
|
||||||
print "<tr class=\"placeholder\" $this_row_id>";
|
print "<tr class=\"placeholder\" $this_row_id>";
|
||||||
|
|
||||||
$edit_title = htmlspecialchars($line["title"]);
|
|
||||||
|
|
||||||
# id needed for selectTableRows()
|
# id needed for selectTableRows()
|
||||||
print "<td width='5%' align='center'><input
|
print "<td width='5%' align='center'><input
|
||||||
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
||||||
|
@ -1639,8 +1643,6 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
# class needed for selectTableRows()
|
# class needed for selectTableRows()
|
||||||
print "<tr class=\"placeholder\" $this_row_id>";
|
print "<tr class=\"placeholder\" $this_row_id>";
|
||||||
|
|
||||||
$edit_title = htmlspecialchars($line["title"]);
|
|
||||||
|
|
||||||
# id needed for selectTableRows()
|
# id needed for selectTableRows()
|
||||||
print "<td width='5%' align='center'><input
|
print "<td width='5%' align='center'><input
|
||||||
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
|
||||||
|
@ -1891,7 +1893,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||||
AND owner_uid = " . $owner_uid);
|
AND owner_uid = " . $owner_uid);
|
||||||
|
|
||||||
if ($this->dbh->num_rows($result) == 1) {
|
if ($this->dbh->num_rows($result) == 1) {
|
||||||
$key = $this->dbh->escape_string(sha1(uniqid(rand(), true)));
|
$key = $this->dbh->escape_string(uniqid(base_convert(rand(), 10, 36)));
|
||||||
|
|
||||||
$this->dbh->query("UPDATE ttrss_access_keys SET access_key = '$key'
|
$this->dbh->query("UPDATE ttrss_access_keys SET access_key = '$key'
|
||||||
WHERE feed_id = '$feed_id' AND is_cat = $sql_is_cat
|
WHERE feed_id = '$feed_id' AND is_cat = $sql_is_cat
|
||||||
|
|
|
@ -88,7 +88,6 @@ class Pref_Filters extends Handler_Protected {
|
||||||
|
|
||||||
$result = $qfh_ret[0];
|
$result = $qfh_ret[0];
|
||||||
|
|
||||||
$articles = array();
|
|
||||||
$found = 0;
|
$found = 0;
|
||||||
|
|
||||||
print __("Articles matching this filter:");
|
print __("Articles matching this filter:");
|
||||||
|
@ -97,15 +96,12 @@ class Pref_Filters extends Handler_Protected {
|
||||||
print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
|
print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
|
||||||
|
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
$line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100, '...');
|
$line["content_preview"] = truncate_string(strip_tags($line["content"]), 100, '...');
|
||||||
|
|
||||||
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
|
||||||
$line = $p->hook_query_headlines($line, 100);
|
$line = $p->hook_query_headlines($line, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_timestamp = strtotime($line["updated"]);
|
|
||||||
$entry_tags = get_article_tags($line["id"], $_SESSION["uid"]);
|
|
||||||
|
|
||||||
$content_preview = $line["content_preview"];
|
$content_preview = $line["content_preview"];
|
||||||
|
|
||||||
if ($line["feed_title"])
|
if ($line["feed_title"])
|
||||||
|
@ -151,6 +147,40 @@ class Pref_Filters extends Handler_Protected {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getfilterrules_concise($filter_id) {
|
||||||
|
$result = $this->dbh->query("SELECT reg_exp,
|
||||||
|
inverse,
|
||||||
|
feed_id,
|
||||||
|
cat_id,
|
||||||
|
cat_filter,
|
||||||
|
ttrss_filter_types.description AS field
|
||||||
|
FROM
|
||||||
|
ttrss_filters2_rules, ttrss_filter_types
|
||||||
|
WHERE
|
||||||
|
filter_id = '$filter_id' AND filter_type = ttrss_filter_types.id");
|
||||||
|
|
||||||
|
$rv = "";
|
||||||
|
|
||||||
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
|
|
||||||
|
$where = sql_bool_to_bool($line["cat_filter"]) ?
|
||||||
|
getCategoryTitle($line["cat_id"]) :
|
||||||
|
($line["feed_id"] ?
|
||||||
|
getFeedTitle($line["feed_id"]) : __("All feeds"));
|
||||||
|
|
||||||
|
# $where = $line["cat_id"] . "/" . $line["feed_id"];
|
||||||
|
|
||||||
|
$inverse = sql_bool_to_bool($line["inverse"]) ? "inverse" : "";
|
||||||
|
|
||||||
|
$rv .= "<span class='$inverse'>" . T_sprintf("%s on %s in %s %s",
|
||||||
|
strip_tags($line["reg_exp"]),
|
||||||
|
$line["field"],
|
||||||
|
$where,
|
||||||
|
sql_bool_to_bool($line["inverse"]) ? __("(inverse)") : "") . "</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rv;
|
||||||
|
}
|
||||||
|
|
||||||
function getfiltertree() {
|
function getfiltertree() {
|
||||||
$root = array();
|
$root = array();
|
||||||
|
@ -174,24 +204,11 @@ class Pref_Filters extends Handler_Protected {
|
||||||
owner_uid = ".$_SESSION["uid"]." ORDER BY order_id, title");
|
owner_uid = ".$_SESSION["uid"]." ORDER BY order_id, title");
|
||||||
|
|
||||||
|
|
||||||
$action_id = -1;
|
|
||||||
$folder = array();
|
$folder = array();
|
||||||
$folder['items'] = array();
|
$folder['items'] = array();
|
||||||
|
|
||||||
while ($line = $this->dbh->fetch_assoc($result)) {
|
while ($line = $this->dbh->fetch_assoc($result)) {
|
||||||
|
|
||||||
/* if ($action_id != $line["action_id"]) {
|
|
||||||
if (count($folder['items']) > 0) {
|
|
||||||
array_push($root['items'], $folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
$folder = array();
|
|
||||||
$folder['id'] = $line["action_id"];
|
|
||||||
$folder['name'] = __($line["action_name"]);
|
|
||||||
$folder['items'] = array();
|
|
||||||
$action_id = $line["action_id"];
|
|
||||||
} */
|
|
||||||
|
|
||||||
$name = $this->getFilterName($line["id"]);
|
$name = $this->getFilterName($line["id"]);
|
||||||
|
|
||||||
$match_ok = false;
|
$match_ok = false;
|
||||||
|
@ -227,6 +244,7 @@ class Pref_Filters extends Handler_Protected {
|
||||||
$filter['param'] = $name[1];
|
$filter['param'] = $name[1];
|
||||||
$filter['checkbox'] = false;
|
$filter['checkbox'] = false;
|
||||||
$filter['enabled'] = sql_bool_to_bool($line["enabled"]);
|
$filter['enabled'] = sql_bool_to_bool($line["enabled"]);
|
||||||
|
$filter['rules'] = $this->getfilterrules_concise($line['id']);
|
||||||
|
|
||||||
if (!$filter_search || $match_ok) {
|
if (!$filter_search || $match_ok) {
|
||||||
array_push($folder['items'], $filter);
|
array_push($folder['items'], $filter);
|
||||||
|
@ -433,8 +451,11 @@ class Pref_Filters extends Handler_Protected {
|
||||||
WHERE id = ".(int)$rule["filter_type"]);
|
WHERE id = ".(int)$rule["filter_type"]);
|
||||||
$filter_type = $this->dbh->fetch_result($result, 0, "description");
|
$filter_type = $this->dbh->fetch_result($result, 0, "description");
|
||||||
|
|
||||||
return T_sprintf("%s on %s in %s %s", strip_tags($rule["reg_exp"]),
|
$inverse = isset($rule["inverse"]) ? "inverse" : "";
|
||||||
$filter_type, $feed, isset($rule["inverse"]) ? __("(inverse)") : "");
|
|
||||||
|
return "<span class='filterRule $inverse'>" .
|
||||||
|
T_sprintf("%s on %s in %s %s", strip_tags($rule["reg_exp"]),
|
||||||
|
$filter_type, $feed, isset($rule["inverse"]) ? __("(inverse)") : "") . "</span>";
|
||||||
}
|
}
|
||||||
|
|
||||||
function printRuleName() {
|
function printRuleName() {
|
||||||
|
@ -471,7 +492,7 @@ class Pref_Filters extends Handler_Protected {
|
||||||
$inverse = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["inverse"]));
|
$inverse = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["inverse"]));
|
||||||
$title = $this->dbh->escape_string($_REQUEST["title"]);
|
$title = $this->dbh->escape_string($_REQUEST["title"]);
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_filters2 SET enabled = $enabled,
|
$this->dbh->query("UPDATE ttrss_filters2 SET enabled = $enabled,
|
||||||
match_any_rule = $match_any_rule,
|
match_any_rule = $match_any_rule,
|
||||||
inverse = $inverse,
|
inverse = $inverse,
|
||||||
title = '$title'
|
title = '$title'
|
||||||
|
|
|
@ -181,7 +181,8 @@ class Pref_Prefs extends Handler_Protected {
|
||||||
global $access_level_names;
|
global $access_level_names;
|
||||||
|
|
||||||
$prefs_blacklist = array("STRIP_UNSAFE_TAGS", "REVERSE_HEADLINES",
|
$prefs_blacklist = array("STRIP_UNSAFE_TAGS", "REVERSE_HEADLINES",
|
||||||
"SORT_HEADLINES_BY_FEED_DATE", "DEFAULT_ARTICLE_LIMIT");
|
"SORT_HEADLINES_BY_FEED_DATE", "DEFAULT_ARTICLE_LIMIT",
|
||||||
|
"FEEDS_SORT_BY_UNREAD");
|
||||||
|
|
||||||
/* "FEEDS_SORT_BY_UNREAD", "HIDE_READ_FEEDS", "REVERSE_HEADLINES" */
|
/* "FEEDS_SORT_BY_UNREAD", "HIDE_READ_FEEDS", "REVERSE_HEADLINES" */
|
||||||
|
|
||||||
|
@ -887,8 +888,9 @@ class Pref_Prefs extends Handler_Protected {
|
||||||
|
|
||||||
if (!$otp_enabled) {
|
if (!$otp_enabled) {
|
||||||
$secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt")));
|
$secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt")));
|
||||||
$topt = new \OTPHP\TOTP($secret);
|
print QRcode::png("otpauth://totp/".urlencode($login).
|
||||||
print QRcode::png($topt->provisioning_uri($login));
|
"?secret=$secret&issuer=".urlencode("Tiny Tiny RSS"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -258,7 +258,7 @@ class Pref_Users extends Handler_Protected {
|
||||||
|
|
||||||
$pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
|
$pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
|
||||||
|
|
||||||
db_query("UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt'
|
db_query("UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt', otp_enabled = false
|
||||||
WHERE id = '$uid'");
|
WHERE id = '$uid'");
|
||||||
|
|
||||||
if ($show_password) {
|
if ($show_password) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ class RPC extends Handler_Protected {
|
||||||
WHERE orig_feed_id = '$id') = 0 AND
|
WHERE orig_feed_id = '$id') = 0 AND
|
||||||
id = '$id' AND owner_uid = ".$_SESSION["uid"]);
|
id = '$id' AND owner_uid = ".$_SESSION["uid"]);
|
||||||
|
|
||||||
$rc = $this->dbh->affected_rows($result);
|
$this->dbh->affected_rows($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ class RPC extends Handler_Protected {
|
||||||
$mark = "false";
|
$mark = "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_user_entries SET marked = $mark,
|
$this->dbh->query("UPDATE ttrss_user_entries SET marked = $mark,
|
||||||
last_marked = NOW()
|
last_marked = NOW()
|
||||||
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ class RPC extends Handler_Protected {
|
||||||
function delete() {
|
function delete() {
|
||||||
$ids = $this->dbh->escape_string($_REQUEST["ids"]);
|
$ids = $this->dbh->escape_string($_REQUEST["ids"]);
|
||||||
|
|
||||||
$result = $this->dbh->query("DELETE FROM ttrss_user_entries
|
$this->dbh->query("DELETE FROM ttrss_user_entries
|
||||||
WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
|
WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
|
||||||
purge_orphans();
|
purge_orphans();
|
||||||
|
|
||||||
|
@ -258,7 +258,6 @@ class RPC extends Handler_Protected {
|
||||||
function publ() {
|
function publ() {
|
||||||
$pub = $_REQUEST["pub"];
|
$pub = $_REQUEST["pub"];
|
||||||
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
$id = $this->dbh->escape_string($_REQUEST["id"]);
|
||||||
$note = trim(strip_tags($this->dbh->escape_string($_REQUEST["note"])));
|
|
||||||
|
|
||||||
if ($pub == "1") {
|
if ($pub == "1") {
|
||||||
$pub = "true";
|
$pub = "true";
|
||||||
|
@ -266,7 +265,7 @@ class RPC extends Handler_Protected {
|
||||||
$pub = "false";
|
$pub = "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->dbh->query("UPDATE ttrss_user_entries SET
|
$this->dbh->query("UPDATE ttrss_user_entries SET
|
||||||
published = $pub, last_published = NOW()
|
published = $pub, last_published = NOW()
|
||||||
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
|
||||||
|
|
||||||
|
@ -620,7 +619,7 @@ class RPC extends Handler_Protected {
|
||||||
|
|
||||||
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
||||||
|
|
||||||
$pubsub_result = $p->publish_update($rss_link);
|
/* $pubsub_result = */ $p->publish_update($rss_link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,64 +1,64 @@
|
||||||
<?php
|
<?php
|
||||||
/* @class ttrssMailer
|
/* @class ttrssMailer
|
||||||
* @brief A TTRSS extension to the PHPMailer class
|
* @brief A TTRSS extension to the PHPMailer class
|
||||||
* Configures default values through the __construct() function
|
* Configures default values through the __construct() function
|
||||||
* @author Derek Murawsky
|
* @author Derek Murawsky
|
||||||
* @version .1 (alpha)
|
* @version .1 (alpha)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
require_once 'lib/phpmailer/class.phpmailer.php';
|
require_once 'lib/phpmailer/class.phpmailer.php';
|
||||||
require_once "config.php";
|
require_once "config.php";
|
||||||
|
|
||||||
class ttrssMailer extends PHPMailer {
|
class ttrssMailer extends PHPMailer {
|
||||||
|
|
||||||
//define all items that we want to override with defaults in PHPMailer
|
//define all items that we want to override with defaults in PHPMailer
|
||||||
public $From = SMTP_FROM_ADDRESS;
|
public $From = SMTP_FROM_ADDRESS;
|
||||||
public $FromName = SMTP_FROM_NAME;
|
public $FromName = SMTP_FROM_NAME;
|
||||||
public $CharSet = "UTF-8";
|
public $CharSet = "UTF-8";
|
||||||
public $PluginDir = "lib/phpmailer/";
|
public $PluginDir = "lib/phpmailer/";
|
||||||
public $ContentType = "text/html"; //default email type is HTML
|
public $ContentType = "text/html"; //default email type is HTML
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
$this->SetLanguage("en", "lib/phpmailer/language/");
|
$this->SetLanguage("en", "lib/phpmailer/language/");
|
||||||
|
|
||||||
if (SMTP_SERVER) {
|
if (SMTP_SERVER) {
|
||||||
$pair = explode(":", SMTP_SERVER, 2);
|
$pair = explode(":", SMTP_SERVER, 2);
|
||||||
$this->Mailer = "smtp";
|
$this->Mailer = "smtp";
|
||||||
|
|
||||||
$this->Host = $pair[0];
|
$this->Host = $pair[0];
|
||||||
$this->Port = $pair[1];
|
$this->Port = $pair[1];
|
||||||
|
|
||||||
if (!$this->Port) $this->Port = 25;
|
if (!$this->Port) $this->Port = 25;
|
||||||
} else {
|
} else {
|
||||||
$this->Host = '';
|
$this->Host = '';
|
||||||
$this->Port = '';
|
$this->Port = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//if SMTP_LOGIN is specified, set credentials and enable auth
|
//if SMTP_LOGIN is specified, set credentials and enable auth
|
||||||
if(SMTP_LOGIN){
|
if(SMTP_LOGIN){
|
||||||
$this->SMTPAuth = true;
|
$this->SMTPAuth = true;
|
||||||
$this->Username = SMTP_LOGIN;
|
$this->Username = SMTP_LOGIN;
|
||||||
$this->Password = SMTP_PASSWORD;
|
$this->Password = SMTP_PASSWORD;
|
||||||
}
|
}
|
||||||
if(SMTP_SECURE)
|
if(SMTP_SECURE)
|
||||||
$this->SMTPSecure = SMTP_SECURE;
|
$this->SMTPSecure = SMTP_SECURE;
|
||||||
}
|
}
|
||||||
/* @brief a simple mail function to send email using the defaults
|
/* @brief a simple mail function to send email using the defaults
|
||||||
* This will send an HTML email using the configured defaults
|
* This will send an HTML email using the configured defaults
|
||||||
* @param $toAddress A string with the recipients email address
|
* @param $toAddress A string with the recipients email address
|
||||||
* @param $toName A string with the recipients name
|
* @param $toName A string with the recipients name
|
||||||
* @param $subject A string with the emails subject
|
* @param $subject A string with the emails subject
|
||||||
* @param $body A string containing the body of the email
|
* @param $body A string containing the body of the email
|
||||||
*/
|
*/
|
||||||
public function quickMail ($toAddress, $toName, $subject, $body, $altbody=""){
|
public function quickMail ($toAddress, $toName, $subject, $body, $altbody=""){
|
||||||
$this->addAddress($toAddress, $toName);
|
$this->addAddress($toAddress, $toName);
|
||||||
$this->Subject = $subject;
|
$this->Subject = $subject;
|
||||||
$this->Body = $body;
|
$this->Body = $body;
|
||||||
$this->IsHTML($altbody != '');
|
$this->IsHTML($altbody != '');
|
||||||
$rc=$this->send();
|
$rc=$this->send();
|
||||||
return $rc;
|
return $rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -104,13 +104,9 @@
|
||||||
// Enable client PubSubHubbub support in tt-rss. When disabled, tt-rss
|
// Enable client PubSubHubbub support in tt-rss. When disabled, tt-rss
|
||||||
// won't try to subscribe to PUSH feed updates.
|
// won't try to subscribe to PUSH feed updates.
|
||||||
|
|
||||||
// *********************
|
// ****************************
|
||||||
// *** Sphinx search ***
|
// *** Sphinx search plugin ***
|
||||||
// *********************
|
// ****************************
|
||||||
|
|
||||||
define('SPHINX_ENABLED', false);
|
|
||||||
// Enable fulltext search using Sphinx (http://www.sphinxsearch.com)
|
|
||||||
// Please see http://tt-rss.org/wiki/SphinxSearch for more information.
|
|
||||||
|
|
||||||
define('SPHINX_SERVER', 'localhost:9312');
|
define('SPHINX_SERVER', 'localhost:9312');
|
||||||
// Hostname:port combination for the Sphinx server.
|
// Hostname:port combination for the Sphinx server.
|
||||||
|
@ -184,6 +180,12 @@
|
||||||
define('CHECK_FOR_NEW_VERSION', true);
|
define('CHECK_FOR_NEW_VERSION', true);
|
||||||
// Check for new versions of tt-rss automatically.
|
// Check for new versions of tt-rss automatically.
|
||||||
|
|
||||||
|
define('DETECT_ARTICLE_LANGUAGE', false);
|
||||||
|
// Detect article language when updating feeds, presently this is only
|
||||||
|
// used for hyphenation. This may increase amount of CPU time used by
|
||||||
|
// update processes, disable if necessary (i.e. you are being billed
|
||||||
|
// for CPU time).
|
||||||
|
|
||||||
define('ENABLE_GZIP_OUTPUT', false);
|
define('ENABLE_GZIP_OUTPUT', false);
|
||||||
// Selectively gzip output to improve wire performance. This requires
|
// Selectively gzip output to improve wire performance. This requires
|
||||||
// PHP Zlib extension on the server.
|
// PHP Zlib extension on the server.
|
||||||
|
@ -211,4 +213,3 @@
|
||||||
// if necessary (after migrating all new options from this file).
|
// if necessary (after migrating all new options from this file).
|
||||||
|
|
||||||
// vim:ft=php
|
// vim:ft=php
|
||||||
?>
|
|
||||||
|
|
|
@ -52,7 +52,8 @@ div.cdmHeader input {
|
||||||
|
|
||||||
div.cdmContentInner {
|
div.cdmContentInner {
|
||||||
margin : 10px;
|
margin : 10px;
|
||||||
line-height : 20px;
|
line-height : 1.5;
|
||||||
|
font-size : 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdmContentInner img {
|
div.cdmContentInner img {
|
||||||
|
@ -61,6 +62,16 @@ div.cdmContentInner img {
|
||||||
height : auto;
|
height : auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdmContentInner h1 {
|
||||||
|
font-size : 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmContentInner h2,
|
||||||
|
div.cdmContentInner h3,
|
||||||
|
div.cdmContentInner h4 {
|
||||||
|
font-size : 15px;
|
||||||
|
}
|
||||||
|
|
||||||
div.cdmFooter {
|
div.cdmFooter {
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
|
@ -68,15 +79,25 @@ div.cdmFooter {
|
||||||
clear : both;
|
clear : both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdm {
|
||||||
|
margin-right : 4px;
|
||||||
|
}
|
||||||
|
|
||||||
div.cdm.expanded {
|
div.cdm.expanded {
|
||||||
margin-top : 4px;
|
margin-top : 4px;
|
||||||
margin-bottom : 4px;
|
margin-bottom : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdm.expanded div.cdmFooter {
|
||||||
|
border-style : solid;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
div.cdm.expandable {
|
div.cdm.expandable {
|
||||||
background-color : #f0f0f0;
|
background-color : #f0f0f0;
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +119,6 @@ div.cdm.expandable.Selected {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expandable.active {
|
div.cdm.expandable.active {
|
||||||
box-shadow : inset 0px 0px 3px 0px rgba(0,0,0,0.1);
|
|
||||||
border-color : #88b0f0;
|
|
||||||
background : white ! important;
|
background : white ! important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +134,15 @@ div.cdm.expandable.active div.cdmHeader span.titleWrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expandable div.cdmHeader a.title {
|
div.cdm.expandable div.cdmHeader a.title {
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
color : #555;
|
color : #555;
|
||||||
|
font-size : 14px;
|
||||||
-webkit-transition : color 0.2s;
|
-webkit-transition : color 0.2s;
|
||||||
transition : color 0.2s;
|
transition : color 0.2s;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expandable.Unread div.cdmHeader a.title {
|
div.cdm.expandable.Unread div.cdmHeader a.title {
|
||||||
|
@ -127,6 +151,12 @@ div.cdm.expandable.Unread div.cdmHeader a.title {
|
||||||
|
|
||||||
div.cdm.expandable.active div.cdmHeader a.title {
|
div.cdm.expandable.active div.cdmHeader a.title {
|
||||||
color : #4684ff;
|
color : #4684ff;
|
||||||
|
font-size : 16px;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expanded div.cdmHeader {
|
div.cdm.expanded div.cdmHeader {
|
||||||
|
@ -134,11 +164,15 @@ div.cdm.expanded div.cdmHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expanded div.cdmHeader a.title {
|
div.cdm.expanded div.cdmHeader a.title {
|
||||||
font-size : 14px;
|
font-size : 16px;
|
||||||
color : #999;
|
color : #999;
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
-webkit-transition : color 0.2s;
|
-webkit-transition : color 0.2s;
|
||||||
transition : color 0.2s;
|
transition : color 0.2s;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.cdm.expanded.active {
|
div.cdm.expanded.active {
|
||||||
|
@ -167,7 +201,7 @@ div.cdm.active div.cdmContent {
|
||||||
|
|
||||||
span.cdmExcerpt {
|
span.cdmExcerpt {
|
||||||
font-size : 11px;
|
font-size : 11px;
|
||||||
color : #555;
|
color : #999;
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +256,6 @@ div.cdm .hlFeed a {
|
||||||
|
|
||||||
div.cdmContentInner p {
|
div.cdmContentInner p {
|
||||||
max-width : 650px;
|
max-width : 650px;
|
||||||
text-align : justify;
|
|
||||||
-webkit-hyphens: auto;
|
-webkit-hyphens: auto;
|
||||||
-moz-hyphens: auto;
|
-moz-hyphens: auto;
|
||||||
hyphens: auto;
|
hyphens: auto;
|
||||||
|
@ -242,15 +275,15 @@ div.cdmHeader span.author {
|
||||||
div#floatingTitle {
|
div#floatingTitle {
|
||||||
position : absolute;
|
position : absolute;
|
||||||
z-index : 5;
|
z-index : 5;
|
||||||
top : 25px;
|
top : 0px;
|
||||||
right : 0px;
|
right : 0px;
|
||||||
left : 0px;
|
left : 0px;
|
||||||
border-color : #ccc;
|
border-color : #ddd;
|
||||||
border-width : 1px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
background : #fcfcfc;
|
background : white;
|
||||||
color : #555;
|
color : #555;
|
||||||
box-shadow : 0px 1px 1px 0px rgba(0,0,0,0.1);
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle > * {
|
div#floatingTitle > * {
|
||||||
|
@ -272,11 +305,15 @@ div#floatingTitle span.author {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle a.title {
|
div#floatingTitle a.title {
|
||||||
font-size : 14px;
|
font-size : 16px;
|
||||||
color : #999;
|
color : #999;
|
||||||
font-weight : bold;
|
|
||||||
-webkit-transition : color 0.2s;
|
-webkit-transition : color 0.2s;
|
||||||
transition : color 0.2s;
|
transition : color 0.2s;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle.Unread a.title {
|
div#floatingTitle.Unread a.title {
|
||||||
|
@ -284,7 +321,6 @@ div#floatingTitle.Unread a.title {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#floatingTitle img.anchor {
|
div#floatingTitle img.anchor {
|
||||||
margin-right : 1px;
|
|
||||||
margin-left : 0px;
|
margin-left : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,4 +377,24 @@ div#floatingTitle img.hlScorePic {
|
||||||
text-decoration : line-through;
|
text-decoration : line-through;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle > * {
|
||||||
|
display : table-cell;
|
||||||
|
vertical-align : middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle a.title {
|
||||||
|
width : 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle a.catchup {
|
||||||
|
text-align : right;
|
||||||
|
color : #555;
|
||||||
|
padding-right : 10px;
|
||||||
|
font-size : 11px;
|
||||||
|
white-space : nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cdmFeedTitle a.catchup:hover {
|
||||||
|
color : #4684ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
409
source/css/dijit.css
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
/* Tree */
|
||||||
|
|
||||||
|
.claro .dijitTreeRow .dijitCheckBox {
|
||||||
|
position : relative;
|
||||||
|
top : -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeLabel {
|
||||||
|
outline : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .feedParam {
|
||||||
|
color : #555;
|
||||||
|
float : right;
|
||||||
|
margin-right : 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .filterRules {
|
||||||
|
display : block;
|
||||||
|
color : #ccc;
|
||||||
|
font-size : 10px;
|
||||||
|
margin-left : 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .filterRules span {
|
||||||
|
display : block;
|
||||||
|
color : green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filterDlg_Matches span.filterRule {
|
||||||
|
color : green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .filterRules span.inverse,
|
||||||
|
#filterDlg_Matches span.filterRule.inverse {
|
||||||
|
color : red;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.claro .dijitTree .labelParam {
|
||||||
|
float : right;
|
||||||
|
margin-right : 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeLabel.Disabled,
|
||||||
|
.claro .dijitTree .labelParam.Disabled {
|
||||||
|
color : #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow.Error {
|
||||||
|
color : red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow.Hidden {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeNode .loadingNode {
|
||||||
|
margin-left : 3px;
|
||||||
|
height : 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitFolderClosed,
|
||||||
|
.claro .dijitFolderOpened {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeNode .dijitCheckBox {
|
||||||
|
margin-left : 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeIsRoot > .dijitTreeRow > .dijitTreeExpando {
|
||||||
|
margin-left : 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeExpando {
|
||||||
|
margin-top : 0px;
|
||||||
|
opacity : 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeNode {
|
||||||
|
padding : 0px;
|
||||||
|
border-width : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRow {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRowSelected {
|
||||||
|
background : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRowHover {
|
||||||
|
background : #f0f0f0;
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTree .dijitTreeRowSelected {
|
||||||
|
background : white;
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRowSelected .dijitTreeLabel {
|
||||||
|
text-shadow : 1px 1px 2px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow .dijitTreeExpando {
|
||||||
|
background-image: url("../images/treeExpandImages.png");
|
||||||
|
position : relative;
|
||||||
|
top : -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTreeRow .dijitTreeExpandoLeaf {
|
||||||
|
background : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toolbar */
|
||||||
|
|
||||||
|
.claro .dijitToolbar {
|
||||||
|
background : #f5f5f5;
|
||||||
|
border-color : #ddd;
|
||||||
|
/* text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif; */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .claro .dijitToolbar {
|
||||||
|
text-shadow : 1px 1px 2px #fff;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.claro .dijitDialog .dijitToolbar {
|
||||||
|
border : 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dialog */
|
||||||
|
|
||||||
|
.claro .dijitDialog h2 {
|
||||||
|
margin-top : 0px;
|
||||||
|
margin-bottom : 4px;
|
||||||
|
border-width : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitMenuItemLabel {
|
||||||
|
font-size : 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkbox */
|
||||||
|
|
||||||
|
.claro .dijitCheckBox {
|
||||||
|
background-image : url("../images/untick.png");
|
||||||
|
background-color : transparent;
|
||||||
|
width : 15px;
|
||||||
|
height : 15px;
|
||||||
|
margin : 1px;
|
||||||
|
opacity : 0.7;
|
||||||
|
background-position : center center;
|
||||||
|
transition : opacity 0.25s;
|
||||||
|
-webkit-transition : opacity 0.25s;
|
||||||
|
/* border : 1px solid #b5bcc7; */
|
||||||
|
padding : 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitCheckBox:hover {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitCheckBox.dijitCheckBoxDisabled:hover {
|
||||||
|
opacity : 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitCheckBox.dijitCheckBoxChecked {
|
||||||
|
border-color : #69C671;
|
||||||
|
background-image : url("../images/tick.png");
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Various buttons */
|
||||||
|
|
||||||
|
.claro .dijitButton .dijitButtonNode,
|
||||||
|
.claro .dijitComboButton .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitComboButton,
|
||||||
|
.claro .dijitToolbar .dijitComboButton .dijitButtonNode {
|
||||||
|
background : none;
|
||||||
|
border-color : transparent;
|
||||||
|
box-shadow : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input[type="submit"] {
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
font-size : 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input[type="submit"],
|
||||||
|
.claro .dijitButton,
|
||||||
|
.claro .dijitComboButton {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 12px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #333333;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
|
||||||
|
background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||||
|
border-bottom-color: #b3b3b3;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover,
|
||||||
|
button:focus,
|
||||||
|
button:active,
|
||||||
|
input[type="submit"]:hover,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
input[type="submit"]:active,
|
||||||
|
.claro .dijitButton:hover,
|
||||||
|
.claro .dijitButton:focus,
|
||||||
|
.claro .dijitButton:active,
|
||||||
|
.claro .dijitComboButton:hover,
|
||||||
|
.claro .dijitComboButton:focus,
|
||||||
|
.claro .dijitComboButton:active,
|
||||||
|
.claro .dijitButton.dijitButtonDisabled {
|
||||||
|
color: #333333;
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active,
|
||||||
|
input[type="submit"]:active,
|
||||||
|
.claro .dijitButton:active,
|
||||||
|
.claro .dijitComboButton:active {
|
||||||
|
background-color: #cccccc \9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover,
|
||||||
|
.claro .dijitToolbar .dijitComboButton,
|
||||||
|
.claro .dijitToolbar .dijitComboButton.dijitHover {
|
||||||
|
background : none;
|
||||||
|
border-color : transparent;
|
||||||
|
box-shadow : none;
|
||||||
|
padding : 0px;
|
||||||
|
margin : 0px;
|
||||||
|
line-height : auto;
|
||||||
|
text-shadow : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonText,
|
||||||
|
.claro .dijitToolbar .dijitComboButton .dijitButtonText {
|
||||||
|
padding : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonNode {
|
||||||
|
border-radius : 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton.dijitHover .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitComboButton.dijitHover {
|
||||||
|
border-color : #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitButtonActive .dijitButtonNode {
|
||||||
|
background : none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitToolbar .dijitButton .dijitButtonContents,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton .dijitButtonContents,
|
||||||
|
.claro .dijitToolbar .dijitComboButton .dijitButtonContents {
|
||||||
|
font-size : 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover,
|
||||||
|
button:focus,
|
||||||
|
input[type="submit"]:hover,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
.claro .dijitButton:hover,
|
||||||
|
.claro .dijitToolbar .dijitButton:hover .dijitButtonNode,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitHover .dijitButtonNode,
|
||||||
|
.claro .dijitButton:focus,
|
||||||
|
.claro .dijitComboButton:hover,
|
||||||
|
.claro .dijitComboButton:focus {
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: none;
|
||||||
|
background-position: 0 -15px;
|
||||||
|
-webkit-transition: background-position 0.1s linear;
|
||||||
|
transition: background-position 0.1s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus,
|
||||||
|
input[type="submit"]:focus,
|
||||||
|
.claro .dijitButton:focus,
|
||||||
|
.claro .dijitComboButton:focus {
|
||||||
|
outline: thin dotted #333;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active,
|
||||||
|
input[type="submit"]:active,
|
||||||
|
.claro .dijitButton:active,
|
||||||
|
.claro .dijitComboButton:active,
|
||||||
|
.claro .dijitToolbar .dijitDropDownButton.dijitOpened,
|
||||||
|
.claro .dijitToolbar .dijitComboButton.dijitOpened,
|
||||||
|
.claro .dijitToolbar .dijitButton.dijitButtonActive .dijitButtonNode {
|
||||||
|
background-image: none;
|
||||||
|
outline: 0;
|
||||||
|
-webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"][disabled],
|
||||||
|
button[disabled],
|
||||||
|
.claro .dijitButton[disabled],
|
||||||
|
.claro .dijitButton.dijitButtonDisabled,
|
||||||
|
.claro .dijitComboButton.dijitButtonDisabled {
|
||||||
|
cursor: default;
|
||||||
|
background-image: none;
|
||||||
|
opacity: 0.65;
|
||||||
|
filter: alpha(opacity=65);
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitButton .dijitButtonContents,
|
||||||
|
.claro .dijitComboButton .dijitButtonContents {
|
||||||
|
font-size : 14px;
|
||||||
|
font-weight : normal;
|
||||||
|
line-height : 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitButton.small .dijitButtonText {
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitMenu {
|
||||||
|
border-color : #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitMenu .dijitMenuItem.dijitHover,
|
||||||
|
.claro .dijitMenu .dijitMenuItem.dijitFocused,
|
||||||
|
.claro .dijitMenuTable .dijitMenuItem.dijitHover .dijitMenuItemLabel,
|
||||||
|
.claro .dijitMenuTable .dijitMenuItem.dijitFocused .dijitMenuItemLabel {
|
||||||
|
background : #eee;
|
||||||
|
border-color : transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitButton .dijitButtonNode,
|
||||||
|
.claro .dijitComboButton .dijitButtonNode {
|
||||||
|
padding : 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other stuff */
|
||||||
|
|
||||||
|
/* .claro .dijitAccordionTitleFocus {
|
||||||
|
text-shadow : 1px 1px 2px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitAccordionTitle {
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.claro .dijitAccordionInnerContainer.dijitAccordionInnerContainerSelected {
|
||||||
|
border-color : #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitAccordionContainer .dijitAccordionChildWrapper {
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
|
|
||||||
|
.claro .dijitTabContent {
|
||||||
|
background : #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTabContent.dijitTabChecked,
|
||||||
|
.claro .dijitTabContent.dijitTabHover,
|
||||||
|
.claro .dijitTabContent.dijitFocused {
|
||||||
|
background : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.claro .dijitTabPaneWrapper,
|
||||||
|
.claro .dijitTabContainerTop-tabs,
|
||||||
|
.claro .dijitTab,
|
||||||
|
.claro .dijitAccordionInnerContainer {
|
||||||
|
border-color : #ddd;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,14 @@
|
||||||
|
body#ttrssPrefs {
|
||||||
|
background-color : #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssPrefs #footer, body#ttrssPrefs #header {
|
||||||
|
background-color : #f5f5f5;
|
||||||
|
padding-left : 8px;
|
||||||
|
padding-right : 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#header a:hover {
|
#header a:hover {
|
||||||
color : black;
|
color : black;
|
||||||
}
|
}
|
||||||
|
@ -13,12 +24,12 @@ div#pref-tabs .dijitContentPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
div#pref-tabs {
|
div#pref-tabs {
|
||||||
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
margin : 0px 5px 0px 5px;
|
margin : 0px 5px 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#pref-tabs .dijitContentPane h3 {
|
div#pref-tabs .dijitContentPane h3 {
|
||||||
font-size : 14px;
|
font-size : 14px;
|
||||||
font-weight : bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pref-filter-wrap, #pref-filter-header, #pref-filter-content,
|
#pref-filter-wrap, #pref-filter-header, #pref-filter-content,
|
||||||
|
@ -52,11 +63,10 @@ div.prefProfileHolder, div.prefFeedOPMLHolder, div.inactiveFeedHolder {
|
||||||
height : 300px;
|
height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
border-width : 0px 1px 1px 1px;
|
border-width : 0px 1px 1px 1px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
background-color : #ecf4ff;
|
background-color : white;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
div.filterTestHolder, div.prefFeedOPMLHolder {
|
div.filterTestHolder, div.prefFeedOPMLHolder {
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
|
@ -66,12 +76,10 @@ ul.selfUpdateList, ul.userFeedList {
|
||||||
height : 200px;
|
height : 200px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
border-radius : 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#feedlistLoading, div#filterlistLoading, div#labellistLoading {
|
div#feedlistLoading, div#filterlistLoading, div#labellistLoading {
|
||||||
|
@ -90,7 +98,8 @@ div#feedlistLoading img, div#filterlistLoading img, div#labellistLoading {
|
||||||
|
|
||||||
a.bookmarklet {
|
a.bookmarklet {
|
||||||
color : #4684ff;
|
color : #4684ff;
|
||||||
border : 1px solid #ecf4ff;
|
border : 1px solid #ddd;
|
||||||
|
background : #f5f5f5;
|
||||||
padding : 2px;
|
padding : 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +129,9 @@ table.prefErrorLog td.filename, table.prefErrorLog td.login, table.prefErrorLog
|
||||||
color : #555;
|
color : #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitAccordionContainer-child {
|
body#ttrssPrefs hr {
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.2);
|
border-color : #ecf4ff;
|
||||||
|
max-width : 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,34 +7,28 @@ body#ttrssMain, body#ttrssPrefs, body#ttrssLogin, body {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssPrefs {
|
|
||||||
background-color : #ecf4ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssPrefs #footer, body#ttrssPrefs #header {
|
|
||||||
background-color : #ecf4ff;
|
|
||||||
padding-left : 8px;
|
|
||||||
padding-right : 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.postReply {
|
div.postReply {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postReply div.postHeader {
|
div.postReply div.postHeader {
|
||||||
border-width : 0px 0px 1px 0px;
|
|
||||||
border-style : solid;
|
|
||||||
border-color : #c0c0c0;
|
|
||||||
background : #fafafa;
|
|
||||||
box-shadow : 0px 0px 3px 0px rgba(0,0,0,0.1);
|
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
|
margin-right : 4px;
|
||||||
color : #909090;
|
color : #909090;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-color : #ddd;
|
||||||
|
border-style : solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postReply div.postTitle {
|
div.postReply div.postTitle {
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space : nowrap;
|
white-space : nowrap;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postReply div.postDate {
|
div.postReply div.postDate {
|
||||||
|
@ -66,13 +60,10 @@ div.postReply img.tagsPic {
|
||||||
div.articleNote {
|
div.articleNote {
|
||||||
background-color : #fff7d5;
|
background-color : #fff7d5;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
margin : 5px;
|
margin : 5px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #e7d796;
|
border-color : #e7d796;
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
background-color : #fff7d5;
|
|
||||||
color : #9a8c59;
|
color : #9a8c59;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,29 +78,50 @@ div.postReply span.author {
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size : 18px;
|
font-size : 18px;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size : 16px;
|
font-size : 16px;
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ecf4ff;
|
border-color : #ecf4ff;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size : 12px;
|
font-size : 13px;
|
||||||
font-weight : bold;
|
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ecf4ff;
|
border-color : #ecf4ff;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size : 14px;
|
||||||
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ccc;
|
||||||
max-width : 90%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -138,7 +150,6 @@ a:hover {
|
||||||
min-width : 100px;
|
min-width : 100px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
-width : 200px;
|
-width : 200px;
|
||||||
box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#notify img {
|
#notify img {
|
||||||
|
@ -181,7 +192,11 @@ a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl div.hlTitle a {
|
.hl div.hlTitle a {
|
||||||
font-weight : bold;
|
font-weight : 600;
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP Semibold", "Segoe UI Semibold",
|
||||||
|
"Segoe UI Web Semibold", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
color : #777;
|
color : #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,13 +204,9 @@ a:hover {
|
||||||
color : black;
|
color : black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl.active {
|
|
||||||
box-shadow : inset 0px 0px 3px 0px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hl.active div.hlTitle a {
|
.hl.active div.hlTitle a {
|
||||||
color : #4684ff;
|
color : #4684ff;
|
||||||
text-shadow : 1px 1px 2px #fff;
|
/* text-shadow : 1px 1px 2px #fff; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl.Selected {
|
.hl.Selected {
|
||||||
|
@ -206,18 +217,11 @@ a:hover {
|
||||||
color : #909090;
|
color : #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #headlines-frame div.hl:nth-child(even) {
|
|
||||||
background : #fafafa;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#headlines-frame.normal {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.hl {
|
.hl {
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
|
padding : 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hl.active {
|
.hl.active {
|
||||||
|
@ -227,13 +231,11 @@ a:hover {
|
||||||
div.filterTestHolder {
|
div.filterTestHolder {
|
||||||
height : 300px;
|
height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -242,7 +244,7 @@ div.filterTestHolder {
|
||||||
color : #555;
|
color : #555;
|
||||||
padding-left : 10px;
|
padding-left : 10px;
|
||||||
border-width : 0px 0px 0px 4px;
|
border-width : 0px 0px 0px 4px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ccc;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +261,9 @@ div.filterTestHolder {
|
||||||
font-family : monospace;
|
font-family : monospace;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
border-width : 0px;
|
border-width : 0px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ccc;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
background : #fafafa;
|
background : #f5f5f5;
|
||||||
display : block;
|
display : block;
|
||||||
max-width : 98%;
|
max-width : 98%;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
|
@ -274,9 +276,7 @@ div.notice, div.warning, div.error {
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ccc;
|
border-color : #ccc;
|
||||||
border-radius : 4px;
|
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.notice div.inner, div.warning div.inner, div.error div.inner {
|
div.notice div.inner, div.warning div.inner, div.error div.inner {
|
||||||
|
@ -324,47 +324,66 @@ div.prefHelp {
|
||||||
color : #555;
|
color : #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar {
|
#main-toolbar > * {
|
||||||
border-width : 0px 0px 1px 0px;
|
white-space : nowrap;
|
||||||
background-color : #fcfcfc;
|
display : table-cell;
|
||||||
border-color : #c0c0c0;
|
color : #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-toolbar > *,
|
||||||
|
#main-toolbar table *,
|
||||||
|
#main-toolbar .actionChooser * {
|
||||||
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe WP", "Segoe UI Web", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
font-family : "Segoe UI", Tahoma, sans-serif;
|
|
||||||
color : #555;
|
|
||||||
padding : 0px;
|
|
||||||
margin : 0px;
|
|
||||||
overflow : hidden;
|
|
||||||
height : 25px;
|
|
||||||
line-height : 25px;
|
|
||||||
padding-left : 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar .dijitSelect {
|
#main-toolbar #headlines-toolbar {
|
||||||
font-size : 11px;
|
padding-right : 4px;
|
||||||
position : relative;
|
width : 100%;
|
||||||
top : -2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar span.r {
|
#main-toolbar #headlines-toolbar span.holder {
|
||||||
float: right;
|
display : table;
|
||||||
position: relative;
|
width : 100%;
|
||||||
padding : 0 4px 0px 4px;
|
}
|
||||||
|
|
||||||
|
#main-toolbar #headlines-toolbar span.holder > * {
|
||||||
|
display : table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-toolbar #headlines-toolbar .main {
|
||||||
text-align : right;
|
text-align : right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#main-toolbar #headlines-toolbar .main,
|
||||||
|
#main-toolbar #headlines-toolbar .r {
|
||||||
|
line-height : 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#headlines-toolbar span.r img {
|
||||||
|
margin-right : 4px;
|
||||||
|
position : relative;
|
||||||
|
top : 3px;
|
||||||
|
}
|
||||||
|
|
||||||
#headlines-toolbar span.r .error a {
|
#headlines-toolbar span.r .error a {
|
||||||
color : red;
|
color : red;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-toolbar span.r a {
|
#main-toolbar #selected_prompt {
|
||||||
color : #555;
|
font-style : italic;
|
||||||
|
text-align : right;
|
||||||
|
margin-right : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.contentPreview {
|
span.contentPreview {
|
||||||
color : #999;
|
color : #999;
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
text-shadow : 1px 1px 2px #fff;
|
font-size : 12px;
|
||||||
font-size : 11px;
|
padding-left : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.hlLabelRef {
|
span.hlLabelRef {
|
||||||
|
@ -377,7 +396,7 @@ span.hlLabelRef {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
vertical-align : middle;
|
vertical-align : middle;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border-radius : 4px;
|
border-radius : 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.postHeader div.postDate {
|
div.postHeader div.postDate {
|
||||||
|
@ -397,63 +416,50 @@ div.postHeader div {
|
||||||
#allEntryTags {
|
#allEntryTags {
|
||||||
border-width : 0px 0px 1px 0px;
|
border-width : 0px 0px 1px 0px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
padding-bottom : 5px;
|
padding-bottom : 5px;
|
||||||
display : none;
|
display : none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.hlFeed {
|
|
||||||
display : block;
|
|
||||||
white-space : nowrap;
|
|
||||||
font-size : 9px;
|
|
||||||
font-style : italic;
|
|
||||||
font-weight : normal;
|
|
||||||
border-radius : 4px;
|
|
||||||
display : inline-block;
|
|
||||||
padding : 1px 2px 1px 2px;
|
|
||||||
margin-bottom : 2px;
|
|
||||||
margin-top : 2px;
|
|
||||||
color : #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.hlFeed:hover {
|
|
||||||
color : #4684ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.markedPic, img.pubPic {
|
img.markedPic, img.pubPic {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
vertical-align : middle;
|
vertical-align : middle;
|
||||||
|
opacity : 0.5;
|
||||||
|
-webkit-transition : opacity 0.25s;
|
||||||
|
transition : opacity 0.25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.markedPic:hover, img.pubPic:hover {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src*='pub_set.png'], img[src*='mark_set.png'] {
|
||||||
|
opacity : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.tagCloudContainer {
|
div.tagCloudContainer {
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 5px 0px 5px 0px;
|
margin : 5px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.errorExplained {
|
div.errorExplained {
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 5px 0px 5px 0px;
|
margin : 5px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.feedErrorsList {
|
ul.feedErrorsList {
|
||||||
max-height : 300px;
|
max-height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.feedErrorsList em {
|
ul.feedErrorsList em {
|
||||||
|
@ -464,7 +470,7 @@ ul.browseFeedList {
|
||||||
height : 300px;
|
height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
border-width : 0px 1px 1px 1px;
|
border-width : 0px 1px 1px 1px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
background-color : white;
|
background-color : white;
|
||||||
|
@ -528,14 +534,6 @@ form {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main_toolbar_form {
|
|
||||||
margin : 0px;
|
|
||||||
padding : 0px;
|
|
||||||
display : table-cell;
|
|
||||||
white-space : nowrap;
|
|
||||||
width : 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.loadingPrompt {
|
div.loadingPrompt {
|
||||||
padding : 1em;
|
padding : 1em;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
|
@ -545,20 +543,11 @@ div.loadingPrompt {
|
||||||
div.whiteBox {
|
div.whiteBox {
|
||||||
margin-left : 1px;
|
margin-left : 1px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
padding : 1em;
|
padding : 1em 1em 0px 1em;
|
||||||
}
|
font-size : 11px;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
/* html, body#ttrssMain, #main {
|
border-style : solid;
|
||||||
width: 100%;
|
border-color : #ddd;
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#toolbar div.actionChooser {
|
|
||||||
display : table-cell;
|
|
||||||
text-align : right;
|
|
||||||
padding-right : 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.autocomplete {
|
div.autocomplete {
|
||||||
|
@ -589,11 +578,13 @@ div.autocomplete ul li {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hlTitle {
|
.hl .hlTitle {
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
white-space : nowrap;
|
white-space : nowrap;
|
||||||
max-width : 500px;
|
max-width : 500px;
|
||||||
text-overflow : ellipsis;
|
text-overflow : ellipsis;
|
||||||
|
padding-left : 6px;
|
||||||
|
padding-right : 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#headlines-frame.wide .hlTitle {
|
div#headlines-frame.wide .hlTitle {
|
||||||
|
@ -602,6 +593,10 @@ div#headlines-frame.wide .hlTitle {
|
||||||
white-space : normal;
|
white-space : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#headlines-frame.wide .hl .hlFeed {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
|
||||||
.hl a.title.high, span.hlContent.high .contentPreview {
|
.hl a.title.high, span.hlContent.high .contentPreview {
|
||||||
color : #00aa00;
|
color : #00aa00;
|
||||||
}
|
}
|
||||||
|
@ -667,7 +662,6 @@ span.labelColorIndicator {
|
||||||
background-color : #fff7d5;
|
background-color : #fff7d5;
|
||||||
color : #063064;
|
color : #063064;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
box-shadow : 0px 0px 1px 0px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div#cmdline {
|
div#cmdline {
|
||||||
|
@ -716,14 +710,39 @@ div.hlRight img {
|
||||||
max-height : 16px;
|
max-height : 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.hlUpdated {
|
.hl span.hlFeed {
|
||||||
color : #555;
|
|
||||||
min-width : 100px;
|
|
||||||
display : table-cell;
|
display : table-cell;
|
||||||
width : 100%;
|
|
||||||
vertical-align : middle;
|
vertical-align : middle;
|
||||||
text-align : right;
|
text-align : right;
|
||||||
font-size : 10px;
|
}
|
||||||
|
|
||||||
|
.hl span.hlFeed a {
|
||||||
|
border-radius : 4px;
|
||||||
|
display : inline-block;
|
||||||
|
padding : 1px 4px 1px 4px;
|
||||||
|
font-size : 11px;
|
||||||
|
font-style : italic;
|
||||||
|
font-weight : normal;
|
||||||
|
color : #555;
|
||||||
|
white-space : nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl span.hlFeed a:hover {
|
||||||
|
color : #4684ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl span.hlUpdated {
|
||||||
|
color : #555;
|
||||||
|
display : table-cell;
|
||||||
|
vertical-align : middle;
|
||||||
|
text-align : right;
|
||||||
|
font-size : 11px;
|
||||||
|
white-space : nowrap;
|
||||||
|
padding-left : 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.hlUpdated div {
|
||||||
|
display : inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.hlLeft {
|
div.hlLeft {
|
||||||
|
@ -771,21 +790,19 @@ div.fatalError textarea {
|
||||||
|
|
||||||
#content-wrap {
|
#content-wrap {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-width : 0px 0px 0px 1px;
|
border-width : 0px;
|
||||||
border-style : solid;
|
|
||||||
border-color : #c0c0c0;
|
|
||||||
margin : 0px;
|
margin : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feeds-holder {
|
#feeds-holder {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-color : #c0c0c0;
|
border-width : 0px 1px 0px 0px;
|
||||||
border-left-width : 0px;
|
border-style : solid;
|
||||||
border-bottom-width : 0px;
|
border-color : #ddd;
|
||||||
border-top-width : 0px;
|
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.1);
|
background : #f5f5f5;
|
||||||
background : #f9fbff;
|
box-shadow : inset -1px 0px 2px -1px rgba(0,0,0,0.1);
|
||||||
|
-webkit-overflow-scrolling : touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headlines-wrap-inner {
|
#headlines-wrap-inner {
|
||||||
|
@ -796,11 +813,10 @@ div.fatalError textarea {
|
||||||
|
|
||||||
#headlines-frame {
|
#headlines-frame {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-color : #c0c0c0;
|
|
||||||
border-style : solid;
|
|
||||||
border-width : 0px;
|
border-width : 0px;
|
||||||
|
border-color : #ddd;
|
||||||
margin-top : 0px;
|
margin-top : 0px;
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.1);
|
-webkit-overflow-scrolling : touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#headlines-toolbar_splitter, #toolbar_splitter {
|
#headlines-toolbar_splitter, #toolbar_splitter {
|
||||||
|
@ -813,7 +829,16 @@ div.fatalError textarea {
|
||||||
border-width : 0px;
|
border-width : 0px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
box-shadow : 0px 0px 2px rgba(0,0,0,0.1);
|
}
|
||||||
|
|
||||||
|
#main-toolbar {
|
||||||
|
background : white;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-color : #ddd;
|
||||||
|
border-style : solid;
|
||||||
|
padding-left : 4px;
|
||||||
|
height : 26px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
|
@ -837,12 +862,12 @@ div.fatalError textarea {
|
||||||
|
|
||||||
#content-insert {
|
#content-insert {
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-bottom-width : 0px;
|
border-width : 0px;
|
||||||
border-right-width : 0px;
|
line-height: 1.5;
|
||||||
border-left-width : 0px;
|
font-size : 15px;
|
||||||
line-height: 20px;
|
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
|
-webkit-overflow-scrolling : touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .dijitTreeRow .dijitTreeLabel.Unread {
|
#feedTree .dijitTreeRow .dijitTreeLabel.Unread {
|
||||||
|
@ -853,33 +878,6 @@ div.fatalError textarea {
|
||||||
color : red;
|
color : red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitTreeLabel {
|
|
||||||
outline : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedParam {
|
|
||||||
color : #555;
|
|
||||||
float : right;
|
|
||||||
margin-right : 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.labelParam {
|
|
||||||
float : right;
|
|
||||||
margin-right : 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeLabel.Disabled, .labelParam.Disabled {
|
|
||||||
color : #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeRow.Error {
|
|
||||||
color : red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeRow.Hidden {
|
|
||||||
display : none;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.feedIcon, img.tinyFeedIcon {
|
img.feedIcon, img.tinyFeedIcon {
|
||||||
width : 16px;
|
width : 16px;
|
||||||
height : 16px;
|
height : 16px;
|
||||||
|
@ -888,24 +886,6 @@ img.feedIcon, img.tinyFeedIcon {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitToolbar {
|
|
||||||
text-shadow : 1px 1px 2px #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitAccordionTitleFocus {
|
|
||||||
text-shadow : 1px 1px 2px #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitDialog .dijitToolbar {
|
|
||||||
border : 1px solid #c0c0c0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitDialog h2 {
|
|
||||||
margin-top : 0px;
|
|
||||||
margin-bottom : 4px;
|
|
||||||
border-width : 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player {
|
.player {
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
color : #555;
|
color : #555;
|
||||||
|
@ -933,8 +913,19 @@ img.feedIcon, img.tinyFeedIcon {
|
||||||
height : 100%;
|
height : 100%;
|
||||||
margin-left : 1px;
|
margin-left : 1px;
|
||||||
text-align : center;
|
text-align : center;
|
||||||
padding : 1em;
|
|
||||||
color : #555;
|
color : #555;
|
||||||
|
font-size : 11px;
|
||||||
|
font-style : italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#headlines-spacer a, #headlines-spacer span {
|
||||||
|
color : #555;
|
||||||
|
padding : 10px;
|
||||||
|
display : block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#headlines-spacer a:hover {
|
||||||
|
color : #88b0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#filterDlg_Matches, ul#filterDlg_Actions {
|
ul#filterDlg_Matches, ul#filterDlg_Actions {
|
||||||
|
@ -942,12 +933,11 @@ ul#filterDlg_Matches, ul#filterDlg_Actions {
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #c0c0c0;
|
border-color : #ddd;
|
||||||
border-width : 0px 1px 1px 1px;
|
border-width : 0px 1px 1px 1px;
|
||||||
background-color : #ecf4ff;
|
background-color : white;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#filterDlg_Matches li, ul#filterDlg_Actions li {
|
ul#filterDlg_Matches li, ul#filterDlg_Actions li {
|
||||||
|
@ -955,20 +945,14 @@ ul#filterDlg_Matches li, ul#filterDlg_Actions li {
|
||||||
padding : 0px 0px 0px 5px;
|
padding : 0px 0px 0px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul#filterDlg_Matches li div.dijitCheckBox, ul#filterDlg_Actions li div.dijitCheckBox {
|
|
||||||
margin-right : 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.helpKbList {
|
ul.helpKbList {
|
||||||
max-height : 300px;
|
max-height : 300px;
|
||||||
overflow : auto;
|
overflow : auto;
|
||||||
list-style-type : none;
|
list-style-type : none;
|
||||||
border : 1px solid #c0c0c0;
|
border : 1px solid #ddd;
|
||||||
background-color : #ecf4ff;
|
background-color : #f5f5f5;
|
||||||
margin : 0px 0px 5px 0px;
|
margin : 0px 0px 5px 0px;
|
||||||
padding : 5px;
|
padding : 5px;
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.helpKbList span.hksequence {
|
ul.helpKbList span.hksequence {
|
||||||
|
@ -983,18 +967,22 @@ ul.helpKbList h2 {
|
||||||
margin-top : 0px;
|
margin-top : 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dijitTreeNode .loadingNode {
|
|
||||||
margin-left : 3px;
|
|
||||||
height : 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.collapseBtn {
|
span.collapseBtn {
|
||||||
cursor : pointer;
|
cursor : pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.postContent h1 {
|
||||||
|
font-size : 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.postContent h2,
|
||||||
|
div.postContent h3,
|
||||||
|
div.postContent h4 {
|
||||||
|
font-size : 15px;
|
||||||
|
}
|
||||||
|
|
||||||
div.postContent p {
|
div.postContent p {
|
||||||
max-width : 650px;
|
max-width : 650px;
|
||||||
text-align : justify;
|
|
||||||
-webkit-hyphens: auto;
|
-webkit-hyphens: auto;
|
||||||
-moz-hyphens: auto;
|
-moz-hyphens: auto;
|
||||||
hyphens: auto;
|
hyphens: auto;
|
||||||
|
@ -1010,90 +998,12 @@ div.postHeader span.author {
|
||||||
font-weight : normal;
|
font-weight : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssZoom {
|
|
||||||
margin-left : auto;
|
|
||||||
margin-right : auto;
|
|
||||||
padding : 20px;
|
|
||||||
max-width : 670px;
|
|
||||||
background : #f9fbff;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postFeedTitle {
|
|
||||||
float : left;
|
|
||||||
text-align : right;
|
|
||||||
padding-left : 0px;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader a.postComments {
|
|
||||||
text-align : right;
|
|
||||||
padding-left : 0px;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postDate {
|
|
||||||
float : none;
|
|
||||||
text-align : right;
|
|
||||||
padding-left : 0px;
|
|
||||||
color : #777;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postTags {
|
|
||||||
color : #777;
|
|
||||||
font-size : 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader div.postTitle {
|
|
||||||
white-space : normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postContent p {
|
|
||||||
max-width : 650px;
|
|
||||||
text-align : justify;
|
|
||||||
-webkit-hyphens: auto;
|
|
||||||
-moz-hyphens: auto;
|
|
||||||
hyphens: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postHeader {
|
|
||||||
margin : 10px;
|
|
||||||
border : 1px solid #ccc;
|
|
||||||
box-shadow : none;
|
|
||||||
border-radius : 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postReply {
|
|
||||||
border : 1px solid #ccc;
|
|
||||||
border-radius : 4px;
|
|
||||||
box-shadow : inset 0px 0px 3px rgba(0,0,0,0.1);
|
|
||||||
background : white;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postContent {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.footer {
|
|
||||||
margin-top : 1em;
|
|
||||||
text-align : center;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssZoom div.postContent img {
|
|
||||||
max-width : 650px;
|
|
||||||
height : auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
select.attachments {
|
select.attachments {
|
||||||
display : block;
|
display : block;
|
||||||
margin-top : 10px;
|
margin-top : 10px;
|
||||||
max-width : 120px;
|
max-width : 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.hl.active {
|
|
||||||
border-color : #88b0f0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#selected_prompt {
|
#selected_prompt {
|
||||||
margin-right : 25px;
|
margin-right : 25px;
|
||||||
}
|
}
|
||||||
|
@ -1107,46 +1017,28 @@ body#ttrssMain #feedTree .dijitTreeRow {
|
||||||
padding : 2px 0px 2px;
|
padding : 2px 0px 2px;
|
||||||
height : 22px;
|
height : 22px;
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
border-color : transparent;
|
|
||||||
color : #333;
|
color : #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitFolderClosed,
|
ul#filterDlg_Matches li div.dijitCheckBox, ul#filterDlg_Actions li div.dijitCheckBox {
|
||||||
body#ttrssMain #feedTree .dijitFolderOpened {
|
margin-right : 5px;
|
||||||
display : none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeNode .dijitCheckBox {
|
|
||||||
margin-left : 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitTreeIsRoot > .dijitTreeRow > .dijitTreeExpando {
|
|
||||||
margin-left : 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitTreeExpando {
|
|
||||||
margin-top : 0px;
|
|
||||||
opacity : 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssMain #feedTree .dijitTreeNode {
|
|
||||||
padding : 0px;
|
|
||||||
border-width : 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body#ttrssMain #feedTree {
|
body#ttrssMain #feedTree {
|
||||||
height : 100%;
|
height : 100%;
|
||||||
overflow-x : hidden;
|
overflow-x : hidden;
|
||||||
font-family : "Segoe UI", Tahoma, sans-serif;
|
text-rendering: optimizelegibility;
|
||||||
|
font-family : "Segoe UI Web", "Segoe UI", Ubuntu, "DejaVu Sans", "Helvetica Neue",
|
||||||
|
Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .counterNode.aux {
|
body#ttrssMain #feedTree .counterNode.aux {
|
||||||
background : #f0f0f0;
|
background : #f0f0f0;
|
||||||
color : #999;
|
color : #999;
|
||||||
border-color : #f0f0f0;
|
border-color : #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .counterNode {
|
body#ttrssMain #feedTree .counterNode {
|
||||||
font-weight : bold;
|
font-weight : bold;
|
||||||
display : inline-block;
|
display : inline-block;
|
||||||
font-size : 9px;
|
font-size : 9px;
|
||||||
|
@ -1159,31 +1051,12 @@ body#ttrssMain #feedTree {
|
||||||
float : right;
|
float : right;
|
||||||
position : relative;
|
position : relative;
|
||||||
line-height : 14px;
|
line-height : 14px;
|
||||||
margin-right : 4px;
|
margin-right : 8px;
|
||||||
margin-top : 3px;
|
margin-top : 3px;
|
||||||
min-width : 23px;
|
min-width : 23px;
|
||||||
height : 14px;
|
height : 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#feedTree .dijitTreeRow {
|
|
||||||
max-width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
body#ttrssPrefs hr {
|
|
||||||
border-color : #ecf4ff;
|
|
||||||
max-width : 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitMenuItemLabel {
|
|
||||||
font-size : 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dijitTreeRowSelected .dijitTreeLabel {
|
|
||||||
text-shadow : 1px 1px 2px #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedTree img[src*='indicator_white.gif'] {
|
#feedTree img[src*='indicator_white.gif'] {
|
||||||
position : relative;
|
position : relative;
|
||||||
top : -2px;
|
top : -2px;
|
||||||
|
@ -1198,3 +1071,23 @@ div.enclosure_title {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body#ttrssMain #headlines-frame .dijitCheckBox {
|
||||||
|
border-width : 0px;
|
||||||
|
opacity : 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssMain #headlines-frame .dijitCheckBoxHover,
|
||||||
|
body#ttrssMain #headlines-frame .dijitCheckBoxChecked {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssMain #feedTree .dijitTreeRow img.dijitTreeExpandoLeaf {
|
||||||
|
width : 16px;
|
||||||
|
height : 16px;
|
||||||
|
vertical-align : middle;
|
||||||
|
position : relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
body {
|
body {
|
||||||
background : #f9fbff;
|
background : #f5f5f5;
|
||||||
color : black;
|
color : black;
|
||||||
padding : 0px;
|
padding : 0px;
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
@ -15,11 +15,11 @@ form {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.content {
|
div.content {
|
||||||
|
overflow : hidden;
|
||||||
background : white;
|
background : white;
|
||||||
border : 1px solid #ccc;
|
border : 1px solid #ddd;
|
||||||
padding : 10px;
|
padding : 10px;
|
||||||
border-radius : 4px;
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
box-shadow : inset 0 0 3px rgba(0,0,0,0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.warning {
|
p.warning {
|
||||||
|
@ -40,9 +40,7 @@ div.insensitive-small {
|
||||||
}
|
}
|
||||||
|
|
||||||
.floatingLogo {
|
.floatingLogo {
|
||||||
float : right;
|
display : none;
|
||||||
position : relative;
|
|
||||||
top : -10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -61,7 +59,6 @@ div.notice, div.warning, div.error {
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
border-style : solid;
|
border-style : solid;
|
||||||
border-color : #ccc;
|
border-color : #ccc;
|
||||||
border-radius : 4px;
|
|
||||||
border-width : 1px;
|
border-width : 1px;
|
||||||
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
box-shadow : inset 0px 0px 2px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
105
source/css/zoom.css
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
body#ttrssZoom {
|
||||||
|
margin-left : auto;
|
||||||
|
margin-right : auto;
|
||||||
|
padding : 20px;
|
||||||
|
max-width : 670px;
|
||||||
|
background : #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postFeedTitle {
|
||||||
|
float : left;
|
||||||
|
text-align : right;
|
||||||
|
padding-left : 0px;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader a.postComments {
|
||||||
|
text-align : right;
|
||||||
|
padding-left : 0px;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postDate {
|
||||||
|
float : none;
|
||||||
|
text-align : right;
|
||||||
|
padding-left : 0px;
|
||||||
|
color : #777;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postTags {
|
||||||
|
color : #777;
|
||||||
|
font-size : 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader div.postTitle {
|
||||||
|
white-space : normal;
|
||||||
|
font-size : 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent {
|
||||||
|
font-size : 15px;
|
||||||
|
line-height : 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent p {
|
||||||
|
max-width : 650px;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postHeader {
|
||||||
|
margin : 10px;
|
||||||
|
border-width : 0px 0px 1px 0px;
|
||||||
|
border-style : solid;
|
||||||
|
border-color : #eee;
|
||||||
|
background : white;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postReply {
|
||||||
|
border : 1px solid #ddd;
|
||||||
|
background : white;
|
||||||
|
box-shadow : 0px 1px 1px -1px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.footer {
|
||||||
|
margin-top : 1em;
|
||||||
|
text-align : center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent img {
|
||||||
|
max-width : 630px;
|
||||||
|
height : auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent blockquote {
|
||||||
|
margin : 5px 0px 5px 0px;
|
||||||
|
color : #555;
|
||||||
|
padding-left : 10px;
|
||||||
|
border-width : 0px 0px 0px 4px;
|
||||||
|
border-color : #ccc;
|
||||||
|
border-style : solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent code {
|
||||||
|
color : #009900;
|
||||||
|
font-family : monospace;
|
||||||
|
font-size : 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body#ttrssZoom div.postContent pre {
|
||||||
|
margin : 5px 0px 5px 0px;
|
||||||
|
padding : 10px;
|
||||||
|
color : #555;
|
||||||
|
font-family : monospace;
|
||||||
|
font-size : 12px;
|
||||||
|
border-width : 0px;
|
||||||
|
border-color : #ccc;
|
||||||
|
border-style : solid;
|
||||||
|
background : #f5f5f5;
|
||||||
|
display : block;
|
||||||
|
max-width : 98%;
|
||||||
|
overflow : auto;
|
||||||
|
}
|
||||||
|
|
0
source/feed-icons/.empty
Executable file
0
source/feed-icons/index.html
Normal file
|
@ -41,8 +41,6 @@
|
||||||
header("Content-type: image/png");
|
header("Content-type: image/png");
|
||||||
$stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT";
|
$stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT";
|
||||||
header("Last-Modified: $stamp", true);
|
header("Last-Modified: $stamp", true);
|
||||||
ob_clean(); // discard any data in the output buffer (if possible)
|
|
||||||
flush(); // flush headers (if possible)
|
|
||||||
readfile($filename);
|
readfile($filename);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Before Width: | Height: | Size: 610 B After Width: | Height: | Size: 623 B |
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 717 B |
BIN
source/images/tick.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
source/images/treeExpandImages.png
Normal file
After Width: | Height: | Size: 288 B |
BIN
source/images/untick.png
Normal file
After Width: | Height: | Size: 518 B |
|
@ -92,7 +92,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function ccache_update($feed_id, $owner_uid, $is_cat = false,
|
function ccache_update($feed_id, $owner_uid, $is_cat = false,
|
||||||
$update_pcat = true) {
|
$update_pcat = true, $pcat_fast = false) {
|
||||||
|
|
||||||
if (!is_numeric($feed_id)) return;
|
if (!is_numeric($feed_id)) return;
|
||||||
|
|
||||||
|
@ -127,11 +127,13 @@
|
||||||
|
|
||||||
/* Recalculate counters for child feeds */
|
/* Recalculate counters for child feeds */
|
||||||
|
|
||||||
$result = db_query("SELECT id FROM ttrss_feeds
|
if (!$pcat_fast) {
|
||||||
|
$result = db_query("SELECT id FROM ttrss_feeds
|
||||||
WHERE owner_uid = '$owner_uid' AND $cat_qpart");
|
WHERE owner_uid = '$owner_uid' AND $cat_qpart");
|
||||||
|
|
||||||
while ($line = db_fetch_assoc($result)) {
|
while ($line = db_fetch_assoc($result)) {
|
||||||
ccache_update($line["id"], $owner_uid, false, false);
|
ccache_update($line["id"], $owner_uid, false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = db_query("SELECT SUM(value) AS sv
|
$result = db_query("SELECT SUM(value) AS sv
|
||||||
|
@ -177,7 +179,7 @@
|
||||||
|
|
||||||
$cat_id = (int) db_fetch_result($result, 0, "cat_id");
|
$cat_id = (int) db_fetch_result($result, 0, "cat_id");
|
||||||
|
|
||||||
ccache_update($cat_id, $owner_uid, true);
|
ccache_update($cat_id, $owner_uid, true, true, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,6 @@
|
||||||
ORDER BY ttrss_feed_categories.title, ttrss_feeds.title, score DESC, date_updated DESC
|
ORDER BY ttrss_feed_categories.title, ttrss_feeds.title, score DESC, date_updated DESC
|
||||||
LIMIT $limit");
|
LIMIT $limit");
|
||||||
|
|
||||||
$cur_feed_title = "";
|
|
||||||
|
|
||||||
$headlines_count = db_num_rows($result);
|
$headlines_count = db_num_rows($result);
|
||||||
|
|
||||||
$headlines = array();
|
$headlines = array();
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
htmlspecialchars($line["title"])."</span></a>";
|
htmlspecialchars($line["title"])."</span></a>";
|
||||||
|
|
||||||
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
||||||
href=\"$feed_url\"><img src='images/pub_set.svg'
|
href=\"$feed_url\"><img src='images/pub_set.png'
|
||||||
style='vertical-align : middle'></a>";
|
style='vertical-align : middle'></a>";
|
||||||
|
|
||||||
$rv .= "<li>$check_box $feed_url $site_url".
|
$rv .= "<li>$check_box $feed_url $site_url".
|
||||||
|
@ -72,7 +72,6 @@
|
||||||
} else if ($mode == 2) {
|
} else if ($mode == 2) {
|
||||||
$feed_url = htmlspecialchars($line["feed_url"]);
|
$feed_url = htmlspecialchars($line["feed_url"]);
|
||||||
$site_url = htmlspecialchars($line["site_url"]);
|
$site_url = htmlspecialchars($line["site_url"]);
|
||||||
$title = htmlspecialchars($line["title"]);
|
|
||||||
|
|
||||||
$check_box = "<input onclick='toggleSelectListRow2(this)' dojoType=\"dijit.form.CheckBox\"
|
$check_box = "<input onclick='toggleSelectListRow2(this)' dojoType=\"dijit.form.CheckBox\"
|
||||||
type=\"checkbox\">";
|
type=\"checkbox\">";
|
||||||
|
@ -92,7 +91,7 @@
|
||||||
htmlspecialchars($line["title"])."</span></a>";
|
htmlspecialchars($line["title"])."</span></a>";
|
||||||
|
|
||||||
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
$feed_url = "<a target=\"_blank\" class=\"fb_feedUrl\"
|
||||||
href=\"$feed_url\"><img src='images/pub_set.svg'
|
href=\"$feed_url\"><img src='images/pub_set.png'
|
||||||
style='vertical-align : middle'></a>";
|
style='vertical-align : middle'></a>";
|
||||||
|
|
||||||
|
|
||||||
|
|
2403
source/include/functions2.php
Normal file
|
@ -109,7 +109,7 @@
|
||||||
|
|
||||||
if (!$label_id) return;
|
if (!$label_id) return;
|
||||||
|
|
||||||
$result = db_query(
|
db_query(
|
||||||
"DELETE FROM ttrss_user_labels2
|
"DELETE FROM ttrss_user_labels2
|
||||||
WHERE
|
WHERE
|
||||||
label_id = '$label_id' AND
|
label_id = '$label_id' AND
|
||||||
|
|
|
@ -2,15 +2,22 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Tiny Tiny RSS : Login</title>
|
<title>Tiny Tiny RSS : Login</title>
|
||||||
<link rel="stylesheet" type="text/css" href="lib/dijit/themes/claro/claro.css"/>
|
<?php echo stylesheet_tag("lib/dijit/themes/claro/claro.css") ?>
|
||||||
<link rel="stylesheet" type="text/css" href="css/tt-rss.css">
|
<?php echo stylesheet_tag("css/tt-rss.css") ?>
|
||||||
|
<?php echo stylesheet_tag("css/dijit.css") ?>
|
||||||
<link rel="shortcut icon" type="image/png" href="images/favicon.png">
|
<link rel="shortcut icon" type="image/png" href="images/favicon.png">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<script type="text/javascript" src="lib/dojo/dojo.js"></script>
|
<?php
|
||||||
<script type="text/javascript" src="lib/dojo/tt-rss-layer.js"></script>
|
foreach (array("lib/prototype.js",
|
||||||
<script type="text/javascript" src="lib/prototype.js"></script>
|
"lib/dojo/dojo.js",
|
||||||
<script type="text/javascript" src="js/functions.js"></script>
|
"lib/dojo/tt-rss-layer.js",
|
||||||
<script type="text/javascript" charset="utf-8" src="errors.php?mode=js"></script>
|
"js/functions.js",
|
||||||
|
"errors.php?mode=js") as $jsfile) {
|
||||||
|
|
||||||
|
echo javascript_tag($jsfile);
|
||||||
|
|
||||||
|
} ?>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
require({cache:{}});
|
require({cache:{}});
|
||||||
Event.observe(window, 'load', function() {
|
Event.observe(window, 'load', function() {
|
||||||
|
|
|
@ -2,6 +2,19 @@
|
||||||
define_default('DAEMON_UPDATE_LOGIN_LIMIT', 30);
|
define_default('DAEMON_UPDATE_LOGIN_LIMIT', 30);
|
||||||
define_default('DAEMON_FEED_LIMIT', 500);
|
define_default('DAEMON_FEED_LIMIT', 500);
|
||||||
define_default('DAEMON_SLEEP_INTERVAL', 120);
|
define_default('DAEMON_SLEEP_INTERVAL', 120);
|
||||||
|
define_default('_MIN_CACHE_IMAGE_SIZE', 1024);
|
||||||
|
|
||||||
|
function calculate_article_hash($article, $pluginhost) {
|
||||||
|
$tmp = "";
|
||||||
|
|
||||||
|
foreach ($article as $k => $v) {
|
||||||
|
if ($k != "feed" && isset($v)) {
|
||||||
|
$tmp .= sha1("$k:" . (is_array($v) ? implode(",", $v) : $v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sha1(implode(",", $pluginhost->get_plugin_names()) . $tmp);
|
||||||
|
}
|
||||||
|
|
||||||
function update_feedbrowser_cache() {
|
function update_feedbrowser_cache() {
|
||||||
|
|
||||||
|
@ -79,7 +92,7 @@
|
||||||
$login_thresh_qpart = "";
|
$login_thresh_qpart = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the feed need a update (update interval exceded).
|
// Test if the feed need a update (update interval exceeded).
|
||||||
if (DB_TYPE == "pgsql") {
|
if (DB_TYPE == "pgsql") {
|
||||||
$update_limit_qpart = "AND ((
|
$update_limit_qpart = "AND ((
|
||||||
ttrss_feeds.update_interval = 0
|
ttrss_feeds.update_interval = 0
|
||||||
|
@ -88,8 +101,10 @@
|
||||||
) OR (
|
) OR (
|
||||||
ttrss_feeds.update_interval > 0
|
ttrss_feeds.update_interval > 0
|
||||||
AND ttrss_feeds.last_updated < NOW() - CAST((ttrss_feeds.update_interval || ' minutes') AS INTERVAL)
|
AND ttrss_feeds.last_updated < NOW() - CAST((ttrss_feeds.update_interval || ' minutes') AS INTERVAL)
|
||||||
) OR ttrss_feeds.last_updated IS NULL
|
) OR (ttrss_feeds.last_updated IS NULL
|
||||||
OR last_updated = '1970-01-01 00:00:00')";
|
AND ttrss_user_prefs.value != '-1')
|
||||||
|
OR (last_updated = '1970-01-01 00:00:00'
|
||||||
|
AND ttrss_user_prefs.value != '-1'))";
|
||||||
} else {
|
} else {
|
||||||
$update_limit_qpart = "AND ((
|
$update_limit_qpart = "AND ((
|
||||||
ttrss_feeds.update_interval = 0
|
ttrss_feeds.update_interval = 0
|
||||||
|
@ -98,8 +113,10 @@
|
||||||
) OR (
|
) OR (
|
||||||
ttrss_feeds.update_interval > 0
|
ttrss_feeds.update_interval > 0
|
||||||
AND ttrss_feeds.last_updated < DATE_SUB(NOW(), INTERVAL ttrss_feeds.update_interval MINUTE)
|
AND ttrss_feeds.last_updated < DATE_SUB(NOW(), INTERVAL ttrss_feeds.update_interval MINUTE)
|
||||||
) OR ttrss_feeds.last_updated IS NULL
|
) OR (ttrss_feeds.last_updated IS NULL
|
||||||
OR last_updated = '1970-01-01 00:00:00')";
|
AND ttrss_user_prefs.value != '-1')
|
||||||
|
OR (last_updated = '1970-01-01 00:00:00'
|
||||||
|
AND ttrss_user_prefs.value != '-1'))";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if feed is currently being updated by another process.
|
// Test if feed is currently being updated by another process.
|
||||||
|
@ -118,6 +135,7 @@
|
||||||
ttrss_feeds, ttrss_users, ttrss_user_prefs
|
ttrss_feeds, ttrss_users, ttrss_user_prefs
|
||||||
WHERE
|
WHERE
|
||||||
ttrss_feeds.owner_uid = ttrss_users.id
|
ttrss_feeds.owner_uid = ttrss_users.id
|
||||||
|
AND ttrss_user_prefs.profile IS NULL
|
||||||
AND ttrss_users.id = ttrss_user_prefs.owner_uid
|
AND ttrss_users.id = ttrss_user_prefs.owner_uid
|
||||||
AND ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL'
|
AND ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL'
|
||||||
$login_thresh_qpart $update_limit_qpart
|
$login_thresh_qpart $update_limit_qpart
|
||||||
|
@ -151,6 +169,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
$nf = 0;
|
$nf = 0;
|
||||||
|
$bstarted = microtime(true);
|
||||||
|
|
||||||
// For each feed, we call the feed update function.
|
// For each feed, we call the feed update function.
|
||||||
foreach ($feeds_to_update as $feed) {
|
foreach ($feeds_to_update as $feed) {
|
||||||
|
@ -165,6 +184,7 @@
|
||||||
ttrss_user_prefs.owner_uid = ttrss_feeds.owner_uid AND
|
ttrss_user_prefs.owner_uid = ttrss_feeds.owner_uid AND
|
||||||
ttrss_users.id = ttrss_user_prefs.owner_uid AND
|
ttrss_users.id = ttrss_user_prefs.owner_uid AND
|
||||||
ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL' AND
|
ttrss_user_prefs.pref_name = 'DEFAULT_UPDATE_INTERVAL' AND
|
||||||
|
ttrss_user_prefs.profile IS NULL AND
|
||||||
feed_url = '".db_escape_string($feed)."' AND
|
feed_url = '".db_escape_string($feed)."' AND
|
||||||
(ttrss_feeds.update_interval > 0 OR
|
(ttrss_feeds.update_interval > 0 OR
|
||||||
ttrss_user_prefs.value != '-1')
|
ttrss_user_prefs.value != '-1')
|
||||||
|
@ -172,15 +192,27 @@
|
||||||
ORDER BY ttrss_feeds.id $query_limit");
|
ORDER BY ttrss_feeds.id $query_limit");
|
||||||
|
|
||||||
if (db_num_rows($tmp_result) > 0) {
|
if (db_num_rows($tmp_result) > 0) {
|
||||||
|
$rss = false;
|
||||||
|
|
||||||
while ($tline = db_fetch_assoc($tmp_result)) {
|
while ($tline = db_fetch_assoc($tmp_result)) {
|
||||||
if($debug) _debug(" => " . $tline["last_updated"] . ", " . $tline["id"] . " " . $tline["owner_uid"]);
|
if($debug) _debug(" => " . $tline["last_updated"] . ", " . $tline["id"] . " " . $tline["owner_uid"]);
|
||||||
update_rss_feed($tline["id"], true);
|
|
||||||
|
$fstarted = microtime(true);
|
||||||
|
$rss = update_rss_feed($tline["id"], true, false);
|
||||||
_debug_suppress(false);
|
_debug_suppress(false);
|
||||||
|
|
||||||
|
_debug(sprintf(" %.4f (sec)", microtime(true) - $fstarted));
|
||||||
|
|
||||||
++$nf;
|
++$nf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($nf > 0) {
|
||||||
|
_debug(sprintf("Processed %d feeds in %.4f (sec), %.4f (sec/feed avg)", $nf,
|
||||||
|
microtime(true) - $bstarted, (microtime(true) - $bstarted) / $nf));
|
||||||
|
}
|
||||||
|
|
||||||
require_once "digest.php";
|
require_once "digest.php";
|
||||||
|
|
||||||
// Send feed digests by email if needed.
|
// Send feed digests by email if needed.
|
||||||
|
@ -191,7 +223,7 @@
|
||||||
} // function update_daemon_common
|
} // function update_daemon_common
|
||||||
|
|
||||||
// ignore_daemon is not used
|
// ignore_daemon is not used
|
||||||
function update_rss_feed($feed, $ignore_daemon = false, $no_cache = false) {
|
function update_rss_feed($feed, $ignore_daemon = false, $no_cache = false, $rss = false) {
|
||||||
|
|
||||||
$debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
|
$debug_enabled = defined('DAEMON_EXTENDED_DEBUG') || $_REQUEST['xdebug'];
|
||||||
|
|
||||||
|
@ -199,7 +231,7 @@
|
||||||
_debug("start", $debug_enabled);
|
_debug("start", $debug_enabled);
|
||||||
|
|
||||||
$result = db_query("SELECT id,update_interval,auth_login,
|
$result = db_query("SELECT id,update_interval,auth_login,
|
||||||
feed_url,auth_pass,cache_images,last_updated,
|
feed_url,auth_pass,cache_images,
|
||||||
mark_unread_on_update, owner_uid,
|
mark_unread_on_update, owner_uid,
|
||||||
pubsub_state, auth_pass_encrypted,
|
pubsub_state, auth_pass_encrypted,
|
||||||
(SELECT max(date_entered) FROM
|
(SELECT max(date_entered) FROM
|
||||||
|
@ -211,7 +243,6 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$last_updated = db_fetch_result($result, 0, "last_updated");
|
|
||||||
$last_article_timestamp = @strtotime(db_fetch_result($result, 0, "last_article_timestamp"));
|
$last_article_timestamp = @strtotime(db_fetch_result($result, 0, "last_article_timestamp"));
|
||||||
|
|
||||||
if (defined('_DISABLE_HTTP_304'))
|
if (defined('_DISABLE_HTTP_304'))
|
||||||
|
@ -252,34 +283,37 @@
|
||||||
$pluginhost->load($user_plugins, PluginHost::KIND_USER, $owner_uid);
|
$pluginhost->load($user_plugins, PluginHost::KIND_USER, $owner_uid);
|
||||||
$pluginhost->load_data();
|
$pluginhost->load_data();
|
||||||
|
|
||||||
$rss = false;
|
if ($rss && is_object($rss) && get_class($rss) == "FeedParser") {
|
||||||
$rss_hash = false;
|
_debug("using previously initialized parser object");
|
||||||
|
|
||||||
$force_refetch = isset($_REQUEST["force_refetch"]);
|
|
||||||
|
|
||||||
if (file_exists($cache_filename) &&
|
|
||||||
is_readable($cache_filename) &&
|
|
||||||
!$auth_login && !$auth_pass &&
|
|
||||||
filemtime($cache_filename) > time() - 30) {
|
|
||||||
|
|
||||||
_debug("using local cache.", $debug_enabled);
|
|
||||||
|
|
||||||
@$feed_data = file_get_contents($cache_filename);
|
|
||||||
|
|
||||||
if ($feed_data) {
|
|
||||||
$rss_hash = sha1($feed_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_debug("local cache will not be used for this feed", $debug_enabled);
|
$rss_hash = false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!$rss) {
|
$force_refetch = isset($_REQUEST["force_refetch"]);
|
||||||
|
|
||||||
foreach ($pluginhost->get_hooks(PluginHost::HOOK_FETCH_FEED) as $plugin) {
|
foreach ($pluginhost->get_hooks(PluginHost::HOOK_FETCH_FEED) as $plugin) {
|
||||||
$feed_data = $plugin->hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed);
|
$feed_data = $plugin->hook_fetch_feed($feed_data, $fetch_url, $owner_uid, $feed, $last_article_timestamp, $auth_login, $auth_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try cache
|
||||||
|
if (!$feed_data &&
|
||||||
|
file_exists($cache_filename) &&
|
||||||
|
is_readable($cache_filename) &&
|
||||||
|
!$auth_login && !$auth_pass &&
|
||||||
|
filemtime($cache_filename) > time() - 30) {
|
||||||
|
|
||||||
|
_debug("using local cache [$cache_filename].", $debug_enabled);
|
||||||
|
|
||||||
|
@$feed_data = file_get_contents($cache_filename);
|
||||||
|
|
||||||
|
if ($feed_data) {
|
||||||
|
$rss_hash = sha1($feed_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_debug("local cache will not be used for this feed", $debug_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch feed from source
|
||||||
if (!$feed_data) {
|
if (!$feed_data) {
|
||||||
_debug("fetching [$fetch_url]...", $debug_enabled);
|
_debug("fetching [$fetch_url]...", $debug_enabled);
|
||||||
_debug("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T', $last_article_timestamp), $debug_enabled);
|
_debug("If-Modified-Since: ".gmdate('D, d M Y H:i:s \G\M\T', $last_article_timestamp), $debug_enabled);
|
||||||
|
@ -318,6 +352,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
// cache vanilla feed data for re-use
|
||||||
|
if ($feed_data && !$auth_pass && !$auth_login && is_writable(CACHE_DIR . "/simplepie")) {
|
||||||
|
$new_rss_hash = sha1($feed_data);
|
||||||
|
|
||||||
|
if ($new_rss_hash != $rss_hash) {
|
||||||
|
_debug("saving $cache_filename", $debug_enabled);
|
||||||
|
@file_put_contents($cache_filename, $feed_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$feed_data) {
|
if (!$feed_data) {
|
||||||
|
@ -356,10 +400,12 @@
|
||||||
$rss->init();
|
$rss->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once "lib/languagedetect/LanguageDetect.php";
|
if (DETECT_ARTICLE_LANGUAGE) {
|
||||||
|
require_once "lib/languagedetect/LanguageDetect.php";
|
||||||
|
|
||||||
$lang = new Text_LanguageDetect();
|
$lang = new Text_LanguageDetect();
|
||||||
$lang->setNameMode(2);
|
$lang->setNameMode(2);
|
||||||
|
}
|
||||||
|
|
||||||
// print_r($rss);
|
// print_r($rss);
|
||||||
|
|
||||||
|
@ -367,16 +413,6 @@
|
||||||
|
|
||||||
if (!$rss->error()) {
|
if (!$rss->error()) {
|
||||||
|
|
||||||
// cache data for later
|
|
||||||
if (!$auth_pass && !$auth_login && is_writable(CACHE_DIR . "/simplepie")) {
|
|
||||||
$new_rss_hash = sha1($rss_data);
|
|
||||||
|
|
||||||
if ($new_rss_hash != $rss_hash && count($rss->get_items()) > 0 ) {
|
|
||||||
_debug("saving $cache_filename", $debug_enabled);
|
|
||||||
@file_put_contents($cache_filename, $feed_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We use local pluginhost here because we need to load different per-user feed plugins
|
// We use local pluginhost here because we need to load different per-user feed plugins
|
||||||
$pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
|
$pluginhost->run_hooks(PluginHost::HOOK_FEED_PARSED, "hook_feed_parsed", $rss);
|
||||||
|
|
||||||
|
@ -495,7 +531,20 @@
|
||||||
|
|
||||||
_debug("feed hub url: $feed_hub_url", $debug_enabled);
|
_debug("feed hub url: $feed_hub_url", $debug_enabled);
|
||||||
|
|
||||||
if ($feed_hub_url && function_exists('curl_init') &&
|
$feed_self_url = $fetch_url;
|
||||||
|
|
||||||
|
$links = $rss->get_links('self');
|
||||||
|
|
||||||
|
if ($links && is_array($links)) {
|
||||||
|
foreach ($links as $l) {
|
||||||
|
$feed_self_url = $l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_debug("feed self url = $feed_self_url");
|
||||||
|
|
||||||
|
if ($feed_hub_url && $feed_self_url && function_exists('curl_init') &&
|
||||||
!ini_get("open_basedir")) {
|
!ini_get("open_basedir")) {
|
||||||
|
|
||||||
require_once 'lib/pubsubhubbub/subscriber.php';
|
require_once 'lib/pubsubhubbub/subscriber.php';
|
||||||
|
@ -505,9 +554,9 @@
|
||||||
|
|
||||||
$s = new Subscriber($feed_hub_url, $callback_url);
|
$s = new Subscriber($feed_hub_url, $callback_url);
|
||||||
|
|
||||||
$rc = $s->subscribe($fetch_url);
|
$rc = $s->subscribe($feed_self_url);
|
||||||
|
|
||||||
_debug("feed hub url found, subscribe request sent.", $debug_enabled);
|
_debug("feed hub url found, subscribe request sent. [rc=$rc]", $debug_enabled);
|
||||||
|
|
||||||
db_query("UPDATE ttrss_feeds SET pubsub_state = 1
|
db_query("UPDATE ttrss_feeds SET pubsub_state = 1
|
||||||
WHERE id = '$feed'");
|
WHERE id = '$feed'");
|
||||||
|
@ -524,9 +573,6 @@
|
||||||
$entry_guid = $item->get_id();
|
$entry_guid = $item->get_id();
|
||||||
if (!$entry_guid) $entry_guid = $item->get_link();
|
if (!$entry_guid) $entry_guid = $item->get_link();
|
||||||
if (!$entry_guid) $entry_guid = make_guid_from_title($item->get_title());
|
if (!$entry_guid) $entry_guid = make_guid_from_title($item->get_title());
|
||||||
|
|
||||||
_debug("f_guid $entry_guid", $debug_enabled);
|
|
||||||
|
|
||||||
if (!$entry_guid) continue;
|
if (!$entry_guid) continue;
|
||||||
|
|
||||||
$entry_guid = "$owner_uid,$entry_guid";
|
$entry_guid = "$owner_uid,$entry_guid";
|
||||||
|
@ -543,9 +589,6 @@
|
||||||
|
|
||||||
if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
|
if ($entry_timestamp == -1 || !$entry_timestamp || $entry_timestamp > time()) {
|
||||||
$entry_timestamp = time();
|
$entry_timestamp = time();
|
||||||
$no_orig_date = 'true';
|
|
||||||
} else {
|
|
||||||
$no_orig_date = 'false';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
|
$entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
|
||||||
|
@ -572,15 +615,19 @@
|
||||||
print "\n";
|
print "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_language = $lang->detect($entry_title . " " . $entry_content, 1);
|
$entry_language = "";
|
||||||
|
|
||||||
if (count($entry_language) > 0) {
|
if (DETECT_ARTICLE_LANGUAGE) {
|
||||||
$entry_language = array_keys($entry_language);
|
$entry_language = $lang->detect($entry_title . " " . $entry_content, 1);
|
||||||
$entry_language = db_escape_string(substr($entry_language[0], 0, 2));
|
|
||||||
|
|
||||||
_debug("detected language: $entry_language", $debug_enabled);
|
if (count($entry_language) > 0) {
|
||||||
} else{
|
$possible = array_keys($entry_language);
|
||||||
$entry_language = "";
|
$entry_language = $possible[0];
|
||||||
|
|
||||||
|
_debug("detected language: $entry_language", $debug_enabled);
|
||||||
|
} else {
|
||||||
|
$entry_language = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$entry_comments = $item->get_comments_url();
|
$entry_comments = $item->get_comments_url();
|
||||||
|
@ -618,24 +665,15 @@
|
||||||
|
|
||||||
_debug("done collecting data.", $debug_enabled);
|
_debug("done collecting data.", $debug_enabled);
|
||||||
|
|
||||||
// TODO: less memory-hungry implementation
|
$result = db_query("SELECT id, content_hash FROM ttrss_entries
|
||||||
|
WHERE guid = '".db_escape_string($entry_guid)."' OR guid = '$entry_guid_hashed'");
|
||||||
_debug("applying plugin filters..", $debug_enabled);
|
|
||||||
|
|
||||||
// FIXME not sure if owner_uid is a good idea here, we may have a base entry without user entry (?)
|
|
||||||
$result = db_query("SELECT plugin_data,title,content,link,tag_cache,author FROM ttrss_entries, ttrss_user_entries
|
|
||||||
WHERE ref_id = id AND (guid = '".db_escape_string($entry_guid)."' OR guid = '$entry_guid_hashed') AND owner_uid = $owner_uid");
|
|
||||||
|
|
||||||
if (db_num_rows($result) != 0) {
|
if (db_num_rows($result) != 0) {
|
||||||
$entry_plugin_data = db_fetch_result($result, 0, "plugin_data");
|
$base_entry_id = db_fetch_result($result, 0, "id");
|
||||||
$stored_article = array("title" => db_fetch_result($result, 0, "title"),
|
$entry_stored_hash = db_fetch_result($result, 0, "content_hash");
|
||||||
"content" => db_fetch_result($result, 0, "content"),
|
|
||||||
"link" => db_fetch_result($result, 0, "link"),
|
|
||||||
"tags" => explode(",", db_fetch_result($result, 0, "tag_cache")),
|
|
||||||
"author" => db_fetch_result($result, 0, "author"));
|
|
||||||
} else {
|
} else {
|
||||||
$entry_plugin_data = "";
|
$base_entry_id = false;
|
||||||
$stored_article = array();
|
$entry_stored_hash = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
$article = array("owner_uid" => $owner_uid, // read only
|
$article = array("owner_uid" => $owner_uid, // read only
|
||||||
|
@ -644,36 +682,63 @@
|
||||||
"content" => $entry_content,
|
"content" => $entry_content,
|
||||||
"link" => $entry_link,
|
"link" => $entry_link,
|
||||||
"tags" => $entry_tags,
|
"tags" => $entry_tags,
|
||||||
"plugin_data" => $entry_plugin_data,
|
|
||||||
"author" => $entry_author,
|
"author" => $entry_author,
|
||||||
"stored" => $stored_article,
|
"language" => $entry_language, // read only
|
||||||
"feed" => array("id" => $feed,
|
"feed" => array("id" => $feed,
|
||||||
"fetch_url" => $fetch_url,
|
"fetch_url" => $fetch_url,
|
||||||
"site_url" => $site_url)
|
"site_url" => $site_url)
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($pluginhost->get_hooks(PluginHost::HOOK_ARTICLE_FILTER) as $plugin) {
|
$entry_plugin_data = "";
|
||||||
$article = $plugin->hook_article_filter($article);
|
$entry_current_hash = calculate_article_hash($article, $pluginhost);
|
||||||
|
|
||||||
|
_debug("article hash: $entry_current_hash [stored=$entry_stored_hash]", $debug_enabled);
|
||||||
|
|
||||||
|
if ($entry_current_hash == $entry_stored_hash && !isset($_REQUEST["force_rehash"])) {
|
||||||
|
_debug("stored article seems up to date [IID: $base_entry_id], updating timestamp only", $debug_enabled);
|
||||||
|
|
||||||
|
// we keep encountering the entry in feeds, so we need to
|
||||||
|
// update date_updated column so that we don't get horrible
|
||||||
|
// dupes when the entry gets purged and reinserted again e.g.
|
||||||
|
// in the case of SLOW SLOW OMG SLOW updating feeds
|
||||||
|
|
||||||
|
$base_entry_id = db_fetch_result($result, 0, "id");
|
||||||
|
|
||||||
|
db_query("UPDATE ttrss_entries SET date_updated = NOW()
|
||||||
|
WHERE id = '$base_entry_id'");
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_debug("hash differs, applying plugin filters:", $debug_enabled);
|
||||||
|
|
||||||
|
foreach ($pluginhost->get_hooks(PluginHost::HOOK_ARTICLE_FILTER) as $plugin) {
|
||||||
|
_debug("... " . get_class($plugin), $debug_enabled);
|
||||||
|
|
||||||
|
$start = microtime(true);
|
||||||
|
$article = $plugin->hook_article_filter($article);
|
||||||
|
|
||||||
|
_debug("=== " . sprintf("%.4f (sec)", microtime(true) - $start), $debug_enabled);
|
||||||
|
|
||||||
|
$entry_plugin_data .= mb_strtolower(get_class($plugin)) . ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry_plugin_data = db_escape_string($entry_plugin_data);
|
||||||
|
|
||||||
|
_debug("plugin data: $entry_plugin_data", $debug_enabled);
|
||||||
|
|
||||||
$entry_tags = $article["tags"];
|
$entry_tags = $article["tags"];
|
||||||
$entry_guid = db_escape_string($entry_guid);
|
$entry_guid = db_escape_string($entry_guid);
|
||||||
$entry_title = db_escape_string($article["title"]);
|
$entry_title = db_escape_string($article["title"]);
|
||||||
$entry_author = db_escape_string($article["author"]);
|
$entry_author = db_escape_string($article["author"]);
|
||||||
$entry_link = db_escape_string($article["link"]);
|
$entry_link = db_escape_string($article["link"]);
|
||||||
$entry_plugin_data = db_escape_string($article["plugin_data"]);
|
|
||||||
$entry_content = $article["content"]; // escaped below
|
$entry_content = $article["content"]; // escaped below
|
||||||
|
|
||||||
|
|
||||||
_debug("plugin data: $entry_plugin_data", $debug_enabled);
|
|
||||||
|
|
||||||
if ($cache_images && is_writable(CACHE_DIR . '/images'))
|
if ($cache_images && is_writable(CACHE_DIR . '/images'))
|
||||||
cache_images($entry_content, $site_url, $debug_enabled);
|
cache_images($entry_content, $site_url, $debug_enabled);
|
||||||
|
|
||||||
$entry_content = db_escape_string($entry_content, false);
|
$entry_content = db_escape_string($entry_content, false);
|
||||||
|
|
||||||
$content_hash = "SHA1:" . sha1($entry_content);
|
|
||||||
|
|
||||||
db_query("BEGIN");
|
db_query("BEGIN");
|
||||||
|
|
||||||
$result = db_query("SELECT id FROM ttrss_entries
|
$result = db_query("SELECT id FROM ttrss_entries
|
||||||
|
@ -707,8 +772,8 @@
|
||||||
'$entry_link',
|
'$entry_link',
|
||||||
'$entry_timestamp_fmt',
|
'$entry_timestamp_fmt',
|
||||||
'$entry_content',
|
'$entry_content',
|
||||||
'$content_hash',
|
'$entry_current_hash',
|
||||||
$no_orig_date,
|
false,
|
||||||
NOW(),
|
NOW(),
|
||||||
'$date_feed_processed',
|
'$date_feed_processed',
|
||||||
'$entry_comments',
|
'$entry_comments',
|
||||||
|
@ -720,28 +785,14 @@
|
||||||
$article_labels = array();
|
$article_labels = array();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// we keep encountering the entry in feeds, so we need to
|
|
||||||
// update date_updated column so that we don't get horrible
|
|
||||||
// dupes when the entry gets purged and reinserted again e.g.
|
|
||||||
// in the case of SLOW SLOW OMG SLOW updating feeds
|
|
||||||
|
|
||||||
$base_entry_id = db_fetch_result($result, 0, "id");
|
$base_entry_id = db_fetch_result($result, 0, "id");
|
||||||
|
|
||||||
db_query("UPDATE ttrss_entries SET date_updated = NOW()
|
|
||||||
WHERE id = '$base_entry_id'");
|
|
||||||
|
|
||||||
$article_labels = get_article_labels($base_entry_id, $owner_uid);
|
$article_labels = get_article_labels($base_entry_id, $owner_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now it should exist, if not - bad luck then
|
// now it should exist, if not - bad luck then
|
||||||
|
|
||||||
$result = db_query("SELECT
|
$result = db_query("SELECT id FROM ttrss_entries
|
||||||
id,content_hash,no_orig_date,title,plugin_data,guid,
|
|
||||||
".SUBSTRING_FOR_DATE."(date_updated,1,19) as date_updated,
|
|
||||||
".SUBSTRING_FOR_DATE."(updated,1,19) as updated,
|
|
||||||
num_comments
|
|
||||||
FROM
|
|
||||||
ttrss_entries
|
|
||||||
WHERE guid = '$entry_guid' OR guid = '$entry_guid_hashed'");
|
WHERE guid = '$entry_guid' OR guid = '$entry_guid_hashed'");
|
||||||
|
|
||||||
$entry_ref_id = 0;
|
$entry_ref_id = 0;
|
||||||
|
@ -751,14 +802,6 @@
|
||||||
|
|
||||||
_debug("base guid found, checking for user record", $debug_enabled);
|
_debug("base guid found, checking for user record", $debug_enabled);
|
||||||
|
|
||||||
// this will be used below in update handler
|
|
||||||
$orig_content_hash = db_fetch_result($result, 0, "content_hash");
|
|
||||||
$orig_title = db_fetch_result($result, 0, "title");
|
|
||||||
$orig_num_comments = db_fetch_result($result, 0, "num_comments");
|
|
||||||
$orig_date_updated = strtotime(db_fetch_result($result,
|
|
||||||
0, "date_updated"));
|
|
||||||
$orig_plugin_data = db_fetch_result($result, 0, "plugin_data");
|
|
||||||
|
|
||||||
$ref_id = db_fetch_result($result, 0, "id");
|
$ref_id = db_fetch_result($result, 0, "id");
|
||||||
$entry_ref_id = $ref_id;
|
$entry_ref_id = $ref_id;
|
||||||
|
|
||||||
|
@ -872,7 +915,7 @@
|
||||||
|
|
||||||
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
$p = new Publisher(PUBSUBHUBBUB_HUB);
|
||||||
|
|
||||||
$pubsub_result = $p->publish_update($rss_link);
|
/* $pubsub_result = */ $p->publish_update($rss_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = db_query(
|
$result = db_query(
|
||||||
|
@ -892,53 +935,20 @@
|
||||||
|
|
||||||
_debug("RID: $entry_ref_id, IID: $entry_int_id", $debug_enabled);
|
_debug("RID: $entry_ref_id, IID: $entry_int_id", $debug_enabled);
|
||||||
|
|
||||||
$post_needs_update = false;
|
db_query("UPDATE ttrss_entries
|
||||||
$update_insignificant = false;
|
SET title = '$entry_title',
|
||||||
|
content = '$entry_content',
|
||||||
|
content_hash = '$entry_current_hash',
|
||||||
|
updated = '$entry_timestamp_fmt',
|
||||||
|
num_comments = '$num_comments',
|
||||||
|
plugin_data = '$entry_plugin_data',
|
||||||
|
author = '$entry_author',
|
||||||
|
lang = '$entry_language'
|
||||||
|
WHERE id = '$ref_id'");
|
||||||
|
|
||||||
if ($orig_num_comments != $num_comments) {
|
if ($mark_unread_on_update) {
|
||||||
$post_needs_update = true;
|
db_query("UPDATE ttrss_user_entries
|
||||||
$update_insignificant = true;
|
SET last_read = null, unread = true WHERE ref_id = '$ref_id'");
|
||||||
}
|
|
||||||
|
|
||||||
if ($entry_plugin_data != $orig_plugin_data) {
|
|
||||||
$post_needs_update = true;
|
|
||||||
$update_insignificant = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($content_hash != $orig_content_hash) {
|
|
||||||
$post_needs_update = true;
|
|
||||||
$update_insignificant = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db_escape_string($orig_title) != $entry_title) {
|
|
||||||
$post_needs_update = true;
|
|
||||||
$update_insignificant = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if post needs update, update it and mark all user entries
|
|
||||||
// linking to this post as updated
|
|
||||||
if ($post_needs_update) {
|
|
||||||
|
|
||||||
if (defined('DAEMON_EXTENDED_DEBUG')) {
|
|
||||||
_debug("post $entry_guid_hashed needs update...", $debug_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// print "<!-- post $orig_title needs update : $post_needs_update -->";
|
|
||||||
|
|
||||||
db_query("UPDATE ttrss_entries
|
|
||||||
SET title = '$entry_title', content = '$entry_content',
|
|
||||||
content_hash = '$content_hash',
|
|
||||||
updated = '$entry_timestamp_fmt',
|
|
||||||
num_comments = '$num_comments',
|
|
||||||
plugin_data = '$entry_plugin_data'
|
|
||||||
WHERE id = '$ref_id'");
|
|
||||||
|
|
||||||
if (!$update_insignificant) {
|
|
||||||
if ($mark_unread_on_update) {
|
|
||||||
db_query("UPDATE ttrss_user_entries
|
|
||||||
SET last_read = null, unread = true WHERE ref_id = '$ref_id'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +970,7 @@
|
||||||
if (is_array($encs)) {
|
if (is_array($encs)) {
|
||||||
foreach ($encs as $e) {
|
foreach ($encs as $e) {
|
||||||
$e_item = array(
|
$e_item = array(
|
||||||
$e->link, $e->type, $e->length, $e->title);
|
$e->link, $e->type, $e->length, $e->title, $e->width, $e->height);
|
||||||
array_push($enclosures, $e_item);
|
array_push($enclosures, $e_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -980,14 +990,16 @@
|
||||||
$enc_type = db_escape_string($enc[1]);
|
$enc_type = db_escape_string($enc[1]);
|
||||||
$enc_dur = db_escape_string($enc[2]);
|
$enc_dur = db_escape_string($enc[2]);
|
||||||
$enc_title = db_escape_string($enc[3]);
|
$enc_title = db_escape_string($enc[3]);
|
||||||
|
$enc_width = intval($enc[4]);
|
||||||
|
$enc_height = intval($enc[5]);
|
||||||
|
|
||||||
$result = db_query("SELECT id FROM ttrss_enclosures
|
$result = db_query("SELECT id FROM ttrss_enclosures
|
||||||
WHERE content_url = '$enc_url' AND post_id = '$entry_ref_id'");
|
WHERE content_url = '$enc_url' AND post_id = '$entry_ref_id'");
|
||||||
|
|
||||||
if (db_num_rows($result) == 0) {
|
if (db_num_rows($result) == 0) {
|
||||||
db_query("INSERT INTO ttrss_enclosures
|
db_query("INSERT INTO ttrss_enclosures
|
||||||
(content_url, content_type, title, duration, post_id) VALUES
|
(content_url, content_type, title, duration, post_id, width, height) VALUES
|
||||||
('$enc_url', '$enc_type', '$enc_title', '$enc_dur', '$entry_ref_id')");
|
('$enc_url', '$enc_type', '$enc_title', '$enc_dur', '$entry_ref_id', $enc_width, $enc_height)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,21 +1113,27 @@
|
||||||
|
|
||||||
$error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
|
$error_msg = db_escape_string(mb_substr($rss->error(), 0, 245));
|
||||||
|
|
||||||
_debug("error fetching feed: $error_msg", $debug_enabled);
|
_debug("fetch error: $error_msg", $debug_enabled);
|
||||||
|
|
||||||
|
if (count($rss->errors()) > 1) {
|
||||||
|
foreach ($rss->errors() as $error) {
|
||||||
|
_debug("+ $error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db_query(
|
db_query(
|
||||||
"UPDATE ttrss_feeds SET last_error = '$error_msg',
|
"UPDATE ttrss_feeds SET last_error = '$error_msg',
|
||||||
last_updated = NOW() WHERE id = '$feed'");
|
last_updated = NOW() WHERE id = '$feed'");
|
||||||
|
|
||||||
|
unset($rss);
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($rss);
|
|
||||||
|
|
||||||
_debug("done", $debug_enabled);
|
_debug("done", $debug_enabled);
|
||||||
|
|
||||||
|
return $rss;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cache_images($html, $site_url, $debug) {
|
function cache_images($html, $site_url, $debug) {
|
||||||
$cache_dir = CACHE_DIR . "/images";
|
|
||||||
|
|
||||||
libxml_use_internal_errors(true);
|
libxml_use_internal_errors(true);
|
||||||
|
|
||||||
$charset_hack = '<head>
|
$charset_hack = '<head>
|
||||||
|
@ -1139,7 +1157,7 @@
|
||||||
if (!file_exists($local_filename)) {
|
if (!file_exists($local_filename)) {
|
||||||
$file_content = fetch_file_contents($src);
|
$file_content = fetch_file_contents($src);
|
||||||
|
|
||||||
if ($file_content && strlen($file_content) > 1024) {
|
if ($file_content && strlen($file_content) > _MIN_CACHE_IMAGE_SIZE) {
|
||||||
file_put_contents($local_filename, $file_content);
|
file_put_contents($local_filename, $file_content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,11 +146,6 @@
|
||||||
array_push($errors, "PHP support for CURL is required for PubSubHubbub.");
|
array_push($errors, "PHP support for CURL is required for PubSubHubbub.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPHINX_ENABLED && class_exists("SphinxClient")) {
|
|
||||||
array_push($errors, "Your PHP has a separate systemwide Sphinx client installed which conflicts with the client library used by tt-rss. Either remove the system library or disable Sphinx support.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists("DOMDocument")) {
|
if (!class_exists("DOMDocument")) {
|
||||||
array_push($errors, "PHP support for DOMDocument is required, but was not found.");
|
array_push($errors, "PHP support for DOMDocument is required, but was not found.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<?php # This file has been generated at: Thu May 30 08:39:20 MSK 2013
|
<?php # This file has been generated at: Fri Sep 27 13:42:37 MSK 2013
|
||||||
define('GENERATED_CONFIG_CHECK', 26);
|
define('GENERATED_CONFIG_CHECK', 26);
|
||||||
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'FEED_CRYPT_KEY', 'SINGLE_USER_MODE', 'SIMPLE_UPDATE_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'SPHINX_ENABLED', 'SPHINX_SERVER', 'SPHINX_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_SERVER', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'SMTP_SECURE', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'LOG_DESTINATION', 'CONFIG_VERSION'); ?>
|
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'FEED_CRYPT_KEY', 'SINGLE_USER_MODE', 'SIMPLE_UPDATE_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_SERVER', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'SMTP_SECURE', 'CHECK_FOR_NEW_VERSION', 'DETECT_ARTICLE_LANGUAGE', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'LOG_DESTINATION', 'CONFIG_VERSION'); ?>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
define('VERSION_STATIC', '1.10');
|
define('VERSION_STATIC', '1.14');
|
||||||
|
|
||||||
function get_version() {
|
function get_version() {
|
||||||
date_default_timezone_set('UTC');
|
date_default_timezone_set('UTC');
|
||||||
|
|
|
@ -56,15 +56,19 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Tiny Tiny RSS</title>
|
<title>Tiny Tiny RSS</title>
|
||||||
|
|
||||||
<?php stylesheet_tag("lib/dijit/themes/claro/claro.css"); ?>
|
<script type="text/javascript">
|
||||||
<?php stylesheet_tag("css/layout.css"); ?>
|
var __ttrss_version = "<?php echo VERSION ?>"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php echo stylesheet_tag("lib/dijit/themes/claro/claro.css"); ?>
|
||||||
|
<?php echo stylesheet_tag("css/layout.css"); ?>
|
||||||
|
|
||||||
<?php if ($_SESSION["uid"]) {
|
<?php if ($_SESSION["uid"]) {
|
||||||
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
|
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
|
||||||
if ($theme && file_exists("themes/$theme")) {
|
if ($theme && file_exists("themes/$theme")) {
|
||||||
stylesheet_tag("themes/$theme");
|
echo stylesheet_tag("themes/$theme");
|
||||||
} else {
|
} else {
|
||||||
stylesheet_tag("themes/default.css");
|
echo stylesheet_tag("themes/default.css");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -86,12 +90,12 @@
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
foreach (array("lib/prototype.js",
|
foreach (array("lib/prototype.js",
|
||||||
"lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls",
|
"lib/scriptaculous/scriptaculous.js?load=effects,controls",
|
||||||
"lib/dojo/dojo.js",
|
"lib/dojo/dojo.js",
|
||||||
"lib/dojo/tt-rss-layer.js",
|
"lib/dojo/tt-rss-layer.js",
|
||||||
"errors.php?mode=js") as $jsfile) {
|
"errors.php?mode=js") as $jsfile) {
|
||||||
|
|
||||||
javascript_tag($jsfile);
|
echo javascript_tag($jsfile);
|
||||||
|
|
||||||
} ?>
|
} ?>
|
||||||
|
|
||||||
|
@ -153,6 +157,10 @@
|
||||||
<div id="toolbar" dojoType="dijit.layout.ContentPane" region="top">
|
<div id="toolbar" dojoType="dijit.layout.ContentPane" region="top">
|
||||||
<div id="main-toolbar" dojoType="dijit.Toolbar">
|
<div id="main-toolbar" dojoType="dijit.Toolbar">
|
||||||
|
|
||||||
|
<form id="headlines-toolbar" action="" onsubmit='return false'>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
<form id="main_toolbar_form" action="" onsubmit='return false'>
|
<form id="main_toolbar_form" action="" onsubmit='return false'>
|
||||||
|
|
||||||
<button dojoType="dijit.form.Button" id="collapse_feeds_btn"
|
<button dojoType="dijit.form.Button" id="collapse_feeds_btn"
|
||||||
|
@ -257,9 +265,6 @@
|
||||||
|
|
||||||
<div id="headlines-wrap-inner" dojoType="dijit.layout.BorderContainer" region="center">
|
<div id="headlines-wrap-inner" dojoType="dijit.layout.BorderContainer" region="center">
|
||||||
|
|
||||||
<div id="headlines-toolbar" dojoType="dijit.layout.ContentPane" region="top">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="floatingTitle" style="display : none"></div>
|
<div id="floatingTitle" style="display : none"></div>
|
||||||
|
|
||||||
<div id="headlines-frame" dojoType="dijit.layout.ContentPane"
|
<div id="headlines-frame" dojoType="dijit.layout.ContentPane"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<title>Tiny Tiny RSS - Installer</title>
|
<title>Tiny Tiny RSS - Installer</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="../css/utility.css">
|
<link rel="stylesheet" type="text/css" href="../css/utility.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="../css/dijit.css">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
textarea { font-size : 12px; }
|
textarea { font-size : 12px; }
|
||||||
</style>
|
</style>
|
||||||
|
@ -10,6 +11,12 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
// could be needed because of existing config.php
|
||||||
|
function define_default($param, $value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
function make_password($length = 8) {
|
function make_password($length = 8) {
|
||||||
|
|
||||||
$password = "";
|
$password = "";
|
||||||
|
@ -263,7 +270,7 @@
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label>Password</label>
|
<label>Password</label>
|
||||||
<input required name="DB_PASS" size="20" type="password" value="<?php echo $DB_PASS ?>"/>
|
<input name="DB_PASS" size="20" type="password" value="<?php echo $DB_PASS ?>"/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
|
|
@ -58,12 +58,12 @@ dojo.declare("fox.FeedStoreModel", dijit.tree.ForestStoreModel, {
|
||||||
|
|
||||||
if (is_cat) {
|
if (is_cat) {
|
||||||
treeItem = this.store._itemsByIdentity['CAT:' + feed];
|
treeItem = this.store._itemsByIdentity['CAT:' + feed];
|
||||||
items = this.store._arrayOfTopLevelItems;
|
|
||||||
} else {
|
} else {
|
||||||
treeItem = this.store._itemsByIdentity['FEED:' + feed];
|
treeItem = this.store._itemsByIdentity['FEED:' + feed];
|
||||||
items = this.store._arrayOfAllItems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
items = this.store._arrayOfAllItems;
|
||||||
|
|
||||||
for (var i = 0; i < items.length; i++) {
|
for (var i = 0; i < items.length; i++) {
|
||||||
if (items[i] == treeItem) {
|
if (items[i] == treeItem) {
|
||||||
|
|
||||||
|
@ -71,14 +71,18 @@ dojo.declare("fox.FeedStoreModel", dijit.tree.ForestStoreModel, {
|
||||||
var unread = this.store.getValue(items[j], 'unread');
|
var unread = this.store.getValue(items[j], 'unread');
|
||||||
var id = this.store.getValue(items[j], 'id');
|
var id = this.store.getValue(items[j], 'id');
|
||||||
|
|
||||||
if (unread > 0 && (is_cat || id.match("FEED:"))) return items[j];
|
if (unread > 0 && ((is_cat && id.match("CAT:")) || (!is_cat && id.match("FEED:")))) {
|
||||||
|
if( !is_cat || ! (this.store.hasAttribute(items[j], 'parent_id') && this.store.getValue(items[j], 'parent_id') == feed) ) return items[j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var j = 0; j < i; j++) {
|
for (var j = 0; j < i; j++) {
|
||||||
var unread = this.store.getValue(items[j], 'unread');
|
var unread = this.store.getValue(items[j], 'unread');
|
||||||
var id = this.store.getValue(items[j], 'id');
|
var id = this.store.getValue(items[j], 'id');
|
||||||
|
|
||||||
if (unread > 0 && (is_cat || id.match("FEED:"))) return items[j];
|
if (unread > 0 && ((is_cat && id.match("CAT:")) || (!is_cat && id.match("FEED:")))) {
|
||||||
|
if( !is_cat || ! (this.store.hasAttribute(items[j], 'parent_id') && this.store.getValue(items[j], 'parent_id') == feed) ) return items[j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,7 +543,7 @@ dojo.declare("fox.FeedTree", dijit.Tree, {
|
||||||
}
|
}
|
||||||
|
|
||||||
items = this.model.store._arrayOfAllItems;
|
items = this.model.store._arrayOfAllItems;
|
||||||
var item = items[0];
|
var item = items[0] == treeItem ? items[items.length-1] : items[0];
|
||||||
|
|
||||||
for (var i = 0; i < items.length; i++) {
|
for (var i = 0; i < items.length; i++) {
|
||||||
if (items[i] == treeItem) {
|
if (items[i] == treeItem) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ dojo.declare("fox.PrefFilterTree", lib.CheckBoxTree, {
|
||||||
|
|
||||||
var enabled = this.model.store.getValue(args.item, 'enabled');
|
var enabled = this.model.store.getValue(args.item, 'enabled');
|
||||||
var param = this.model.store.getValue(args.item, 'param');
|
var param = this.model.store.getValue(args.item, 'param');
|
||||||
|
var rules = this.model.store.getValue(args.item, 'rules');
|
||||||
|
|
||||||
if (param) {
|
if (param) {
|
||||||
param = dojo.doc.createElement('span');
|
param = dojo.doc.createElement('span');
|
||||||
|
@ -32,6 +33,13 @@ dojo.declare("fox.PrefFilterTree", lib.CheckBoxTree, {
|
||||||
dojo.place(param, tnode.rowNode, 'first');
|
dojo.place(param, tnode.rowNode, 'first');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rules) {
|
||||||
|
param = dojo.doc.createElement('span');
|
||||||
|
param.className = 'filterRules';
|
||||||
|
param.innerHTML = rules;
|
||||||
|
dojo.place(param, tnode.rowNode, 'next');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.model.store.getValue(args.item, 'id') != 'root') {
|
if (this.model.store.getValue(args.item, 'id') != 'root') {
|
||||||
var img = dojo.doc.createElement('img');
|
var img = dojo.doc.createElement('img');
|
||||||
img.src ='images/filter.png';
|
img.src ='images/filter.png';
|
||||||
|
|
|
@ -44,11 +44,8 @@ function exception_error(location, e, ext_info) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (ext_info) {
|
if (ext_info)
|
||||||
if (ext_info.responseText) {
|
ext_info = JSON.stringify(ext_info);
|
||||||
ext_info = ext_info.responseText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
new Ajax.Request("backend.php", {
|
new Ajax.Request("backend.php", {
|
||||||
|
@ -104,13 +101,15 @@ function exception_error(location, e, ext_info) {
|
||||||
title: "Unhandled exception",
|
title: "Unhandled exception",
|
||||||
style: "width: 600px",
|
style: "width: 600px",
|
||||||
report: function() {
|
report: function() {
|
||||||
if (confirm(__("Are you sure to report this exception to tt-rss.org? The report will include your browser information. Your IP would be saved in the database."))) {
|
if (confirm(__("Are you sure to report this exception to tt-rss.org? The report will include information about your web browser and tt-rss configuration. Your IP will be saved in the database."))) {
|
||||||
|
|
||||||
document.forms['exceptionForm'].params.value = $H({
|
document.forms['exceptionForm'].params.value = $H({
|
||||||
browserName: navigator.appName,
|
browserName: navigator.appName,
|
||||||
browserVersion: navigator.appVersion,
|
browserVersion: navigator.appVersion,
|
||||||
browserPlatform: navigator.platform,
|
browserPlatform: navigator.platform,
|
||||||
browserCookies: navigator.cookieEnabled,
|
browserCookies: navigator.cookieEnabled,
|
||||||
|
ttrssVersion: __ttrss_version,
|
||||||
|
initParams: JSON.stringify(init_params),
|
||||||
}).toQueryString();
|
}).toQueryString();
|
||||||
|
|
||||||
document.forms['exceptionForm'].submit();
|
document.forms['exceptionForm'].submit();
|
||||||
|
@ -205,6 +204,7 @@ function notify_real(msg, no_hide, n_type) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Element.show(n);
|
Element.show(n);
|
||||||
|
new Effect.Highlight(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* types:
|
/* types:
|
||||||
|
@ -829,7 +829,14 @@ function quickAddFeed() {
|
||||||
onComplete: function(transport) {
|
onComplete: function(transport) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var reply = JSON.parse(transport.responseText);
|
try {
|
||||||
|
var reply = JSON.parse(transport.responseText);
|
||||||
|
} catch (e) {
|
||||||
|
Element.hide("feed_add_spinner");
|
||||||
|
alert(__("Failed to parse output. This can indicate server timeout and/or network issues. Backend output was logged to browser console."));
|
||||||
|
console.log('quickAddFeed, backend returned:' + transport.responseText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var rc = reply['result'];
|
var rc = reply['result'];
|
||||||
|
|
||||||
|
@ -854,6 +861,8 @@ function quickAddFeed() {
|
||||||
case 4:
|
case 4:
|
||||||
feeds = rc['feeds'];
|
feeds = rc['feeds'];
|
||||||
|
|
||||||
|
Element.show("fadd_multiple_notify");
|
||||||
|
|
||||||
var select = dijit.byId("feedDlg_feedContainerSelect");
|
var select = dijit.byId("feedDlg_feedContainerSelect");
|
||||||
|
|
||||||
while (select.getOptions().length > 0)
|
while (select.getOptions().length > 0)
|
||||||
|
@ -1148,33 +1157,48 @@ function quickAddFilter() {
|
||||||
href: query});
|
href: query});
|
||||||
|
|
||||||
if (!inPreferences()) {
|
if (!inPreferences()) {
|
||||||
|
var selectedText = getSelectionText();
|
||||||
|
|
||||||
var lh = dojo.connect(dialog, "onLoad", function(){
|
var lh = dojo.connect(dialog, "onLoad", function(){
|
||||||
dojo.disconnect(lh);
|
dojo.disconnect(lh);
|
||||||
|
|
||||||
var query = "op=rpc&method=getlinktitlebyid&id=" + getActiveArticleId();
|
if (selectedText != "") {
|
||||||
|
|
||||||
new Ajax.Request("backend.php", {
|
var feed_id = activeFeedIsCat() ? 'CAT:' + parseInt(getActiveFeedId()) :
|
||||||
parameters: query,
|
getActiveFeedId();
|
||||||
onComplete: function(transport) {
|
|
||||||
var reply = JSON.parse(transport.responseText);
|
|
||||||
|
|
||||||
var title = false;
|
var rule = { reg_exp: selectedText, feed_id: feed_id, filter_type: 1 };
|
||||||
|
|
||||||
if (reply && reply) title = reply.title;
|
addFilterRule(null, dojo.toJson(rule));
|
||||||
|
|
||||||
if (title || getActiveFeedId() || activeFeedIsCat()) {
|
} else {
|
||||||
|
|
||||||
console.log(title + " " + getActiveFeedId());
|
var query = "op=rpc&method=getlinktitlebyid&id=" + getActiveArticleId();
|
||||||
|
|
||||||
var feed_id = activeFeedIsCat() ? 'CAT:' + parseInt(getActiveFeedId()) :
|
new Ajax.Request("backend.php", {
|
||||||
getActiveFeedId();
|
parameters: query,
|
||||||
|
onComplete: function(transport) {
|
||||||
|
var reply = JSON.parse(transport.responseText);
|
||||||
|
|
||||||
var rule = { reg_exp: title, feed_id: feed_id, filter_type: 1 };
|
var title = false;
|
||||||
|
|
||||||
addFilterRule(null, dojo.toJson(rule));
|
if (reply && reply) title = reply.title;
|
||||||
}
|
|
||||||
|
|
||||||
} });
|
if (title || getActiveFeedId() || activeFeedIsCat()) {
|
||||||
|
|
||||||
|
console.log(title + " " + getActiveFeedId());
|
||||||
|
|
||||||
|
var feed_id = activeFeedIsCat() ? 'CAT:' + parseInt(getActiveFeedId()) :
|
||||||
|
getActiveFeedId();
|
||||||
|
|
||||||
|
var rule = { reg_exp: title, feed_id: feed_id, filter_type: 1 };
|
||||||
|
|
||||||
|
addFilterRule(null, dojo.toJson(rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
} });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1270,10 +1294,8 @@ function backend_sanity_check_callback(transport) {
|
||||||
console.log('reading init-params...');
|
console.log('reading init-params...');
|
||||||
|
|
||||||
for (k in params) {
|
for (k in params) {
|
||||||
var v = params[k];
|
console.log("IP: " + k + " => " + JSON.stringify(params[k]));
|
||||||
console.log("IP: " + k + " => " + v);
|
if (k == "label_base_index") _label_base_index = parseInt(params[k]);
|
||||||
|
|
||||||
if (k == "label_base_index") _label_base_index = parseInt(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_params = params;
|
init_params = params;
|
||||||
|
@ -1934,3 +1956,25 @@ function feed_to_label_id(feed) {
|
||||||
return _label_base_index - 1 + Math.abs(feed);
|
return _label_base_index - 1 + Math.abs(feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/6251937/how-to-get-selecteduser-highlighted-text-in-contenteditable-element-and-replac
|
||||||
|
|
||||||
|
function getSelectionText() {
|
||||||
|
var text = "";
|
||||||
|
|
||||||
|
if (typeof window.getSelection != "undefined") {
|
||||||
|
var sel = window.getSelection();
|
||||||
|
if (sel.rangeCount) {
|
||||||
|
var container = document.createElement("div");
|
||||||
|
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
|
||||||
|
container.appendChild(sel.getRangeAt(i).cloneContents());
|
||||||
|
}
|
||||||
|
text = container.innerHTML;
|
||||||
|
}
|
||||||
|
} else if (typeof document.selection != "undefined") {
|
||||||
|
if (document.selection.type == "Text") {
|
||||||
|
text = document.selection.createRange().textText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.stripTags();
|
||||||
|
}
|
||||||
|
|
|
@ -231,6 +231,7 @@ function init() {
|
||||||
dojo.require("dijit.form.Select");
|
dojo.require("dijit.form.Select");
|
||||||
dojo.require("dijit.form.SimpleTextarea");
|
dojo.require("dijit.form.SimpleTextarea");
|
||||||
dojo.require("dijit.form.TextBox");
|
dojo.require("dijit.form.TextBox");
|
||||||
|
dojo.require("dijit.form.ComboBox");
|
||||||
dojo.require("dijit.form.ValidationTextBox");
|
dojo.require("dijit.form.ValidationTextBox");
|
||||||
dojo.require("dijit.InlineEditBox");
|
dojo.require("dijit.InlineEditBox");
|
||||||
dojo.require("dijit.layout.AccordionContainer");
|
dojo.require("dijit.layout.AccordionContainer");
|
||||||
|
@ -500,6 +501,10 @@ function init() {
|
||||||
if (!isCdmMode()) {
|
if (!isCdmMode()) {
|
||||||
_widescreen_mode = !_widescreen_mode;
|
_widescreen_mode = !_widescreen_mode;
|
||||||
|
|
||||||
|
// reset stored sizes because geometry changed
|
||||||
|
setCookie("ttrss_ci_width", 0);
|
||||||
|
setCookie("ttrss_ci_height", 0);
|
||||||
|
|
||||||
switchPanelMode(_widescreen_mode);
|
switchPanelMode(_widescreen_mode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -550,25 +555,11 @@ function init_second_stage() {
|
||||||
updateFeedList();
|
updateFeedList();
|
||||||
closeArticlePanel();
|
closeArticlePanel();
|
||||||
|
|
||||||
_widescreen_mode = getInitParam("widescreen");
|
|
||||||
switchPanelMode(_widescreen_mode);
|
|
||||||
|
|
||||||
if (parseInt(getCookie("ttrss_fh_width")) > 0) {
|
if (parseInt(getCookie("ttrss_fh_width")) > 0) {
|
||||||
dijit.byId("feeds-holder").domNode.setStyle(
|
dijit.byId("feeds-holder").domNode.setStyle(
|
||||||
{width: getCookie("ttrss_fh_width") + "px" });
|
{width: getCookie("ttrss_fh_width") + "px" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parseInt(getCookie("ttrss_ci_width")) > 0) {
|
|
||||||
if (_widescreen_mode) {
|
|
||||||
dijit.byId("content-insert").domNode.setStyle(
|
|
||||||
{width: getCookie("ttrss_ci_width") + "px" });
|
|
||||||
|
|
||||||
} else {
|
|
||||||
dijit.byId("content-insert").domNode.setStyle(
|
|
||||||
{height: getCookie("ttrss_ci_height") + "px" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dijit.byId("main").resize();
|
dijit.byId("main").resize();
|
||||||
|
|
||||||
var tmph = dojo.connect(dijit.byId('feeds-holder'), 'resize',
|
var tmph = dojo.connect(dijit.byId('feeds-holder'), 'resize',
|
||||||
|
@ -624,6 +615,9 @@ function init_second_stage() {
|
||||||
hotkeys[1] = tmp;
|
hotkeys[1] = tmp;
|
||||||
setInitParam("hotkeys", hotkeys);
|
setInitParam("hotkeys", hotkeys);
|
||||||
|
|
||||||
|
_widescreen_mode = getInitParam("widescreen");
|
||||||
|
switchPanelMode(_widescreen_mode);
|
||||||
|
|
||||||
console.log("second stage ok");
|
console.log("second stage ok");
|
||||||
|
|
||||||
if (getInitParam("simple_update")) {
|
if (getInitParam("simple_update")) {
|
||||||
|
@ -706,6 +700,10 @@ function quickMenuGo(opid) {
|
||||||
if (!isCdmMode()) {
|
if (!isCdmMode()) {
|
||||||
_widescreen_mode = !_widescreen_mode;
|
_widescreen_mode = !_widescreen_mode;
|
||||||
|
|
||||||
|
// reset stored sizes because geometry changed
|
||||||
|
setCookie("ttrss_ci_width", 0);
|
||||||
|
setCookie("ttrss_ci_height", 0);
|
||||||
|
|
||||||
switchPanelMode(_widescreen_mode);
|
switchPanelMode(_widescreen_mode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -989,6 +987,12 @@ function handle_rpc_json(transport, scheduled_call) {
|
||||||
try {
|
try {
|
||||||
var reply = JSON.parse(transport.responseText);
|
var reply = JSON.parse(transport.responseText);
|
||||||
|
|
||||||
|
var netalert_dijit = dijit.byId("net-alert");
|
||||||
|
var netalert = false;
|
||||||
|
|
||||||
|
if (netalert_dijit)
|
||||||
|
netalert = netalert_dijit.domNode;
|
||||||
|
|
||||||
if (reply) {
|
if (reply) {
|
||||||
|
|
||||||
var error = reply['error'];
|
var error = reply['error'];
|
||||||
|
@ -1035,16 +1039,21 @@ function handle_rpc_json(transport, scheduled_call) {
|
||||||
if (runtime_info)
|
if (runtime_info)
|
||||||
parse_runtime_info(runtime_info);
|
parse_runtime_info(runtime_info);
|
||||||
|
|
||||||
Element.hide(dijit.byId("net-alert").domNode);
|
if (netalert) Element.hide(netalert);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//notify_error("Error communicating with server.");
|
if (netalert)
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
Element.show(netalert);
|
||||||
|
else
|
||||||
|
notify_error("Communication problem with server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
if (netalert)
|
||||||
//notify_error("Error communicating with server.");
|
Element.show(netalert);
|
||||||
|
else
|
||||||
|
notify_error("Communication problem with server.");
|
||||||
|
|
||||||
console.log(e);
|
console.log(e);
|
||||||
//exception_error("handle_rpc_json", e, transport);
|
//exception_error("handle_rpc_json", e, transport);
|
||||||
}
|
}
|
||||||
|
@ -1064,11 +1073,13 @@ function switchPanelMode(wide) {
|
||||||
|
|
||||||
dijit.byId("content-insert").domNode.setStyle({width: '50%',
|
dijit.byId("content-insert").domNode.setStyle({width: '50%',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
borderLeftWidth: '1px',
|
|
||||||
borderLeftColor: '#c0c0c0',
|
|
||||||
borderTopWidth: '0px' });
|
borderTopWidth: '0px' });
|
||||||
|
|
||||||
$("headlines-toolbar").setStyle({ borderBottomWidth: '0px' });
|
if (parseInt(getCookie("ttrss_ci_width")) > 0) {
|
||||||
|
dijit.byId("content-insert").domNode.setStyle(
|
||||||
|
{width: getCookie("ttrss_ci_width") + "px" });
|
||||||
|
}
|
||||||
|
|
||||||
$("headlines-frame").setStyle({ borderBottomWidth: '0px' });
|
$("headlines-frame").setStyle({ borderBottomWidth: '0px' });
|
||||||
$("headlines-frame").addClassName("wide");
|
$("headlines-frame").addClassName("wide");
|
||||||
|
|
||||||
|
@ -1078,10 +1089,12 @@ function switchPanelMode(wide) {
|
||||||
|
|
||||||
dijit.byId("content-insert").domNode.setStyle({width: 'auto',
|
dijit.byId("content-insert").domNode.setStyle({width: 'auto',
|
||||||
height: '50%',
|
height: '50%',
|
||||||
borderLeftWidth: '0px',
|
borderTopWidth: '0px'});
|
||||||
borderTopWidth: '1px'});
|
|
||||||
|
|
||||||
$("headlines-toolbar").setStyle({ borderBottomWidth: '1px' });
|
if (parseInt(getCookie("ttrss_ci_height")) > 0) {
|
||||||
|
dijit.byId("content-insert").domNode.setStyle(
|
||||||
|
{height: getCookie("ttrss_ci_height") + "px" });
|
||||||
|
}
|
||||||
|
|
||||||
$("headlines-frame").setStyle({ borderBottomWidth: '1px' });
|
$("headlines-frame").setStyle({ borderBottomWidth: '1px' });
|
||||||
$("headlines-frame").removeClassName("wide");
|
$("headlines-frame").removeClassName("wide");
|
||||||
|
|
|
@ -87,8 +87,12 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
dijit.byId("headlines-frame").attr('content',
|
dijit.byId("headlines-frame").attr('content',
|
||||||
reply['headlines']['content']);
|
reply['headlines']['content']);
|
||||||
|
|
||||||
dijit.byId("headlines-toolbar").attr('content',
|
//dijit.byId("headlines-toolbar").attr('content',
|
||||||
reply['headlines']['toolbar']);
|
// reply['headlines']['toolbar']);
|
||||||
|
|
||||||
|
dojo.html.set($("headlines-toolbar"),
|
||||||
|
reply['headlines']['toolbar'],
|
||||||
|
{parseContent: true});
|
||||||
|
|
||||||
$$("#headlines-frame > div[id*=RROW]").each(function(row) {
|
$$("#headlines-frame > div[id*=RROW]").each(function(row) {
|
||||||
if (loaded_article_ids.indexOf(row.id) != -1) {
|
if (loaded_article_ids.indexOf(row.id) != -1) {
|
||||||
|
@ -104,6 +108,10 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
|
|
||||||
initHeadlinesMenu();
|
initHeadlinesMenu();
|
||||||
|
|
||||||
|
if (_infscroll_disable)
|
||||||
|
hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
|
||||||
|
__("Click to open next unread feed.") + "</a>";
|
||||||
|
|
||||||
if (_search_query) {
|
if (_search_query) {
|
||||||
$("feed_title").innerHTML += "<span id='cancel_search'>" +
|
$("feed_title").innerHTML += "<span id='cancel_search'>" +
|
||||||
" (<a href='#' onclick='cancelSearch()'>" + __("Cancel search") + "</a>)" +
|
" (<a href='#' onclick='cancelSearch()'>" + __("Cancel search") + "</a>)" +
|
||||||
|
@ -143,9 +151,9 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
|
|
||||||
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
|
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
|
||||||
|
|
||||||
if (getInitParam("cdm_auto_catchup") == 1) {
|
// if (getInitParam("cdm_auto_catchup") == 1) {
|
||||||
c.domNode.appendChild(hsp);
|
c.domNode.appendChild(hsp);
|
||||||
}
|
// }
|
||||||
|
|
||||||
console.log("added " + new_elems.size() + " headlines");
|
console.log("added " + new_elems.size() + " headlines");
|
||||||
|
|
||||||
|
@ -172,7 +180,8 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
|
|
||||||
var hsp = $("headlines-spacer");
|
var hsp = $("headlines-spacer");
|
||||||
|
|
||||||
if (hsp) hsp.innerHTML = "";
|
if (hsp) hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
|
||||||
|
__("Click to open next unread feed.") + "</a>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,14 +199,11 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
|
||||||
else
|
else
|
||||||
request_counters(true);
|
request_counters(true);
|
||||||
|
|
||||||
} else if (transport.responseText) {
|
} else {
|
||||||
console.error("Invalid object received: " + transport.responseText);
|
console.error("Invalid object received: " + transport.responseText);
|
||||||
dijit.byId("headlines-frame").attr('content', "<div class='whiteBox'>" +
|
dijit.byId("headlines-frame").attr('content', "<div class='whiteBox'>" +
|
||||||
__('Could not update headlines (invalid object received - see error console for details)') +
|
__('Could not update headlines (invalid object received - see error console for details)') +
|
||||||
"</div>");
|
"</div>");
|
||||||
} else {
|
|
||||||
//notify_error("Error communicating with server.");
|
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_infscroll_request_sent = 0;
|
_infscroll_request_sent = 0;
|
||||||
|
@ -314,13 +320,11 @@ function article_callback2(transport, id) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
} else if (transport.responseText) {
|
} else {
|
||||||
console.error("Invalid object received: " + transport.responseText);
|
console.error("Invalid object received: " + transport.responseText);
|
||||||
|
|
||||||
render_article("<div class='whiteBox'>" +
|
render_article("<div class='whiteBox'>" +
|
||||||
__('Could not display article (invalid object received - see error console for details)') + "</div>");
|
__('Could not display article (invalid object received - see error console for details)') + "</div>");
|
||||||
} else {
|
|
||||||
Element.show(dijit.byId("net-alert").domNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length
|
var unread_in_buffer = $$("#headlines-frame > div[id*=RROW][class*=Unread]").length
|
||||||
|
@ -961,10 +965,12 @@ function getLoadedArticleIds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// mode = all,none,unread,invert,marked,published
|
// mode = all,none,unread,invert,marked,published
|
||||||
function selectArticles(mode) {
|
function selectArticles(mode, query) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
var children = $$("#headlines-frame > div[id*=RROW]");
|
if (!query) query = "#headlines-frame > div[id*=RROW]";
|
||||||
|
|
||||||
|
var children = $$(query);
|
||||||
|
|
||||||
children.each(function(child) {
|
children.each(function(child) {
|
||||||
var id = child.id.replace("RROW-", "");
|
var id = child.id.replace("RROW-", "");
|
||||||
|
@ -1243,7 +1249,7 @@ function postMouseOut(id) {
|
||||||
|
|
||||||
function unpackVisibleHeadlines() {
|
function unpackVisibleHeadlines() {
|
||||||
try {
|
try {
|
||||||
if (!isCdmMode()) return;
|
if (!isCdmMode() || !getInitParam("cdm_expanded")) return;
|
||||||
|
|
||||||
$$("#headlines-frame > div[id*=RROW]").each(
|
$$("#headlines-frame > div[id*=RROW]").each(
|
||||||
function(child) {
|
function(child) {
|
||||||
|
@ -1306,15 +1312,20 @@ function headlines_scroll_handler(e) {
|
||||||
((e.scrollTop + e.offsetHeight) / e.scrollHeight >= 0.7))) {
|
((e.scrollTop + e.offsetHeight) / e.scrollHeight >= 0.7))) {
|
||||||
|
|
||||||
if (hsp)
|
if (hsp)
|
||||||
hsp.innerHTML = "<img src='images/indicator_tiny.gif'> " +
|
hsp.innerHTML = "<span class='loading'><img src='images/indicator_tiny.gif'> " +
|
||||||
__("Loading, please wait...");
|
__("Loading, please wait...") + "</span>";
|
||||||
|
|
||||||
loadMoreHeadlines();
|
loadMoreHeadlines();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (hsp) hsp.innerHTML = "";
|
if (hsp)
|
||||||
|
if (_infscroll_disable)
|
||||||
|
hsp.innerHTML = "<a href='#' onclick='openNextUnreadFeed()'>" +
|
||||||
|
__("Click to open next unread feed.") + "</a>";
|
||||||
|
else
|
||||||
|
hsp.innerHTML = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCdmMode()) {
|
if (isCdmMode()) {
|
||||||
|
@ -1350,6 +1361,20 @@ function headlines_scroll_handler(e) {
|
||||||
500);
|
500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_infscroll_disable) {
|
||||||
|
var child = $$("#headlines-frame div[id*=RROW]").last();
|
||||||
|
|
||||||
|
if (child && $("headlines-frame").scrollTop >
|
||||||
|
(child.offsetTop + child.offsetHeight - 50)) {
|
||||||
|
|
||||||
|
console.log("we seem to be at an end");
|
||||||
|
|
||||||
|
if (getInitParam("on_catchup_show_next_feed") == "1") {
|
||||||
|
openNextUnreadFeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1357,6 +1382,16 @@ function headlines_scroll_handler(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openNextUnreadFeed() {
|
||||||
|
try {
|
||||||
|
var is_cat = activeFeedIsCat();
|
||||||
|
var nuf = getNextUnreadFeed(getActiveFeedId(), is_cat);
|
||||||
|
if (nuf) viewfeed(nuf, '', is_cat);
|
||||||
|
} catch (e) {
|
||||||
|
exception_error("openNextUnreadFeed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function catchupBatchedArticles() {
|
function catchupBatchedArticles() {
|
||||||
try {
|
try {
|
||||||
if (catchup_id_batch.length > 0 && !_infscroll_request_sent) {
|
if (catchup_id_batch.length > 0 && !_infscroll_request_sent) {
|
||||||
|
@ -1761,7 +1796,8 @@ function cdmClicked(event, id) {
|
||||||
return !event.shiftKey;
|
return !event.shiftKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else if (event.target.parents(".cdmHeader").length > 0) {
|
||||||
|
|
||||||
toggleSelected(id, true);
|
toggleSelected(id, true);
|
||||||
|
|
||||||
var elem = $("RROW-" + id);
|
var elem = $("RROW-" + id);
|
||||||
|
@ -2107,6 +2143,72 @@ function initHeadlinesMenu() {
|
||||||
|
|
||||||
menu.startup();
|
menu.startup();
|
||||||
|
|
||||||
|
/* vgroup feed title menu */
|
||||||
|
|
||||||
|
var nodes = $$("#headlines-frame > div[class='cdmFeedTitle']");
|
||||||
|
var ids = [];
|
||||||
|
|
||||||
|
nodes.each(function(node) {
|
||||||
|
ids.push(node.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ids.length > 0) {
|
||||||
|
if (dijit.byId("headlinesFeedTitleMenu"))
|
||||||
|
dijit.byId("headlinesFeedTitleMenu").destroyRecursive();
|
||||||
|
|
||||||
|
var menu = new dijit.Menu({
|
||||||
|
id: "headlinesFeedTitleMenu",
|
||||||
|
targetNodeIds: ids,
|
||||||
|
});
|
||||||
|
|
||||||
|
var tmph = dojo.connect(menu, '_openMyself', function (event) {
|
||||||
|
var callerNode = event.target, match = null, tries = 0;
|
||||||
|
|
||||||
|
while (match == null && callerNode && tries <= 3) {
|
||||||
|
console.log(callerNode.id);
|
||||||
|
|
||||||
|
match = callerNode.id.match("^[A-Z]+[-]([0-9]+)$");
|
||||||
|
callerNode = callerNode.parentNode;
|
||||||
|
++tries;
|
||||||
|
|
||||||
|
console.log(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) this.callerRowId = parseInt(match[1]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addChild(new dijit.MenuItem({
|
||||||
|
label: __("Select articles in group"),
|
||||||
|
onClick: function(event) {
|
||||||
|
selectArticles("all",
|
||||||
|
"#headlines-frame > div[id*=RROW]"+
|
||||||
|
"[orig-feed-id='"+menu.callerRowId+"']");
|
||||||
|
|
||||||
|
}}));
|
||||||
|
|
||||||
|
menu.addChild(new dijit.MenuItem({
|
||||||
|
label: __("Mark group as read"),
|
||||||
|
onClick: function(event) {
|
||||||
|
selectArticles("none");
|
||||||
|
selectArticles("all",
|
||||||
|
"#headlines-frame > div[id*=RROW]"+
|
||||||
|
"[orig-feed-id='"+menu.callerRowId+"']");
|
||||||
|
|
||||||
|
catchupSelection();
|
||||||
|
}}));
|
||||||
|
|
||||||
|
|
||||||
|
menu.addChild(new dijit.MenuItem({
|
||||||
|
label: __("Mark feed as read"),
|
||||||
|
onClick: function(event) {
|
||||||
|
catchupFeedInGroup(menu.callerRowId);
|
||||||
|
}}));
|
||||||
|
|
||||||
|
menu.startup();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
exception_error("initHeadlinesMenu", e);
|
exception_error("initHeadlinesMenu", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,220 +1,220 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Mobile Detect
|
* Mobile Detect
|
||||||
* $Id: Mobile_Detect.php 44 2012-05-03 21:45:00Z serbanghita@gmail.com $
|
* $Id: Mobile_Detect.php 44 2012-05-03 21:45:00Z serbanghita@gmail.com $
|
||||||
*
|
*
|
||||||
* @usage require_once 'Mobile_Detect.php';
|
* @usage require_once 'Mobile_Detect.php';
|
||||||
* $detect = new Mobile_Detect();
|
* $detect = new Mobile_Detect();
|
||||||
* $detect->isMobile() or $detect->isTablet()
|
* $detect->isMobile() or $detect->isTablet()
|
||||||
*
|
*
|
||||||
* For more specific usage see the documentation navigate to:
|
* For more specific usage see the documentation navigate to:
|
||||||
* http://code.google.com/p/php-mobile-detect/wiki/Mobile_Detect
|
* http://code.google.com/p/php-mobile-detect/wiki/Mobile_Detect
|
||||||
*
|
*
|
||||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Mobile_Detect {
|
class Mobile_Detect {
|
||||||
|
|
||||||
protected $detectionRules;
|
protected $detectionRules;
|
||||||
protected $userAgent = null;
|
protected $userAgent = null;
|
||||||
protected $accept = null;
|
protected $accept = null;
|
||||||
// Assume the visitor has a desktop environment.
|
// Assume the visitor has a desktop environment.
|
||||||
protected $isMobile = false;
|
protected $isMobile = false;
|
||||||
protected $isTablet = false;
|
protected $isTablet = false;
|
||||||
protected $phoneDeviceName = null;
|
protected $phoneDeviceName = null;
|
||||||
protected $tabletDevicename = null;
|
protected $tabletDevicename = null;
|
||||||
protected $operatingSystemName = null;
|
protected $operatingSystemName = null;
|
||||||
protected $userAgentName = null;
|
protected $userAgentName = null;
|
||||||
// List of mobile devices (phones)
|
// List of mobile devices (phones)
|
||||||
protected $phoneDevices = array(
|
protected $phoneDevices = array(
|
||||||
'iPhone' => '(iPhone.*Mobile|iPod|iTunes)',
|
'iPhone' => '(iPhone.*Mobile|iPod|iTunes)',
|
||||||
'BlackBerry' => 'BlackBerry|rim[0-9]+',
|
'BlackBerry' => 'BlackBerry|rim[0-9]+',
|
||||||
'HTC' => 'HTC|HTC.*(6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090',
|
'HTC' => 'HTC|HTC.*(6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090',
|
||||||
'Nexus' => 'Nexus One|Nexus S',
|
'Nexus' => 'Nexus One|Nexus S',
|
||||||
'DellStreak' => 'Dell Streak',
|
'DellStreak' => 'Dell Streak',
|
||||||
'Motorola' => '\bDroid\b.*Build|HRI39|MOT\-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT909|XT910|XT912|XT928',
|
'Motorola' => '\bDroid\b.*Build|HRI39|MOT\-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT909|XT910|XT912|XT928',
|
||||||
'Samsung' => 'Samsung|GT-I9100|GT-I9000|GT-I9020|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-LC11|SCH-N150|SCH-N300|SCH-R300|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-C207|SGH-C225|SGH-C417|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D807|SGH-E105|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E635|SGH-E715|SGH-I577|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I717|SGH-I727|SGH-I777|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-N105|SGH-N625|SGH-P107|SGH-P207|SGH-P735|SGH-P777|SGH-Q105|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T919|SGH-T929|SGH-T939|SGH-T939|SGH-T959|SGH-T989|SGH-V205|SGH-V206|SGH-X105|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-ZX10|SGH-ZX20|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500I|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100',
|
'Samsung' => 'Samsung|GT-I9100|GT-I9000|GT-I9020|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-LC11|SCH-N150|SCH-N300|SCH-R300|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-C207|SGH-C225|SGH-C417|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D807|SGH-E105|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E635|SGH-E715|SGH-I577|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I717|SGH-I727|SGH-I777|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-N105|SGH-N625|SGH-P107|SGH-P207|SGH-P735|SGH-P777|SGH-Q105|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T919|SGH-T929|SGH-T939|SGH-T939|SGH-T959|SGH-T989|SGH-V205|SGH-V206|SGH-X105|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-ZX10|SGH-ZX20|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500I|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100',
|
||||||
'Sony' => 'E10i|SonyEricsson|SonyEricssonLT15iv',
|
'Sony' => 'E10i|SonyEricsson|SonyEricssonLT15iv',
|
||||||
'Asus' => 'Asus.*Galaxy',
|
'Asus' => 'Asus.*Galaxy',
|
||||||
'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino
|
'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino
|
||||||
'GenericPhone' => '(mmp|pocket|psp|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|wap|nokia|Series40|Series60|S60|SonyEricsson|N900|PPC;|MAUI.*WAP.*Browser|LG-P500)'
|
'GenericPhone' => '(mmp|pocket|psp|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|wap|nokia|Series40|Series60|S60|SonyEricsson|N900|PPC;|MAUI.*WAP.*Browser|LG-P500)'
|
||||||
);
|
);
|
||||||
// List of tablet devices.
|
// List of tablet devices.
|
||||||
protected $tabletDevices = array(
|
protected $tabletDevices = array(
|
||||||
'BlackBerryTablet' => 'PlayBook|RIM Tablet',
|
'BlackBerryTablet' => 'PlayBook|RIM Tablet',
|
||||||
'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
|
'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
|
||||||
'Kindle' => 'Kindle|Silk.*Accelerated',
|
'Kindle' => 'Kindle|Silk.*Accelerated',
|
||||||
'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|GT-P1000|GT-P1010|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I777|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SGH-T989|SPH-D710|SPH-P100',
|
'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|GT-P1000|GT-P1010|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I777|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SGH-T989|SPH-D710|SPH-P100',
|
||||||
'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
|
'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
|
||||||
'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
|
'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
|
||||||
'AsusTablet' => 'Transformer|TF101',
|
'AsusTablet' => 'Transformer|TF101',
|
||||||
'NookTablet' => 'NookColor|nook browser|BNTV250A|LogicPD Zoom2',
|
'NookTablet' => 'NookColor|nook browser|BNTV250A|LogicPD Zoom2',
|
||||||
'AcerTablet' => 'Android.*(A100|A101|A200|A500|A501|A510|W500|W500P|W501|W501P)',
|
'AcerTablet' => 'Android.*(A100|A101|A200|A500|A501|A510|W500|W500P|W501|W501P)',
|
||||||
'YarvikTablet' => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)',
|
'YarvikTablet' => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)',
|
||||||
'GenericTablet' => 'Tablet(?!.*PC)|ViewPad7|LG-V909|MID7015|BNTV250A|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b',
|
'GenericTablet' => 'Tablet(?!.*PC)|ViewPad7|LG-V909|MID7015|BNTV250A|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b',
|
||||||
);
|
);
|
||||||
// List of mobile Operating Systems.
|
// List of mobile Operating Systems.
|
||||||
protected $operatingSystems = array(
|
protected $operatingSystems = array(
|
||||||
'AndroidOS' => '(android.*mobile|android(?!.*mobile))',
|
'AndroidOS' => '(android.*mobile|android(?!.*mobile))',
|
||||||
'BlackBerryOS' => '(blackberry|rim tablet os)',
|
'BlackBerryOS' => '(blackberry|rim tablet os)',
|
||||||
'PalmOS' => '(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)',
|
'PalmOS' => '(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)',
|
||||||
'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|\bS60\b',
|
'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|\bS60\b',
|
||||||
'WindowsMobileOS' => 'IEMobile|Windows Phone|Windows CE.*(PPC|Smartphone)|MSIEMobile|Window Mobile|XBLWP7',
|
'WindowsMobileOS' => 'IEMobile|Windows Phone|Windows CE.*(PPC|Smartphone)|MSIEMobile|Window Mobile|XBLWP7',
|
||||||
'iOS' => '(iphone|ipod|ipad)',
|
'iOS' => '(iphone|ipod|ipad)',
|
||||||
'FlashLiteOS' => '',
|
'FlashLiteOS' => '',
|
||||||
'JavaOS' => '',
|
'JavaOS' => '',
|
||||||
'NokiaOS' => '',
|
'NokiaOS' => '',
|
||||||
'webOS' => '',
|
'webOS' => '',
|
||||||
'badaOS' => '\bBada\b',
|
'badaOS' => '\bBada\b',
|
||||||
'BREWOS' => '',
|
'BREWOS' => '',
|
||||||
);
|
);
|
||||||
// List of mobile User Agents.
|
// List of mobile User Agents.
|
||||||
protected $userAgents = array(
|
protected $userAgents = array(
|
||||||
'Chrome' => '\bCrMo\b|Chrome\/[.0-9]* Mobile',
|
'Chrome' => '\bCrMo\b|Chrome\/[.0-9]* Mobile',
|
||||||
'Dolfin' => '\bDolfin\b',
|
'Dolfin' => '\bDolfin\b',
|
||||||
'Opera' => 'Opera.*Mini|Opera.*Mobi',
|
'Opera' => 'Opera.*Mini|Opera.*Mobi',
|
||||||
'Skyfire' => 'skyfire',
|
'Skyfire' => 'skyfire',
|
||||||
'IE' => 'IEMobile',
|
'IE' => 'IEMobile',
|
||||||
'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
|
'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
|
||||||
'Bolt' => 'bolt',
|
'Bolt' => 'bolt',
|
||||||
'TeaShark' => 'teashark',
|
'TeaShark' => 'teashark',
|
||||||
'Blazer' => 'Blazer',
|
'Blazer' => 'Blazer',
|
||||||
'Safari' => 'Mobile.*Safari|Safari.*Mobile',
|
'Safari' => 'Mobile.*Safari|Safari.*Mobile',
|
||||||
'Midori' => 'midori',
|
'Midori' => 'midori',
|
||||||
'GenericBrowser' => 'NokiaBrowser|OviBrowser|SEMC.*Browser'
|
'GenericBrowser' => 'NokiaBrowser|OviBrowser|SEMC.*Browser'
|
||||||
);
|
);
|
||||||
|
|
||||||
function __construct(){
|
function __construct(){
|
||||||
|
|
||||||
// Merge all rules together.
|
// Merge all rules together.
|
||||||
$this->detectionRules = array_merge(
|
$this->detectionRules = array_merge(
|
||||||
$this->phoneDevices,
|
$this->phoneDevices,
|
||||||
$this->tabletDevices,
|
$this->tabletDevices,
|
||||||
$this->operatingSystems,
|
$this->operatingSystems,
|
||||||
$this->userAgents
|
$this->userAgents
|
||||||
);
|
);
|
||||||
$this->userAgent = $_SERVER['HTTP_USER_AGENT'];
|
$this->userAgent = $_SERVER['HTTP_USER_AGENT'];
|
||||||
$this->accept = $_SERVER['HTTP_ACCEPT'];
|
$this->accept = $_SERVER['HTTP_ACCEPT'];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isset($_SERVER['HTTP_X_WAP_PROFILE']) ||
|
isset($_SERVER['HTTP_X_WAP_PROFILE']) ||
|
||||||
isset($_SERVER['HTTP_X_WAP_CLIENTID']) ||
|
isset($_SERVER['HTTP_X_WAP_CLIENTID']) ||
|
||||||
isset($_SERVER['HTTP_WAP_CONNECTION']) ||
|
isset($_SERVER['HTTP_WAP_CONNECTION']) ||
|
||||||
isset($_SERVER['HTTP_PROFILE']) ||
|
isset($_SERVER['HTTP_PROFILE']) ||
|
||||||
isset($_SERVER['HTTP_X_OPERAMINI_PHONE_UA']) || // Reported by Nokia devices (eg. C3)
|
isset($_SERVER['HTTP_X_OPERAMINI_PHONE_UA']) || // Reported by Nokia devices (eg. C3)
|
||||||
isset($_SERVER['HTTP_X_NOKIA_IPADDRESS']) ||
|
isset($_SERVER['HTTP_X_NOKIA_IPADDRESS']) ||
|
||||||
isset($_SERVER['HTTP_X_NOKIA_GATEWAY_ID']) ||
|
isset($_SERVER['HTTP_X_NOKIA_GATEWAY_ID']) ||
|
||||||
isset($_SERVER['HTTP_X_ORANGE_ID']) ||
|
isset($_SERVER['HTTP_X_ORANGE_ID']) ||
|
||||||
isset($_SERVER['HTTP_X_VODAFONE_3GPDPCONTEXT']) ||
|
isset($_SERVER['HTTP_X_VODAFONE_3GPDPCONTEXT']) ||
|
||||||
isset($_SERVER['HTTP_X_HUAWEI_USERID']) ||
|
isset($_SERVER['HTTP_X_HUAWEI_USERID']) ||
|
||||||
isset($_SERVER['HTTP_UA_OS']) || // Reported by Windows Smartphones
|
isset($_SERVER['HTTP_UA_OS']) || // Reported by Windows Smartphones
|
||||||
(isset($_SERVER['HTTP_UA_CPU']) && $_SERVER['HTTP_UA_CPU'] == 'ARM') // Seen this on a HTC
|
(isset($_SERVER['HTTP_UA_CPU']) && $_SERVER['HTTP_UA_CPU'] == 'ARM') // Seen this on a HTC
|
||||||
) {
|
) {
|
||||||
$this->isMobile = true;
|
$this->isMobile = true;
|
||||||
} elseif (!empty($this->accept) && (strpos($this->accept, 'text/vnd.wap.wml') !== false || strpos($this->accept, 'application/vnd.wap.xhtml+xml') !== false)) {
|
} elseif (!empty($this->accept) && (strpos($this->accept, 'text/vnd.wap.wml') !== false || strpos($this->accept, 'application/vnd.wap.xhtml+xml') !== false)) {
|
||||||
$this->isMobile = true;
|
$this->isMobile = true;
|
||||||
} else {
|
} else {
|
||||||
$this->_detect();
|
$this->_detect();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRules()
|
public function getRules()
|
||||||
{
|
{
|
||||||
return $this->detectionRules;
|
return $this->detectionRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic overloading method.
|
* Magic overloading method.
|
||||||
*
|
*
|
||||||
* @method boolean is[...]()
|
* @method boolean is[...]()
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param array $arguments
|
* @param array $arguments
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function __call($name, $arguments)
|
public function __call($name, $arguments)
|
||||||
{
|
{
|
||||||
|
|
||||||
$key = substr($name, 2);
|
$key = substr($name, 2);
|
||||||
return $this->_detect($key);
|
return $this->_detect($key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private method that does the detection of the
|
* Private method that does the detection of the
|
||||||
* mobile devices.
|
* mobile devices.
|
||||||
*
|
*
|
||||||
* @param type $key
|
* @param type $key
|
||||||
* @return boolean|null
|
* @return boolean|null
|
||||||
*/
|
*/
|
||||||
private function _detect($key='')
|
private function _detect($key='')
|
||||||
{
|
{
|
||||||
|
|
||||||
if(empty($key)){
|
if(empty($key)){
|
||||||
|
|
||||||
// Begin general search.
|
// Begin general search.
|
||||||
foreach($this->detectionRules as $_regex){
|
foreach($this->detectionRules as $_regex){
|
||||||
if(empty($_regex)){ continue; }
|
if(empty($_regex)){ continue; }
|
||||||
if(preg_match('/'.$_regex.'/is', $this->userAgent)){
|
if(preg_match('/'.$_regex.'/is', $this->userAgent)){
|
||||||
$this->isMobile = true;
|
$this->isMobile = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Search for a certain key.
|
// Search for a certain key.
|
||||||
// Make the keys lowecase so we can match: isIphone(), isiPhone(), isiphone(), etc.
|
// Make the keys lowecase so we can match: isIphone(), isiPhone(), isiphone(), etc.
|
||||||
$key = strtolower($key);
|
$key = strtolower($key);
|
||||||
$_rules = array_change_key_case($this->detectionRules);
|
$_rules = array_change_key_case($this->detectionRules);
|
||||||
|
|
||||||
if(array_key_exists($key, $_rules)){
|
if(array_key_exists($key, $_rules)){
|
||||||
if(empty($_rules[$key])){ return null; }
|
if(empty($_rules[$key])){ return null; }
|
||||||
if(preg_match('/'.$_rules[$key].'/is', $this->userAgent)){
|
if(preg_match('/'.$_rules[$key].'/is', $this->userAgent)){
|
||||||
$this->isMobile = true;
|
$this->isMobile = true;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trigger_error("Method $key is not defined", E_USER_WARNING);
|
trigger_error("Method $key is not defined", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the device is mobile.
|
* Check if the device is mobile.
|
||||||
* Returns true if any type of mobile device detected, including special ones
|
* Returns true if any type of mobile device detected, including special ones
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isMobile()
|
public function isMobile()
|
||||||
{
|
{
|
||||||
return $this->isMobile;
|
return $this->isMobile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the device is a tablet.
|
* Check if the device is a tablet.
|
||||||
* Return true if any type of tablet device is detected.
|
* Return true if any type of tablet device is detected.
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function isTablet()
|
public function isTablet()
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach($this->tabletDevices as $_regex){
|
foreach($this->tabletDevices as $_regex){
|
||||||
if(preg_match('/'.$_regex.'/is', $this->userAgent)){
|
if(preg_match('/'.$_regex.'/is', $this->userAgent)){
|
||||||
$this->isTablet = true;
|
$this->isTablet = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
Copyright (c) 2005, Fabricio Zuardi
|
Copyright (c) 2005, Fabricio Zuardi
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
* 1.0.0 build 2010031920
|
* 1.0.0 build 2010031920
|
||||||
|
|
||||||
- first public release
|
- first public release
|
||||||
- help in readme, install
|
- help in readme, install
|
||||||
- cleanup ans separation of QRtools and QRspec
|
- cleanup ans separation of QRtools and QRspec
|
||||||
- now TCPDF binding requires minimal changes in TCPDF, having most of job
|
- now TCPDF binding requires minimal changes in TCPDF, having most of job
|
||||||
done in QRtools tcpdfBarcodeArray
|
done in QRtools tcpdfBarcodeArray
|
||||||
- nicer QRtools::timeBenchmark output
|
- nicer QRtools::timeBenchmark output
|
||||||
- license and copyright notices in files
|
- license and copyright notices in files
|
||||||
- indent cleanup - from tab to 4spc, keep it that way please :)
|
- indent cleanup - from tab to 4spc, keep it that way please :)
|
||||||
- sf project, repository, wiki
|
- sf project, repository, wiki
|
||||||
- simple code generator in index.php
|
- simple code generator in index.php
|
||||||
|
|
||||||
* 1.1.0 build 2010032113
|
* 1.1.0 build 2010032113
|
||||||
|
|
||||||
- added merge tool wich generate merged version of code
|
- added merge tool wich generate merged version of code
|
||||||
located in phpqrcode.php
|
located in phpqrcode.php
|
||||||
- splited qrconst.php from qrlib.php
|
- splited qrconst.php from qrlib.php
|
||||||
|
|
||||||
* 1.1.1 build 2010032405
|
* 1.1.1 build 2010032405
|
||||||
|
|
||||||
- patch by Rick Seymour allowing saving PNG and displaying it at the same time
|
- patch by Rick Seymour allowing saving PNG and displaying it at the same time
|
||||||
- added version info in VERSION file
|
- added version info in VERSION file
|
||||||
- modified merge tool to include version info into generated file
|
- modified merge tool to include version info into generated file
|
||||||
- fixed e-mail in almost all head comments
|
- fixed e-mail in almost all head comments
|
||||||
|
|
||||||
* 1.1.2 build 2010032722
|
* 1.1.2 build 2010032722
|
||||||
|
|
||||||
- full integration with TCPDF thanks to Nicola Asuni, it's author
|
- full integration with TCPDF thanks to Nicola Asuni, it's author
|
||||||
- fixed bug with alphanumeric encoding detection
|
- fixed bug with alphanumeric encoding detection
|
||||||
|
|
||||||
* 1.1.3 build 2010081807
|
* 1.1.3 build 2010081807
|
||||||
|
|
||||||
- short opening tags replaced with standard ones
|
- short opening tags replaced with standard ones
|
||||||
|
|
||||||
* 1.1.4 build 2010100721
|
* 1.1.4 build 2010100721
|
||||||
|
|
||||||
- added missing static keyword QRinput::check (found by Luke Brookhart, Onjax LLC)
|
- added missing static keyword QRinput::check (found by Luke Brookhart, Onjax LLC)
|
||||||
|
|
|
@ -1,67 +1,67 @@
|
||||||
== REQUIREMENTS ==
|
== REQUIREMENTS ==
|
||||||
|
|
||||||
* PHP5
|
* PHP5
|
||||||
* PHP GD2 extension with JPEG and PNG support
|
* PHP GD2 extension with JPEG and PNG support
|
||||||
|
|
||||||
== INSTALLATION ==
|
== INSTALLATION ==
|
||||||
|
|
||||||
If you want to recreate cache by yourself make sure cache directory is
|
If you want to recreate cache by yourself make sure cache directory is
|
||||||
writable and you have permisions to write into it. Also make sure you are
|
writable and you have permisions to write into it. Also make sure you are
|
||||||
able to read files in it if you have cache option enabled
|
able to read files in it if you have cache option enabled
|
||||||
|
|
||||||
== CONFIGURATION ==
|
== CONFIGURATION ==
|
||||||
|
|
||||||
Feel free to modify config constants in qrconfig.php file. Read about it in
|
Feel free to modify config constants in qrconfig.php file. Read about it in
|
||||||
provided comments and project wiki page (links in README file)
|
provided comments and project wiki page (links in README file)
|
||||||
|
|
||||||
== QUICK START ==
|
== QUICK START ==
|
||||||
|
|
||||||
Notice: probably you should'nt use all of this in same script :)
|
Notice: probably you should'nt use all of this in same script :)
|
||||||
|
|
||||||
<?phpb
|
<?phpb
|
||||||
|
|
||||||
//include only that one, rest required files will be included from it
|
//include only that one, rest required files will be included from it
|
||||||
include "qrlib.php"
|
include "qrlib.php"
|
||||||
|
|
||||||
//write code into file, Error corection lecer is lowest, L (one form: L,M,Q,H)
|
//write code into file, Error corection lecer is lowest, L (one form: L,M,Q,H)
|
||||||
//each code square will be 4x4 pixels (4x zoom)
|
//each code square will be 4x4 pixels (4x zoom)
|
||||||
//code will have 2 code squares white boundary around
|
//code will have 2 code squares white boundary around
|
||||||
|
|
||||||
QRcode::png('PHP QR Code :)', 'test.png', 'L', 4, 2);
|
QRcode::png('PHP QR Code :)', 'test.png', 'L', 4, 2);
|
||||||
|
|
||||||
//same as above but outputs file directly into browser (with appr. header etc.)
|
//same as above but outputs file directly into browser (with appr. header etc.)
|
||||||
//all other settings are default
|
//all other settings are default
|
||||||
//WARNING! it should be FIRST and ONLY output generated by script, otherwise
|
//WARNING! it should be FIRST and ONLY output generated by script, otherwise
|
||||||
//rest of output will land inside PNG binary, breaking it for sure
|
//rest of output will land inside PNG binary, breaking it for sure
|
||||||
QRcode::png('PHP QR Code :)');
|
QRcode::png('PHP QR Code :)');
|
||||||
|
|
||||||
//show benchmark
|
//show benchmark
|
||||||
QRtools::timeBenchmark();
|
QRtools::timeBenchmark();
|
||||||
|
|
||||||
//rebuild cache
|
//rebuild cache
|
||||||
QRtools::buildCache();
|
QRtools::buildCache();
|
||||||
|
|
||||||
//code generated in text mode - as a binary table
|
//code generated in text mode - as a binary table
|
||||||
//then displayed out as HTML using Unicode block building chars :)
|
//then displayed out as HTML using Unicode block building chars :)
|
||||||
$tab = $qr->encode('PHP QR Code :)');
|
$tab = $qr->encode('PHP QR Code :)');
|
||||||
QRspec::debug($tab, true);
|
QRspec::debug($tab, true);
|
||||||
|
|
||||||
== TCPDF INTEGRATION ==
|
== TCPDF INTEGRATION ==
|
||||||
|
|
||||||
Inside bindings/tcpdf you will find slightly modified 2dbarcodes.php.
|
Inside bindings/tcpdf you will find slightly modified 2dbarcodes.php.
|
||||||
Instal phpqrcode liblaty inside tcpdf folder, then overwrite (or merge)
|
Instal phpqrcode liblaty inside tcpdf folder, then overwrite (or merge)
|
||||||
2dbarcodes.php
|
2dbarcodes.php
|
||||||
|
|
||||||
Then use similar as example #50 from TCPDF examples:
|
Then use similar as example #50 from TCPDF examples:
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$style = array(
|
$style = array(
|
||||||
'border' => true,
|
'border' => true,
|
||||||
'padding' => 4,
|
'padding' => 4,
|
||||||
'fgcolor' => array(0,0,0),
|
'fgcolor' => array(0,0,0),
|
||||||
'bgcolor' => false, //array(255,255,255)
|
'bgcolor' => false, //array(255,255,255)
|
||||||
);
|
);
|
||||||
|
|
||||||
//code name: QR, specify error correction level after semicolon (L,M,Q,H)
|
//code name: QR, specify error correction level after semicolon (L,M,Q,H)
|
||||||
$pdf->write2DBarcode('PHP QR Code :)', 'QR,L', '', '', 30, 30, $style, 'N');
|
$pdf->write2DBarcode('PHP QR Code :)', 'QR,L', '', '', 30, 30, $style, 'N');
|
||||||
|
|
|
@ -1,165 +1,165 @@
|
||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
This version of the GNU Lesser General Public License incorporates
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
License, supplemented by the additional permissions listed below.
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
0. Additional Definitions.
|
0. Additional Definitions.
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
General Public License.
|
General Public License.
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
"The Library" refers to a covered work governed by this License,
|
||||||
other than an Application or a Combined Work as defined below.
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
An "Application" is any work that makes use of an interface provided
|
||||||
by the Library, but which is not otherwise based on the Library.
|
by the Library, but which is not otherwise based on the Library.
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
of using an interface provided by the Library.
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
Application with the Library. The particular version of the Library
|
Application with the Library. The particular version of the Library
|
||||||
with which the Combined Work was made is also called the "Linked
|
with which the Combined Work was made is also called the "Linked
|
||||||
Version".
|
Version".
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
based on the Application, and not on the Linked Version.
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
object code and/or source code for the Application, including any data
|
object code and/or source code for the Application, including any data
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
without being bound by section 3 of the GNU GPL.
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
facility refers to a function or data to be supplied by an Application
|
facility refers to a function or data to be supplied by an Application
|
||||||
that uses the facility (other than as an argument passed when the
|
that uses the facility (other than as an argument passed when the
|
||||||
facility is invoked), then you may convey a copy of the modified
|
facility is invoked), then you may convey a copy of the modified
|
||||||
version:
|
version:
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
a) under this License, provided that you make a good faith effort to
|
||||||
ensure that, in the event an Application does not supply the
|
ensure that, in the event an Application does not supply the
|
||||||
function or data, the facility still operates, and performs
|
function or data, the facility still operates, and performs
|
||||||
whatever part of its purpose remains meaningful, or
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
this License applicable to that copy.
|
this License applicable to that copy.
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
The object code form of an Application may incorporate material from
|
||||||
a header file that is part of the Library. You may convey such object
|
a header file that is part of the Library. You may convey such object
|
||||||
code under terms of your choice, provided that, if the incorporated
|
code under terms of your choice, provided that, if the incorporated
|
||||||
material is not limited to numerical parameters, data structure
|
material is not limited to numerical parameters, data structure
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
(ten or fewer lines in length), you do both of the following:
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
a) Give prominent notice with each copy of the object code that the
|
||||||
Library is used in it and that the Library and its use are
|
Library is used in it and that the Library and its use are
|
||||||
covered by this License.
|
covered by this License.
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
document.
|
document.
|
||||||
|
|
||||||
4. Combined Works.
|
4. Combined Works.
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
You may convey a Combined Work under terms of your choice that,
|
||||||
taken together, effectively do not restrict modification of the
|
taken together, effectively do not restrict modification of the
|
||||||
portions of the Library contained in the Combined Work and reverse
|
portions of the Library contained in the Combined Work and reverse
|
||||||
engineering for debugging such modifications, if you also do each of
|
engineering for debugging such modifications, if you also do each of
|
||||||
the following:
|
the following:
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
the Library is used in it and that the Library and its use are
|
the Library is used in it and that the Library and its use are
|
||||||
covered by this License.
|
covered by this License.
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
document.
|
document.
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
c) For a Combined Work that displays copyright notices during
|
||||||
execution, include the copyright notice for the Library among
|
execution, include the copyright notice for the Library among
|
||||||
these notices, as well as a reference directing the user to the
|
these notices, as well as a reference directing the user to the
|
||||||
copies of the GNU GPL and this license document.
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
d) Do one of the following:
|
d) Do one of the following:
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
License, and the Corresponding Application Code in a form
|
License, and the Corresponding Application Code in a form
|
||||||
suitable for, and under terms that permit, the user to
|
suitable for, and under terms that permit, the user to
|
||||||
recombine or relink the Application with a modified version of
|
recombine or relink the Application with a modified version of
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
Corresponding Source.
|
Corresponding Source.
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
a copy of the Library already present on the user's computer
|
a copy of the Library already present on the user's computer
|
||||||
system, and (b) will operate properly with a modified version
|
system, and (b) will operate properly with a modified version
|
||||||
of the Library that is interface-compatible with the Linked
|
of the Library that is interface-compatible with the Linked
|
||||||
Version.
|
Version.
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
be required to provide such information under section 6 of the
|
be required to provide such information under section 6 of the
|
||||||
GNU GPL, and only to the extent that such information is
|
GNU GPL, and only to the extent that such information is
|
||||||
necessary to install and execute a modified version of the
|
necessary to install and execute a modified version of the
|
||||||
Combined Work produced by recombining or relinking the
|
Combined Work produced by recombining or relinking the
|
||||||
Application with a modified version of the Linked Version. (If
|
Application with a modified version of the Linked Version. (If
|
||||||
you use option 4d0, the Installation Information must accompany
|
you use option 4d0, the Installation Information must accompany
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
for conveying Corresponding Source.)
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
5. Combined Libraries.
|
5. Combined Libraries.
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
You may place library facilities that are a work based on the
|
||||||
Library side by side in a single library together with other library
|
Library side by side in a single library together with other library
|
||||||
facilities that are not Applications and are not covered by this
|
facilities that are not Applications and are not covered by this
|
||||||
License, and convey such a combined library under terms of your
|
License, and convey such a combined library under terms of your
|
||||||
choice, if you do both of the following:
|
choice, if you do both of the following:
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
a) Accompany the combined library with a copy of the same work based
|
||||||
on the Library, uncombined with any other library facilities,
|
on the Library, uncombined with any other library facilities,
|
||||||
conveyed under the terms of this License.
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
b) Give prominent notice with the combined library that part of it
|
||||||
is a work based on the Library, and explaining where to find the
|
is a work based on the Library, and explaining where to find the
|
||||||
accompanying uncombined form of the same work.
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
versions will be similar in spirit to the present version, but may
|
versions will be similar in spirit to the present version, but may
|
||||||
differ in detail to address new problems or concerns.
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Library as you received it specifies that a certain numbered version
|
Library as you received it specifies that a certain numbered version
|
||||||
of the GNU Lesser General Public License "or any later version"
|
of the GNU Lesser General Public License "or any later version"
|
||||||
applies to it, you have the option of following the terms and
|
applies to it, you have the option of following the terms and
|
||||||
conditions either of that published version or of any later version
|
conditions either of that published version or of any later version
|
||||||
published by the Free Software Foundation. If the Library as you
|
published by the Free Software Foundation. If the Library as you
|
||||||
received it does not specify a version number of the GNU Lesser
|
received it does not specify a version number of the GNU Lesser
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
General Public License ever published by the Free Software Foundation.
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
If the Library as you received it specifies that a proxy can decide
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
permanent authorization for you to choose that version for the
|
permanent authorization for you to choose that version for the
|
||||||
Library.
|
Library.
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
This is PHP implementation of QR Code 2-D barcode generator. It is pure-php
|
This is PHP implementation of QR Code 2-D barcode generator. It is pure-php
|
||||||
LGPL-licensed implementation based on C libqrencode by Kentaro Fukuchi.
|
LGPL-licensed implementation based on C libqrencode by Kentaro Fukuchi.
|
||||||
|
|
||||||
== LICENSING ==
|
== LICENSING ==
|
||||||
|
|
||||||
Copyright (C) 2010 by Dominik Dzienia
|
Copyright (C) 2010 by Dominik Dzienia
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or modify it under
|
This library is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU Lesser General Public License as published by the Free
|
the terms of the GNU Lesser General Public License as published by the Free
|
||||||
Software Foundation; either version 3 of the License, or any later version.
|
Software Foundation; either version 3 of the License, or any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
PARTICULAR PURPOSE. See the GNU Lesser General Public License (LICENSE file)
|
PARTICULAR PURPOSE. See the GNU Lesser General Public License (LICENSE file)
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
with this library; if not, write to the Free Software Foundation, Inc., 51
|
with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||||
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
== INSTALATION AND USAGE ==
|
== INSTALATION AND USAGE ==
|
||||||
|
|
||||||
* INSTALL file
|
* INSTALL file
|
||||||
* http://sourceforge.net/apps/mediawiki/phpqrcode/index.php?title=Main_Page
|
* http://sourceforge.net/apps/mediawiki/phpqrcode/index.php?title=Main_Page
|
||||||
|
|
||||||
== CONTACT ==
|
== CONTACT ==
|
||||||
|
|
||||||
Fell free to contact me via e-mail (deltalab at poczta dot fm) or using
|
Fell free to contact me via e-mail (deltalab at poczta dot fm) or using
|
||||||
folowing project pages:
|
folowing project pages:
|
||||||
|
|
||||||
* http://sourceforge.net/projects/phpqrcode/
|
* http://sourceforge.net/projects/phpqrcode/
|
||||||
* http://phpqrcode.sourceforge.net/
|
* http://phpqrcode.sourceforge.net/
|
||||||
|
|
||||||
== ACKNOWLEDGMENTS ==
|
== ACKNOWLEDGMENTS ==
|
||||||
|
|
||||||
Based on C libqrencode library (ver. 3.1.1)
|
Based on C libqrencode library (ver. 3.1.1)
|
||||||
Copyright (C) 2006-2010 by Kentaro Fukuchi
|
Copyright (C) 2006-2010 by Kentaro Fukuchi
|
||||||
http://megaui.net/fukuchi/works/qrencode/index.en.html
|
http://megaui.net/fukuchi/works/qrencode/index.en.html
|
||||||
|
|
||||||
QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other
|
QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other
|
||||||
countries.
|
countries.
|
||||||
|
|
||||||
Reed-Solomon code encoder is written by Phil Karn, KA9Q.
|
Reed-Solomon code encoder is written by Phil Karn, KA9Q.
|
||||||
Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
1.1.4
|
1.1.4
|
||||||
2010100721
|
2010100721
|
|
@ -1,93 +1,93 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Exemplatory usage
|
* Exemplatory usage
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
echo "<h1>PHP QR Code</h1><hr/>";
|
echo "<h1>PHP QR Code</h1><hr/>";
|
||||||
|
|
||||||
//set it to writable location, a place for temp generated PNG files
|
//set it to writable location, a place for temp generated PNG files
|
||||||
$PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
|
$PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
//html PNG location prefix
|
//html PNG location prefix
|
||||||
$PNG_WEB_DIR = 'temp/';
|
$PNG_WEB_DIR = 'temp/';
|
||||||
|
|
||||||
include "qrlib.php";
|
include "qrlib.php";
|
||||||
|
|
||||||
//ofcourse we need rights to create temp dir
|
//ofcourse we need rights to create temp dir
|
||||||
if (!file_exists($PNG_TEMP_DIR))
|
if (!file_exists($PNG_TEMP_DIR))
|
||||||
mkdir($PNG_TEMP_DIR);
|
mkdir($PNG_TEMP_DIR);
|
||||||
|
|
||||||
|
|
||||||
$filename = $PNG_TEMP_DIR.'test.png';
|
$filename = $PNG_TEMP_DIR.'test.png';
|
||||||
|
|
||||||
//processing form input
|
//processing form input
|
||||||
//remember to sanitize user input in real-life solution !!!
|
//remember to sanitize user input in real-life solution !!!
|
||||||
$errorCorrectionLevel = 'L';
|
$errorCorrectionLevel = 'L';
|
||||||
if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], array('L','M','Q','H')))
|
if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], array('L','M','Q','H')))
|
||||||
$errorCorrectionLevel = $_REQUEST['level'];
|
$errorCorrectionLevel = $_REQUEST['level'];
|
||||||
|
|
||||||
|
$matrixPointSize = 4;
|
||||||
|
if (isset($_REQUEST['size']))
|
||||||
|
$matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10);
|
||||||
|
|
||||||
|
|
||||||
$matrixPointSize = 4;
|
if (isset($_REQUEST['data'])) {
|
||||||
if (isset($_REQUEST['size']))
|
|
||||||
$matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10);
|
//it's very important!
|
||||||
|
if (trim($_REQUEST['data']) == '')
|
||||||
|
die('data cannot be empty! <a href="?">back</a>');
|
||||||
if (isset($_REQUEST['data'])) {
|
|
||||||
|
|
||||||
//it's very important!
|
|
||||||
if (trim($_REQUEST['data']) == '')
|
|
||||||
die('data cannot be empty! <a href="?">back</a>');
|
|
||||||
|
|
||||||
// user data
|
// user data
|
||||||
$filename = $PNG_TEMP_DIR.'test'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png';
|
$filename = $PNG_TEMP_DIR.'test'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png';
|
||||||
QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2);
|
QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//default data
|
//default data
|
||||||
echo 'You can provide data in GET parameter: <a href="?data=like_that">like that</a><hr/>';
|
echo 'You can provide data in GET parameter: <a href="?data=like_that">like that</a><hr/>';
|
||||||
QRcode::png('PHP QR Code :)', $filename, $errorCorrectionLevel, $matrixPointSize, 2);
|
QRcode::png('PHP QR Code :)', $filename, $errorCorrectionLevel, $matrixPointSize, 2);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//display generated file
|
//display generated file
|
||||||
echo '<img src="'.$PNG_WEB_DIR.basename($filename).'" /><hr/>';
|
echo '<img src="'.$PNG_WEB_DIR.basename($filename).'" /><hr/>';
|
||||||
|
|
||||||
//config form
|
//config form
|
||||||
echo '<form action="index.php" method="post">
|
echo '<form action="index.php" method="post">
|
||||||
Data: <input name="data" value="'.(isset($_REQUEST['data'])?htmlspecialchars($_REQUEST['data']):'PHP QR Code :)').'" />
|
Data: <input name="data" value="'.(isset($_REQUEST['data'])?htmlspecialchars($_REQUEST['data']):'PHP QR Code :)').'" />
|
||||||
ECC: <select name="level">
|
ECC: <select name="level">
|
||||||
<option value="L"'.(($errorCorrectionLevel=='L')?' selected':'').'>L - smallest</option>
|
<option value="L"'.(($errorCorrectionLevel=='L')?' selected':'').'>L - smallest</option>
|
||||||
<option value="M"'.(($errorCorrectionLevel=='M')?' selected':'').'>M</option>
|
<option value="M"'.(($errorCorrectionLevel=='M')?' selected':'').'>M</option>
|
||||||
<option value="Q"'.(($errorCorrectionLevel=='Q')?' selected':'').'>Q</option>
|
<option value="Q"'.(($errorCorrectionLevel=='Q')?' selected':'').'>Q</option>
|
||||||
<option value="H"'.(($errorCorrectionLevel=='H')?' selected':'').'>H - best</option>
|
<option value="H"'.(($errorCorrectionLevel=='H')?' selected':'').'>H - best</option>
|
||||||
</select>
|
</select>
|
||||||
Size: <select name="size">';
|
Size: <select name="size">';
|
||||||
|
|
||||||
for($i=1;$i<=10;$i++)
|
for($i=1;$i<=10;$i++)
|
||||||
echo '<option value="'.$i.'"'.(($matrixPointSize==$i)?' selected':'').'>'.$i.'</option>';
|
echo '<option value="'.$i.'"'.(($matrixPointSize==$i)?' selected':'').'>'.$i.'</option>';
|
||||||
|
|
||||||
echo '</select>
|
echo '</select>
|
||||||
<input type="submit" value="GENERATE"></form><hr/>';
|
<input type="submit" value="GENERATE"></form><hr/>';
|
||||||
|
|
||||||
// benchmark
|
// benchmark
|
||||||
QRtools::timeBenchmark();
|
QRtools::timeBenchmark();
|
||||||
|
|
||||||
|
|
|
@ -1,180 +1,180 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Bitstream class
|
* Bitstream class
|
||||||
*
|
*
|
||||||
* Based on libqrencode C library distributed under LGPL 2.1
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QRbitstream {
|
class QRbitstream {
|
||||||
|
|
||||||
public $data = array();
|
public $data = array();
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function size()
|
public function size()
|
||||||
{
|
{
|
||||||
return count($this->data);
|
return count($this->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function allocate($setLength)
|
public function allocate($setLength)
|
||||||
{
|
{
|
||||||
$this->data = array_fill(0, $setLength, 0);
|
$this->data = array_fill(0, $setLength, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function newFromNum($bits, $num)
|
public static function newFromNum($bits, $num)
|
||||||
{
|
{
|
||||||
$bstream = new QRbitstream();
|
$bstream = new QRbitstream();
|
||||||
$bstream->allocate($bits);
|
$bstream->allocate($bits);
|
||||||
|
|
||||||
$mask = 1 << ($bits - 1);
|
$mask = 1 << ($bits - 1);
|
||||||
for($i=0; $i<$bits; $i++) {
|
for($i=0; $i<$bits; $i++) {
|
||||||
if($num & $mask) {
|
if($num & $mask) {
|
||||||
$bstream->data[$i] = 1;
|
$bstream->data[$i] = 1;
|
||||||
} else {
|
} else {
|
||||||
$bstream->data[$i] = 0;
|
$bstream->data[$i] = 0;
|
||||||
}
|
}
|
||||||
$mask = $mask >> 1;
|
$mask = $mask >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bstream;
|
return $bstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function newFromBytes($size, $data)
|
public static function newFromBytes($size, $data)
|
||||||
{
|
{
|
||||||
$bstream = new QRbitstream();
|
$bstream = new QRbitstream();
|
||||||
$bstream->allocate($size * 8);
|
$bstream->allocate($size * 8);
|
||||||
$p=0;
|
$p=0;
|
||||||
|
|
||||||
for($i=0; $i<$size; $i++) {
|
for($i=0; $i<$size; $i++) {
|
||||||
$mask = 0x80;
|
$mask = 0x80;
|
||||||
for($j=0; $j<8; $j++) {
|
for($j=0; $j<8; $j++) {
|
||||||
if($data[$i] & $mask) {
|
if($data[$i] & $mask) {
|
||||||
$bstream->data[$p] = 1;
|
$bstream->data[$p] = 1;
|
||||||
} else {
|
} else {
|
||||||
$bstream->data[$p] = 0;
|
$bstream->data[$p] = 0;
|
||||||
}
|
}
|
||||||
$p++;
|
$p++;
|
||||||
$mask = $mask >> 1;
|
$mask = $mask >> 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bstream;
|
return $bstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function append(QRbitstream $arg)
|
public function append(QRbitstream $arg)
|
||||||
{
|
{
|
||||||
if (is_null($arg)) {
|
if (is_null($arg)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($arg->size() == 0) {
|
if($arg->size() == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->size() == 0) {
|
if($this->size() == 0) {
|
||||||
$this->data = $arg->data;
|
$this->data = $arg->data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->data = array_values(array_merge($this->data, $arg->data));
|
$this->data = array_values(array_merge($this->data, $arg->data));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function appendNum($bits, $num)
|
public function appendNum($bits, $num)
|
||||||
{
|
{
|
||||||
if ($bits == 0)
|
if ($bits == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
$b = QRbitstream::newFromNum($bits, $num);
|
$b = QRbitstream::newFromNum($bits, $num);
|
||||||
|
|
||||||
if(is_null($b))
|
if(is_null($b))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
$ret = $this->append($b);
|
$ret = $this->append($b);
|
||||||
unset($b);
|
unset($b);
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function appendBytes($size, $data)
|
public function appendBytes($size, $data)
|
||||||
{
|
{
|
||||||
if ($size == 0)
|
if ($size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
$b = QRbitstream::newFromBytes($size, $data);
|
$b = QRbitstream::newFromBytes($size, $data);
|
||||||
|
|
||||||
if(is_null($b))
|
if(is_null($b))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
$ret = $this->append($b);
|
$ret = $this->append($b);
|
||||||
unset($b);
|
unset($b);
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function toByte()
|
public function toByte()
|
||||||
{
|
{
|
||||||
|
|
||||||
$size = $this->size();
|
$size = $this->size();
|
||||||
|
|
||||||
if($size == 0) {
|
if($size == 0) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = array_fill(0, (int)(($size + 7) / 8), 0);
|
$data = array_fill(0, (int)(($size + 7) / 8), 0);
|
||||||
$bytes = (int)($size / 8);
|
$bytes = (int)($size / 8);
|
||||||
|
|
||||||
$p = 0;
|
$p = 0;
|
||||||
|
|
||||||
for($i=0; $i<$bytes; $i++) {
|
for($i=0; $i<$bytes; $i++) {
|
||||||
$v = 0;
|
$v = 0;
|
||||||
for($j=0; $j<8; $j++) {
|
for($j=0; $j<8; $j++) {
|
||||||
$v = $v << 1;
|
$v = $v << 1;
|
||||||
$v |= $this->data[$p];
|
$v |= $this->data[$p];
|
||||||
$p++;
|
$p++;
|
||||||
}
|
}
|
||||||
$data[$i] = $v;
|
$data[$i] = $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($size & 7) {
|
if($size & 7) {
|
||||||
$v = 0;
|
$v = 0;
|
||||||
for($j=0; $j<($size & 7); $j++) {
|
for($j=0; $j<($size & 7); $j++) {
|
||||||
$v = $v << 1;
|
$v = $v << 1;
|
||||||
$v |= $this->data[$p];
|
$v |= $this->data[$p];
|
||||||
$p++;
|
$p++;
|
||||||
}
|
}
|
||||||
$data[$bytes] = $v;
|
$data[$bytes] = $v;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Config file, feel free to modify
|
* Config file, feel free to modify
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('QR_CACHEABLE', true); // use cache - more disk reads but less CPU power, masks and format templates are stored there
|
define('QR_CACHEABLE', true); // use cache - more disk reads but less CPU power, masks and format templates are stored there
|
||||||
define('QR_CACHE_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR); // used when QR_CACHEABLE === true
|
define('QR_CACHE_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR); // used when QR_CACHEABLE === true
|
||||||
define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR); // default error logs dir
|
define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR); // default error logs dir
|
||||||
|
|
||||||
define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
|
define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
|
||||||
define('QR_FIND_FROM_RANDOM', false); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
|
define('QR_FIND_FROM_RANDOM', false); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
|
||||||
define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
|
define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
|
||||||
|
|
||||||
define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
|
define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
|
||||||
|
|
|
@ -1,54 +1,54 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Common constants
|
* Common constants
|
||||||
*
|
*
|
||||||
* Based on libqrencode C library distributed under LGPL 2.1
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Encoding modes
|
// Encoding modes
|
||||||
|
|
||||||
define('QR_MODE_NUL', -1);
|
define('QR_MODE_NUL', -1);
|
||||||
define('QR_MODE_NUM', 0);
|
define('QR_MODE_NUM', 0);
|
||||||
define('QR_MODE_AN', 1);
|
define('QR_MODE_AN', 1);
|
||||||
define('QR_MODE_8', 2);
|
define('QR_MODE_8', 2);
|
||||||
define('QR_MODE_KANJI', 3);
|
define('QR_MODE_KANJI', 3);
|
||||||
define('QR_MODE_STRUCTURE', 4);
|
define('QR_MODE_STRUCTURE', 4);
|
||||||
|
|
||||||
// Levels of error correction.
|
// Levels of error correction.
|
||||||
|
|
||||||
define('QR_ECLEVEL_L', 0);
|
define('QR_ECLEVEL_L', 0);
|
||||||
define('QR_ECLEVEL_M', 1);
|
define('QR_ECLEVEL_M', 1);
|
||||||
define('QR_ECLEVEL_Q', 2);
|
define('QR_ECLEVEL_Q', 2);
|
||||||
define('QR_ECLEVEL_H', 3);
|
define('QR_ECLEVEL_H', 3);
|
||||||
|
|
||||||
// Supported output formats
|
// Supported output formats
|
||||||
|
|
||||||
define('QR_FORMAT_TEXT', 0);
|
define('QR_FORMAT_TEXT', 0);
|
||||||
define('QR_FORMAT_PNG', 1);
|
define('QR_FORMAT_PNG', 1);
|
||||||
|
|
||||||
class qrstr {
|
class qrstr {
|
||||||
public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
|
public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
|
||||||
$srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
|
$srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,95 +1,95 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Image output of code using GD2
|
* Image output of code using GD2
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('QR_IMAGE', true);
|
define('QR_IMAGE', true);
|
||||||
|
|
||||||
class QRimage {
|
class QRimage {
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
|
public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
|
||||||
{
|
{
|
||||||
$image = self::image($frame, $pixelPerPoint, $outerFrame);
|
$image = self::image($frame, $pixelPerPoint, $outerFrame);
|
||||||
|
|
||||||
if ($filename === false) {
|
if ($filename === false) {
|
||||||
Header("Content-type: image/png");
|
Header("Content-type: image/png");
|
||||||
ImagePng($image);
|
ImagePng($image);
|
||||||
} else {
|
} else {
|
||||||
if($saveandprint===TRUE){
|
if($saveandprint===TRUE){
|
||||||
ImagePng($image, $filename);
|
ImagePng($image, $filename);
|
||||||
header("Content-type: image/png");
|
header("Content-type: image/png");
|
||||||
ImagePng($image);
|
ImagePng($image);
|
||||||
}else{
|
}else{
|
||||||
ImagePng($image, $filename);
|
ImagePng($image, $filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDestroy($image);
|
ImageDestroy($image);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
|
public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
|
||||||
{
|
{
|
||||||
$image = self::image($frame, $pixelPerPoint, $outerFrame);
|
$image = self::image($frame, $pixelPerPoint, $outerFrame);
|
||||||
|
|
||||||
if ($filename === false) {
|
if ($filename === false) {
|
||||||
Header("Content-type: image/jpeg");
|
Header("Content-type: image/jpeg");
|
||||||
ImageJpeg($image, null, $q);
|
ImageJpeg($image, null, $q);
|
||||||
} else {
|
} else {
|
||||||
ImageJpeg($image, $filename, $q);
|
ImageJpeg($image, $filename, $q);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDestroy($image);
|
ImageDestroy($image);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
|
private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
|
||||||
{
|
{
|
||||||
$h = count($frame);
|
$h = count($frame);
|
||||||
$w = strlen($frame[0]);
|
$w = strlen($frame[0]);
|
||||||
|
|
||||||
$imgW = $w + 2*$outerFrame;
|
$imgW = $w + 2*$outerFrame;
|
||||||
$imgH = $h + 2*$outerFrame;
|
$imgH = $h + 2*$outerFrame;
|
||||||
|
|
||||||
$base_image =ImageCreate($imgW, $imgH);
|
$base_image =ImageCreate($imgW, $imgH);
|
||||||
|
|
||||||
$col[0] = ImageColorAllocate($base_image,255,255,255);
|
$col[0] = ImageColorAllocate($base_image,255,255,255);
|
||||||
$col[1] = ImageColorAllocate($base_image,0,0,0);
|
$col[1] = ImageColorAllocate($base_image,0,0,0);
|
||||||
|
|
||||||
imagefill($base_image, 0, 0, $col[0]);
|
imagefill($base_image, 0, 0, $col[0]);
|
||||||
|
|
||||||
for($y=0; $y<$h; $y++) {
|
for($y=0; $y<$h; $y++) {
|
||||||
for($x=0; $x<$w; $x++) {
|
for($x=0; $x<$w; $x++) {
|
||||||
if ($frame[$y][$x] == '1') {
|
if ($frame[$y][$x] == '1') {
|
||||||
ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
|
ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
|
$target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
|
||||||
ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
|
ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
|
||||||
ImageDestroy($base_image);
|
ImageDestroy($base_image);
|
||||||
|
|
||||||
return $target_image;
|
return $target_image;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,43 +1,43 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Root library file, prepares environment and includes dependencies
|
* Root library file, prepares environment and includes dependencies
|
||||||
*
|
*
|
||||||
* Based on libqrencode C library distributed under LGPL 2.1
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR;
|
$QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
// Required libs
|
// Required libs
|
||||||
|
|
||||||
include $QR_BASEDIR."qrconst.php";
|
include $QR_BASEDIR."qrconst.php";
|
||||||
include $QR_BASEDIR."qrconfig.php";
|
include $QR_BASEDIR."qrconfig.php";
|
||||||
include $QR_BASEDIR."qrtools.php";
|
include $QR_BASEDIR."qrtools.php";
|
||||||
include $QR_BASEDIR."qrspec.php";
|
include $QR_BASEDIR."qrspec.php";
|
||||||
include $QR_BASEDIR."qrimage.php";
|
include $QR_BASEDIR."qrimage.php";
|
||||||
include $QR_BASEDIR."qrinput.php";
|
include $QR_BASEDIR."qrinput.php";
|
||||||
include $QR_BASEDIR."qrbitstream.php";
|
include $QR_BASEDIR."qrbitstream.php";
|
||||||
include $QR_BASEDIR."qrsplit.php";
|
include $QR_BASEDIR."qrsplit.php";
|
||||||
include $QR_BASEDIR."qrrscode.php";
|
include $QR_BASEDIR."qrrscode.php";
|
||||||
include $QR_BASEDIR."qrmask.php";
|
include $QR_BASEDIR."qrmask.php";
|
||||||
include $QR_BASEDIR."qrencode.php";
|
include $QR_BASEDIR."qrencode.php";
|
||||||
|
|
||||||
|
|
|
@ -1,328 +1,328 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Masking
|
* Masking
|
||||||
*
|
*
|
||||||
* Based on libqrencode C library distributed under LGPL 2.1
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('N1', 3);
|
define('N1', 3);
|
||||||
define('N2', 3);
|
define('N2', 3);
|
||||||
define('N3', 40);
|
define('N3', 40);
|
||||||
define('N4', 10);
|
define('N4', 10);
|
||||||
|
|
||||||
class QRmask {
|
class QRmask {
|
||||||
|
|
||||||
public $runLength = array();
|
public $runLength = array();
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
|
$this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function writeFormatInformation($width, &$frame, $mask, $level)
|
public function writeFormatInformation($width, &$frame, $mask, $level)
|
||||||
{
|
{
|
||||||
$blacks = 0;
|
$blacks = 0;
|
||||||
$format = QRspec::getFormatInfo($mask, $level);
|
$format = QRspec::getFormatInfo($mask, $level);
|
||||||
|
|
||||||
for($i=0; $i<8; $i++) {
|
for($i=0; $i<8; $i++) {
|
||||||
if($format & 1) {
|
if($format & 1) {
|
||||||
$blacks += 2;
|
$blacks += 2;
|
||||||
$v = 0x85;
|
$v = 0x85;
|
||||||
} else {
|
} else {
|
||||||
$v = 0x84;
|
$v = 0x84;
|
||||||
}
|
}
|
||||||
|
|
||||||
$frame[8][$width - 1 - $i] = chr($v);
|
$frame[8][$width - 1 - $i] = chr($v);
|
||||||
if($i < 6) {
|
if($i < 6) {
|
||||||
$frame[$i][8] = chr($v);
|
$frame[$i][8] = chr($v);
|
||||||
} else {
|
} else {
|
||||||
$frame[$i + 1][8] = chr($v);
|
$frame[$i + 1][8] = chr($v);
|
||||||
}
|
}
|
||||||
$format = $format >> 1;
|
$format = $format >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for($i=0; $i<7; $i++) {
|
for($i=0; $i<7; $i++) {
|
||||||
if($format & 1) {
|
if($format & 1) {
|
||||||
$blacks += 2;
|
$blacks += 2;
|
||||||
$v = 0x85;
|
$v = 0x85;
|
||||||
} else {
|
} else {
|
||||||
$v = 0x84;
|
$v = 0x84;
|
||||||
}
|
}
|
||||||
|
|
||||||
$frame[$width - 7 + $i][8] = chr($v);
|
$frame[$width - 7 + $i][8] = chr($v);
|
||||||
if($i == 0) {
|
if($i == 0) {
|
||||||
$frame[8][7] = chr($v);
|
$frame[8][7] = chr($v);
|
||||||
} else {
|
} else {
|
||||||
$frame[8][6 - $i] = chr($v);
|
$frame[8][6 - $i] = chr($v);
|
||||||
}
|
}
|
||||||
|
|
||||||
$format = $format >> 1;
|
$format = $format >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $blacks;
|
return $blacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function mask0($x, $y) { return ($x+$y)&1; }
|
public function mask0($x, $y) { return ($x+$y)&1; }
|
||||||
public function mask1($x, $y) { return ($y&1); }
|
public function mask1($x, $y) { return ($y&1); }
|
||||||
public function mask2($x, $y) { return ($x%3); }
|
public function mask2($x, $y) { return ($x%3); }
|
||||||
public function mask3($x, $y) { return ($x+$y)%3; }
|
public function mask3($x, $y) { return ($x+$y)%3; }
|
||||||
public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
|
public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
|
||||||
public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
|
public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
|
||||||
public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
|
public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
|
||||||
public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
|
public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
private function generateMaskNo($maskNo, $width, $frame)
|
private function generateMaskNo($maskNo, $width, $frame)
|
||||||
{
|
{
|
||||||
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
|
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
|
||||||
|
|
||||||
for($y=0; $y<$width; $y++) {
|
for($y=0; $y<$width; $y++) {
|
||||||
for($x=0; $x<$width; $x++) {
|
for($x=0; $x<$width; $x++) {
|
||||||
if(ord($frame[$y][$x]) & 0x80) {
|
if(ord($frame[$y][$x]) & 0x80) {
|
||||||
$bitMask[$y][$x] = 0;
|
$bitMask[$y][$x] = 0;
|
||||||
} else {
|
} else {
|
||||||
$maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
|
$maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
|
||||||
$bitMask[$y][$x] = ($maskFunc == 0)?1:0;
|
$bitMask[$y][$x] = ($maskFunc == 0)?1:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bitMask;
|
return $bitMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function serial($bitFrame)
|
public static function serial($bitFrame)
|
||||||
{
|
{
|
||||||
$codeArr = array();
|
$codeArr = array();
|
||||||
|
|
||||||
foreach ($bitFrame as $line)
|
foreach ($bitFrame as $line)
|
||||||
$codeArr[] = join('', $line);
|
$codeArr[] = join('', $line);
|
||||||
|
|
||||||
return gzcompress(join("\n", $codeArr), 9);
|
return gzcompress(join("\n", $codeArr), 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function unserial($code)
|
public static function unserial($code)
|
||||||
{
|
{
|
||||||
$codeArr = array();
|
$codeArr = array();
|
||||||
|
|
||||||
$codeLines = explode("\n", gzuncompress($code));
|
$codeLines = explode("\n", gzuncompress($code));
|
||||||
foreach ($codeLines as $line)
|
foreach ($codeLines as $line)
|
||||||
$codeArr[] = str_split($line);
|
$codeArr[] = str_split($line);
|
||||||
|
|
||||||
return $codeArr;
|
return $codeArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
|
public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
|
||||||
{
|
{
|
||||||
$b = 0;
|
$b = 0;
|
||||||
$bitMask = array();
|
$bitMask = array();
|
||||||
|
|
||||||
$fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
|
$fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
|
||||||
|
|
||||||
if (QR_CACHEABLE) {
|
if (QR_CACHEABLE) {
|
||||||
if (file_exists($fileName)) {
|
if (file_exists($fileName)) {
|
||||||
$bitMask = self::unserial(file_get_contents($fileName));
|
$bitMask = self::unserial(file_get_contents($fileName));
|
||||||
} else {
|
} else {
|
||||||
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
|
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
|
||||||
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
|
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
|
||||||
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
|
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
|
||||||
file_put_contents($fileName, self::serial($bitMask));
|
file_put_contents($fileName, self::serial($bitMask));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
|
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($maskGenOnly)
|
if ($maskGenOnly)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$d = $s;
|
$d = $s;
|
||||||
|
|
||||||
for($y=0; $y<$width; $y++) {
|
for($y=0; $y<$width; $y++) {
|
||||||
for($x=0; $x<$width; $x++) {
|
for($x=0; $x<$width; $x++) {
|
||||||
if($bitMask[$y][$x] == 1) {
|
if($bitMask[$y][$x] == 1) {
|
||||||
$d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
|
$d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
|
||||||
}
|
}
|
||||||
$b += (int)(ord($d[$y][$x]) & 1);
|
$b += (int)(ord($d[$y][$x]) & 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $b;
|
return $b;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function makeMask($width, $frame, $maskNo, $level)
|
public function makeMask($width, $frame, $maskNo, $level)
|
||||||
{
|
{
|
||||||
$masked = array_fill(0, $width, str_repeat("\0", $width));
|
$masked = array_fill(0, $width, str_repeat("\0", $width));
|
||||||
$this->makeMaskNo($maskNo, $width, $frame, $masked);
|
$this->makeMaskNo($maskNo, $width, $frame, $masked);
|
||||||
$this->writeFormatInformation($width, $masked, $maskNo, $level);
|
$this->writeFormatInformation($width, $masked, $maskNo, $level);
|
||||||
|
|
||||||
return $masked;
|
return $masked;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function calcN1N3($length)
|
public function calcN1N3($length)
|
||||||
{
|
{
|
||||||
$demerit = 0;
|
$demerit = 0;
|
||||||
|
|
||||||
for($i=0; $i<$length; $i++) {
|
for($i=0; $i<$length; $i++) {
|
||||||
|
|
||||||
if($this->runLength[$i] >= 5) {
|
if($this->runLength[$i] >= 5) {
|
||||||
$demerit += (N1 + ($this->runLength[$i] - 5));
|
$demerit += (N1 + ($this->runLength[$i] - 5));
|
||||||
}
|
}
|
||||||
if($i & 1) {
|
if($i & 1) {
|
||||||
if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
|
if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
|
||||||
$fact = (int)($this->runLength[$i] / 3);
|
$fact = (int)($this->runLength[$i] / 3);
|
||||||
if(($this->runLength[$i-2] == $fact) &&
|
if(($this->runLength[$i-2] == $fact) &&
|
||||||
($this->runLength[$i-1] == $fact) &&
|
($this->runLength[$i-1] == $fact) &&
|
||||||
($this->runLength[$i+1] == $fact) &&
|
($this->runLength[$i+1] == $fact) &&
|
||||||
($this->runLength[$i+2] == $fact)) {
|
($this->runLength[$i+2] == $fact)) {
|
||||||
if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
|
if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
|
||||||
$demerit += N3;
|
$demerit += N3;
|
||||||
} else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
|
} else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
|
||||||
$demerit += N3;
|
$demerit += N3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $demerit;
|
return $demerit;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function evaluateSymbol($width, $frame)
|
public function evaluateSymbol($width, $frame)
|
||||||
{
|
{
|
||||||
$head = 0;
|
$head = 0;
|
||||||
$demerit = 0;
|
$demerit = 0;
|
||||||
|
|
||||||
for($y=0; $y<$width; $y++) {
|
for($y=0; $y<$width; $y++) {
|
||||||
$head = 0;
|
$head = 0;
|
||||||
$this->runLength[0] = 1;
|
$this->runLength[0] = 1;
|
||||||
|
|
||||||
$frameY = $frame[$y];
|
$frameY = $frame[$y];
|
||||||
|
|
||||||
if ($y>0)
|
if ($y>0)
|
||||||
$frameYM = $frame[$y-1];
|
$frameYM = $frame[$y-1];
|
||||||
|
|
||||||
for($x=0; $x<$width; $x++) {
|
for($x=0; $x<$width; $x++) {
|
||||||
if(($x > 0) && ($y > 0)) {
|
if(($x > 0) && ($y > 0)) {
|
||||||
$b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
|
$b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
|
||||||
$w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
|
$w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
|
||||||
|
|
||||||
if(($b22 | ($w22 ^ 1))&1) {
|
if(($b22 | ($w22 ^ 1))&1) {
|
||||||
$demerit += N2;
|
$demerit += N2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(($x == 0) && (ord($frameY[$x]) & 1)) {
|
if(($x == 0) && (ord($frameY[$x]) & 1)) {
|
||||||
$this->runLength[0] = -1;
|
$this->runLength[0] = -1;
|
||||||
$head = 1;
|
$head = 1;
|
||||||
$this->runLength[$head] = 1;
|
$this->runLength[$head] = 1;
|
||||||
} else if($x > 0) {
|
} else if($x > 0) {
|
||||||
if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
|
if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
|
||||||
$head++;
|
$head++;
|
||||||
$this->runLength[$head] = 1;
|
$this->runLength[$head] = 1;
|
||||||
} else {
|
} else {
|
||||||
$this->runLength[$head]++;
|
$this->runLength[$head]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$demerit += $this->calcN1N3($head+1);
|
$demerit += $this->calcN1N3($head+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for($x=0; $x<$width; $x++) {
|
for($x=0; $x<$width; $x++) {
|
||||||
$head = 0;
|
$head = 0;
|
||||||
$this->runLength[0] = 1;
|
$this->runLength[0] = 1;
|
||||||
|
|
||||||
for($y=0; $y<$width; $y++) {
|
for($y=0; $y<$width; $y++) {
|
||||||
if($y == 0 && (ord($frame[$y][$x]) & 1)) {
|
if($y == 0 && (ord($frame[$y][$x]) & 1)) {
|
||||||
$this->runLength[0] = -1;
|
$this->runLength[0] = -1;
|
||||||
$head = 1;
|
$head = 1;
|
||||||
$this->runLength[$head] = 1;
|
$this->runLength[$head] = 1;
|
||||||
} else if($y > 0) {
|
} else if($y > 0) {
|
||||||
if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
|
if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
|
||||||
$head++;
|
$head++;
|
||||||
$this->runLength[$head] = 1;
|
$this->runLength[$head] = 1;
|
||||||
} else {
|
} else {
|
||||||
$this->runLength[$head]++;
|
$this->runLength[$head]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$demerit += $this->calcN1N3($head+1);
|
$demerit += $this->calcN1N3($head+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $demerit;
|
return $demerit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function mask($width, $frame, $level)
|
public function mask($width, $frame, $level)
|
||||||
{
|
{
|
||||||
$minDemerit = PHP_INT_MAX;
|
$minDemerit = PHP_INT_MAX;
|
||||||
$bestMaskNum = 0;
|
$bestMaskNum = 0;
|
||||||
$bestMask = array();
|
$bestMask = array();
|
||||||
|
|
||||||
$checked_masks = array(0,1,2,3,4,5,6,7);
|
$checked_masks = array(0,1,2,3,4,5,6,7);
|
||||||
|
|
||||||
if (QR_FIND_FROM_RANDOM !== false) {
|
if (QR_FIND_FROM_RANDOM !== false) {
|
||||||
|
|
||||||
$howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
|
$howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
|
||||||
for ($i = 0; $i < $howManuOut; $i++) {
|
for ($i = 0; $i < $howManuOut; $i++) {
|
||||||
$remPos = rand (0, count($checked_masks)-1);
|
$remPos = rand (0, count($checked_masks)-1);
|
||||||
unset($checked_masks[$remPos]);
|
unset($checked_masks[$remPos]);
|
||||||
$checked_masks = array_values($checked_masks);
|
$checked_masks = array_values($checked_masks);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$bestMask = $frame;
|
$bestMask = $frame;
|
||||||
|
|
||||||
foreach($checked_masks as $i) {
|
foreach($checked_masks as $i) {
|
||||||
$mask = array_fill(0, $width, str_repeat("\0", $width));
|
$mask = array_fill(0, $width, str_repeat("\0", $width));
|
||||||
|
|
||||||
$demerit = 0;
|
$demerit = 0;
|
||||||
$blacks = 0;
|
$blacks = 0;
|
||||||
$blacks = $this->makeMaskNo($i, $width, $frame, $mask);
|
$blacks = $this->makeMaskNo($i, $width, $frame, $mask);
|
||||||
$blacks += $this->writeFormatInformation($width, $mask, $i, $level);
|
$blacks += $this->writeFormatInformation($width, $mask, $i, $level);
|
||||||
$blacks = (int)(100 * $blacks / ($width * $width));
|
$blacks = (int)(100 * $blacks / ($width * $width));
|
||||||
$demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
|
$demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
|
||||||
$demerit += $this->evaluateSymbol($width, $mask);
|
$demerit += $this->evaluateSymbol($width, $mask);
|
||||||
|
|
||||||
if($demerit < $minDemerit) {
|
if($demerit < $minDemerit) {
|
||||||
$minDemerit = $demerit;
|
$minDemerit = $demerit;
|
||||||
$bestMask = $mask;
|
$bestMask = $mask;
|
||||||
$bestMaskNum = $i;
|
$bestMaskNum = $i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bestMask;
|
return $bestMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,210 +1,210 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Reed-Solomon error correction support
|
* Reed-Solomon error correction support
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
||||||
* (libfec is released under the GNU Lesser General Public License.)
|
* (libfec is released under the GNU Lesser General Public License.)
|
||||||
*
|
*
|
||||||
* Based on libqrencode C library distributed under LGPL 2.1
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QRrsItem {
|
class QRrsItem {
|
||||||
|
|
||||||
public $mm; // Bits per symbol
|
public $mm; // Bits per symbol
|
||||||
public $nn; // Symbols per block (= (1<<mm)-1)
|
public $nn; // Symbols per block (= (1<<mm)-1)
|
||||||
public $alpha_to = array(); // log lookup table
|
public $alpha_to = array(); // log lookup table
|
||||||
public $index_of = array(); // Antilog lookup table
|
public $index_of = array(); // Antilog lookup table
|
||||||
public $genpoly = array(); // Generator polynomial
|
public $genpoly = array(); // Generator polynomial
|
||||||
public $nroots; // Number of generator roots = number of parity symbols
|
public $nroots; // Number of generator roots = number of parity symbols
|
||||||
public $fcr; // First consecutive root, index form
|
public $fcr; // First consecutive root, index form
|
||||||
public $prim; // Primitive element, index form
|
public $prim; // Primitive element, index form
|
||||||
public $iprim; // prim-th root of 1, index form
|
public $iprim; // prim-th root of 1, index form
|
||||||
public $pad; // Padding bytes in shortened block
|
public $pad; // Padding bytes in shortened block
|
||||||
public $gfpoly;
|
public $gfpoly;
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function modnn($x)
|
public function modnn($x)
|
||||||
{
|
{
|
||||||
while ($x >= $this->nn) {
|
while ($x >= $this->nn) {
|
||||||
$x -= $this->nn;
|
$x -= $this->nn;
|
||||||
$x = ($x >> $this->mm) + ($x & $this->nn);
|
$x = ($x >> $this->mm) + ($x & $this->nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
|
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
|
||||||
{
|
{
|
||||||
// Common code for intializing a Reed-Solomon control block (char or int symbols)
|
// Common code for intializing a Reed-Solomon control block (char or int symbols)
|
||||||
// Copyright 2004 Phil Karn, KA9Q
|
// Copyright 2004 Phil Karn, KA9Q
|
||||||
// May be used under the terms of the GNU Lesser General Public License (LGPL)
|
// May be used under the terms of the GNU Lesser General Public License (LGPL)
|
||||||
|
|
||||||
$rs = null;
|
$rs = null;
|
||||||
|
|
||||||
// Check parameter ranges
|
// Check parameter ranges
|
||||||
if($symsize < 0 || $symsize > 8) return $rs;
|
if($symsize < 0 || $symsize > 8) return $rs;
|
||||||
if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;
|
if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;
|
||||||
if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;
|
if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;
|
||||||
if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!
|
if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!
|
||||||
if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
|
if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
|
||||||
|
|
||||||
$rs = new QRrsItem();
|
$rs = new QRrsItem();
|
||||||
$rs->mm = $symsize;
|
$rs->mm = $symsize;
|
||||||
$rs->nn = (1<<$symsize)-1;
|
$rs->nn = (1<<$symsize)-1;
|
||||||
$rs->pad = $pad;
|
$rs->pad = $pad;
|
||||||
|
|
||||||
$rs->alpha_to = array_fill(0, $rs->nn+1, 0);
|
$rs->alpha_to = array_fill(0, $rs->nn+1, 0);
|
||||||
$rs->index_of = array_fill(0, $rs->nn+1, 0);
|
$rs->index_of = array_fill(0, $rs->nn+1, 0);
|
||||||
|
|
||||||
// PHP style macro replacement ;)
|
// PHP style macro replacement ;)
|
||||||
$NN =& $rs->nn;
|
$NN =& $rs->nn;
|
||||||
$A0 =& $NN;
|
$A0 =& $NN;
|
||||||
|
|
||||||
// Generate Galois field lookup tables
|
// Generate Galois field lookup tables
|
||||||
$rs->index_of[0] = $A0; // log(zero) = -inf
|
$rs->index_of[0] = $A0; // log(zero) = -inf
|
||||||
$rs->alpha_to[$A0] = 0; // alpha**-inf = 0
|
$rs->alpha_to[$A0] = 0; // alpha**-inf = 0
|
||||||
$sr = 1;
|
$sr = 1;
|
||||||
|
|
||||||
for($i=0; $i<$rs->nn; $i++) {
|
for($i=0; $i<$rs->nn; $i++) {
|
||||||
$rs->index_of[$sr] = $i;
|
$rs->index_of[$sr] = $i;
|
||||||
$rs->alpha_to[$i] = $sr;
|
$rs->alpha_to[$i] = $sr;
|
||||||
$sr <<= 1;
|
$sr <<= 1;
|
||||||
if($sr & (1<<$symsize)) {
|
if($sr & (1<<$symsize)) {
|
||||||
$sr ^= $gfpoly;
|
$sr ^= $gfpoly;
|
||||||
}
|
}
|
||||||
$sr &= $rs->nn;
|
$sr &= $rs->nn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($sr != 1){
|
if($sr != 1){
|
||||||
// field generator polynomial is not primitive!
|
// field generator polynomial is not primitive!
|
||||||
$rs = NULL;
|
$rs = NULL;
|
||||||
return $rs;
|
return $rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Form RS code generator polynomial from its roots */
|
/* Form RS code generator polynomial from its roots */
|
||||||
$rs->genpoly = array_fill(0, $nroots+1, 0);
|
$rs->genpoly = array_fill(0, $nroots+1, 0);
|
||||||
|
|
||||||
$rs->fcr = $fcr;
|
$rs->fcr = $fcr;
|
||||||
$rs->prim = $prim;
|
$rs->prim = $prim;
|
||||||
$rs->nroots = $nroots;
|
$rs->nroots = $nroots;
|
||||||
$rs->gfpoly = $gfpoly;
|
$rs->gfpoly = $gfpoly;
|
||||||
|
|
||||||
/* Find prim-th root of 1, used in decoding */
|
/* Find prim-th root of 1, used in decoding */
|
||||||
for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
|
for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
|
||||||
; // intentional empty-body loop!
|
; // intentional empty-body loop!
|
||||||
|
|
||||||
$rs->iprim = (int)($iprim / $prim);
|
$rs->iprim = (int)($iprim / $prim);
|
||||||
$rs->genpoly[0] = 1;
|
$rs->genpoly[0] = 1;
|
||||||
|
|
||||||
for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
|
for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
|
||||||
$rs->genpoly[$i+1] = 1;
|
$rs->genpoly[$i+1] = 1;
|
||||||
|
|
||||||
// Multiply rs->genpoly[] by @**(root + x)
|
// Multiply rs->genpoly[] by @**(root + x)
|
||||||
for ($j = $i; $j > 0; $j--) {
|
for ($j = $i; $j > 0; $j--) {
|
||||||
if ($rs->genpoly[$j] != 0) {
|
if ($rs->genpoly[$j] != 0) {
|
||||||
$rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
|
$rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
|
||||||
} else {
|
} else {
|
||||||
$rs->genpoly[$j] = $rs->genpoly[$j-1];
|
$rs->genpoly[$j] = $rs->genpoly[$j-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// rs->genpoly[0] can never be zero
|
// rs->genpoly[0] can never be zero
|
||||||
$rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
|
$rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert rs->genpoly[] to index form for quicker encoding
|
// convert rs->genpoly[] to index form for quicker encoding
|
||||||
for ($i = 0; $i <= $nroots; $i++)
|
for ($i = 0; $i <= $nroots; $i++)
|
||||||
$rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
|
$rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
|
||||||
|
|
||||||
return $rs;
|
return $rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function encode_rs_char($data, &$parity)
|
public function encode_rs_char($data, &$parity)
|
||||||
{
|
{
|
||||||
$MM =& $this->mm;
|
$MM =& $this->mm;
|
||||||
$NN =& $this->nn;
|
$NN =& $this->nn;
|
||||||
$ALPHA_TO =& $this->alpha_to;
|
$ALPHA_TO =& $this->alpha_to;
|
||||||
$INDEX_OF =& $this->index_of;
|
$INDEX_OF =& $this->index_of;
|
||||||
$GENPOLY =& $this->genpoly;
|
$GENPOLY =& $this->genpoly;
|
||||||
$NROOTS =& $this->nroots;
|
$NROOTS =& $this->nroots;
|
||||||
$FCR =& $this->fcr;
|
$FCR =& $this->fcr;
|
||||||
$PRIM =& $this->prim;
|
$PRIM =& $this->prim;
|
||||||
$IPRIM =& $this->iprim;
|
$IPRIM =& $this->iprim;
|
||||||
$PAD =& $this->pad;
|
$PAD =& $this->pad;
|
||||||
$A0 =& $NN;
|
$A0 =& $NN;
|
||||||
|
|
||||||
$parity = array_fill(0, $NROOTS, 0);
|
$parity = array_fill(0, $NROOTS, 0);
|
||||||
|
|
||||||
for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
|
for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
|
||||||
|
|
||||||
$feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
|
$feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
|
||||||
if($feedback != $A0) {
|
if($feedback != $A0) {
|
||||||
// feedback term is non-zero
|
// feedback term is non-zero
|
||||||
|
|
||||||
// This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
|
// This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
|
||||||
// always be for the polynomials constructed by init_rs()
|
// always be for the polynomials constructed by init_rs()
|
||||||
$feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
|
$feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
|
||||||
|
|
||||||
for($j=1;$j<$NROOTS;$j++) {
|
for($j=1;$j<$NROOTS;$j++) {
|
||||||
$parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
|
$parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift
|
// Shift
|
||||||
array_shift($parity);
|
array_shift($parity);
|
||||||
if($feedback != $A0) {
|
if($feedback != $A0) {
|
||||||
array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
|
array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
|
||||||
} else {
|
} else {
|
||||||
array_push($parity, 0);
|
array_push($parity, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//##########################################################################
|
//##########################################################################
|
||||||
|
|
||||||
class QRrs {
|
class QRrs {
|
||||||
|
|
||||||
public static $items = array();
|
public static $items = array();
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
|
public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
|
||||||
{
|
{
|
||||||
foreach(self::$items as $rs) {
|
foreach(self::$items as $rs) {
|
||||||
if($rs->pad != $pad) continue;
|
if($rs->pad != $pad) continue;
|
||||||
if($rs->nroots != $nroots) continue;
|
if($rs->nroots != $nroots) continue;
|
||||||
if($rs->mm != $symsize) continue;
|
if($rs->mm != $symsize) continue;
|
||||||
if($rs->gfpoly != $gfpoly) continue;
|
if($rs->gfpoly != $gfpoly) continue;
|
||||||
if($rs->fcr != $fcr) continue;
|
if($rs->fcr != $fcr) continue;
|
||||||
if($rs->prim != $prim) continue;
|
if($rs->prim != $prim) continue;
|
||||||
|
|
||||||
return $rs;
|
return $rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
|
$rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
|
||||||
array_unshift(self::$items, $rs);
|
array_unshift(self::$items, $rs);
|
||||||
|
|
||||||
return $rs;
|
return $rs;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,311 +1,311 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Input splitting classes
|
* Input splitting classes
|
||||||
*
|
*
|
||||||
* Based on libqrencode C library distributed under LGPL 2.1
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* The following data / specifications are taken from
|
* The following data / specifications are taken from
|
||||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||||
* or
|
* or
|
||||||
* "Automatic identification and data capture techniques --
|
* "Automatic identification and data capture techniques --
|
||||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
class QRsplit {
|
class QRsplit {
|
||||||
|
|
||||||
public $dataStr = '';
|
public $dataStr = '';
|
||||||
public $input;
|
public $input;
|
||||||
public $modeHint;
|
public $modeHint;
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function __construct($dataStr, $input, $modeHint)
|
public function __construct($dataStr, $input, $modeHint)
|
||||||
{
|
{
|
||||||
$this->dataStr = $dataStr;
|
$this->dataStr = $dataStr;
|
||||||
$this->input = $input;
|
$this->input = $input;
|
||||||
$this->modeHint = $modeHint;
|
$this->modeHint = $modeHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function isdigitat($str, $pos)
|
public static function isdigitat($str, $pos)
|
||||||
{
|
{
|
||||||
if ($pos >= strlen($str))
|
if ($pos >= strlen($str))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
|
return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function isalnumat($str, $pos)
|
public static function isalnumat($str, $pos)
|
||||||
{
|
{
|
||||||
if ($pos >= strlen($str))
|
if ($pos >= strlen($str))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
|
return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function identifyMode($pos)
|
public function identifyMode($pos)
|
||||||
{
|
{
|
||||||
if ($pos >= strlen($this->dataStr))
|
if ($pos >= strlen($this->dataStr))
|
||||||
return QR_MODE_NUL;
|
return QR_MODE_NUL;
|
||||||
|
|
||||||
$c = $this->dataStr[$pos];
|
$c = $this->dataStr[$pos];
|
||||||
|
|
||||||
if(self::isdigitat($this->dataStr, $pos)) {
|
if(self::isdigitat($this->dataStr, $pos)) {
|
||||||
return QR_MODE_NUM;
|
return QR_MODE_NUM;
|
||||||
} else if(self::isalnumat($this->dataStr, $pos)) {
|
} else if(self::isalnumat($this->dataStr, $pos)) {
|
||||||
return QR_MODE_AN;
|
return QR_MODE_AN;
|
||||||
} else if($this->modeHint == QR_MODE_KANJI) {
|
} else if($this->modeHint == QR_MODE_KANJI) {
|
||||||
|
|
||||||
if ($pos+1 < strlen($this->dataStr))
|
if ($pos+1 < strlen($this->dataStr))
|
||||||
{
|
{
|
||||||
$d = $this->dataStr[$pos+1];
|
$d = $this->dataStr[$pos+1];
|
||||||
$word = (ord($c) << 8) | ord($d);
|
$word = (ord($c) << 8) | ord($d);
|
||||||
if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
|
if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
|
||||||
return QR_MODE_KANJI;
|
return QR_MODE_KANJI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QR_MODE_8;
|
return QR_MODE_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function eatNum()
|
public function eatNum()
|
||||||
{
|
{
|
||||||
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
||||||
|
|
||||||
$p = 0;
|
$p = 0;
|
||||||
while(self::isdigitat($this->dataStr, $p)) {
|
while(self::isdigitat($this->dataStr, $p)) {
|
||||||
$p++;
|
$p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$run = $p;
|
$run = $p;
|
||||||
$mode = $this->identifyMode($p);
|
$mode = $this->identifyMode($p);
|
||||||
|
|
||||||
if($mode == QR_MODE_8) {
|
if($mode == QR_MODE_8) {
|
||||||
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
|
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
|
||||||
+ QRinput::estimateBitsMode8(1) // + 4 + l8
|
+ QRinput::estimateBitsMode8(1) // + 4 + l8
|
||||||
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
|
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
|
||||||
if($dif > 0) {
|
if($dif > 0) {
|
||||||
return $this->eat8();
|
return $this->eat8();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($mode == QR_MODE_AN) {
|
if($mode == QR_MODE_AN) {
|
||||||
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
|
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
|
||||||
+ QRinput::estimateBitsModeAn(1) // + 4 + la
|
+ QRinput::estimateBitsModeAn(1) // + 4 + la
|
||||||
- QRinput::estimateBitsModeAn($run + 1);// - 4 - la
|
- QRinput::estimateBitsModeAn($run + 1);// - 4 - la
|
||||||
if($dif > 0) {
|
if($dif > 0) {
|
||||||
return $this->eatAn();
|
return $this->eatAn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
|
$ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
|
||||||
if($ret < 0)
|
if($ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return $run;
|
return $run;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function eatAn()
|
public function eatAn()
|
||||||
{
|
{
|
||||||
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
|
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
|
||||||
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
||||||
|
|
||||||
$p = 0;
|
$p = 0;
|
||||||
|
|
||||||
while(self::isalnumat($this->dataStr, $p)) {
|
while(self::isalnumat($this->dataStr, $p)) {
|
||||||
if(self::isdigitat($this->dataStr, $p)) {
|
if(self::isdigitat($this->dataStr, $p)) {
|
||||||
$q = $p;
|
$q = $p;
|
||||||
while(self::isdigitat($this->dataStr, $q)) {
|
while(self::isdigitat($this->dataStr, $q)) {
|
||||||
$q++;
|
$q++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dif = QRinput::estimateBitsModeAn($p) // + 4 + la
|
$dif = QRinput::estimateBitsModeAn($p) // + 4 + la
|
||||||
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
|
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
|
||||||
- QRinput::estimateBitsModeAn($q); // - 4 - la
|
- QRinput::estimateBitsModeAn($q); // - 4 - la
|
||||||
|
|
||||||
if($dif < 0) {
|
if($dif < 0) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
$p = $q;
|
$p = $q;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$p++;
|
$p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$run = $p;
|
$run = $p;
|
||||||
|
|
||||||
if(!self::isalnumat($this->dataStr, $p)) {
|
if(!self::isalnumat($this->dataStr, $p)) {
|
||||||
$dif = QRinput::estimateBitsModeAn($run) + 4 + $la
|
$dif = QRinput::estimateBitsModeAn($run) + 4 + $la
|
||||||
+ QRinput::estimateBitsMode8(1) // + 4 + l8
|
+ QRinput::estimateBitsMode8(1) // + 4 + l8
|
||||||
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
|
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
|
||||||
if($dif > 0) {
|
if($dif > 0) {
|
||||||
return $this->eat8();
|
return $this->eat8();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
|
$ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
|
||||||
if($ret < 0)
|
if($ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return $run;
|
return $run;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function eatKanji()
|
public function eatKanji()
|
||||||
{
|
{
|
||||||
$p = 0;
|
$p = 0;
|
||||||
|
|
||||||
while($this->identifyMode($p) == QR_MODE_KANJI) {
|
while($this->identifyMode($p) == QR_MODE_KANJI) {
|
||||||
$p += 2;
|
$p += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
|
$ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
|
||||||
if($ret < 0)
|
if($ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function eat8()
|
public function eat8()
|
||||||
{
|
{
|
||||||
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
|
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
|
||||||
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
||||||
|
|
||||||
$p = 1;
|
$p = 1;
|
||||||
$dataStrLen = strlen($this->dataStr);
|
$dataStrLen = strlen($this->dataStr);
|
||||||
|
|
||||||
while($p < $dataStrLen) {
|
while($p < $dataStrLen) {
|
||||||
|
|
||||||
$mode = $this->identifyMode($p);
|
$mode = $this->identifyMode($p);
|
||||||
if($mode == QR_MODE_KANJI) {
|
if($mode == QR_MODE_KANJI) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if($mode == QR_MODE_NUM) {
|
if($mode == QR_MODE_NUM) {
|
||||||
$q = $p;
|
$q = $p;
|
||||||
while(self::isdigitat($this->dataStr, $q)) {
|
while(self::isdigitat($this->dataStr, $q)) {
|
||||||
$q++;
|
$q++;
|
||||||
}
|
}
|
||||||
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
|
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
|
||||||
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
|
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
|
||||||
- QRinput::estimateBitsMode8($q); // - 4 - l8
|
- QRinput::estimateBitsMode8($q); // - 4 - l8
|
||||||
if($dif < 0) {
|
if($dif < 0) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
$p = $q;
|
$p = $q;
|
||||||
}
|
}
|
||||||
} else if($mode == QR_MODE_AN) {
|
} else if($mode == QR_MODE_AN) {
|
||||||
$q = $p;
|
$q = $p;
|
||||||
while(self::isalnumat($this->dataStr, $q)) {
|
while(self::isalnumat($this->dataStr, $q)) {
|
||||||
$q++;
|
$q++;
|
||||||
}
|
}
|
||||||
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
|
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
|
||||||
+ QRinput::estimateBitsModeAn($q - $p) + 4 + $la
|
+ QRinput::estimateBitsModeAn($q - $p) + 4 + $la
|
||||||
- QRinput::estimateBitsMode8($q); // - 4 - l8
|
- QRinput::estimateBitsMode8($q); // - 4 - l8
|
||||||
if($dif < 0) {
|
if($dif < 0) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
$p = $q;
|
$p = $q;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$p++;
|
$p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$run = $p;
|
$run = $p;
|
||||||
$ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
|
$ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
|
||||||
|
|
||||||
if($ret < 0)
|
if($ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return $run;
|
return $run;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function splitString()
|
public function splitString()
|
||||||
{
|
{
|
||||||
while (strlen($this->dataStr) > 0)
|
while (strlen($this->dataStr) > 0)
|
||||||
{
|
{
|
||||||
if($this->dataStr == '')
|
if($this->dataStr == '')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
$mode = $this->identifyMode(0);
|
$mode = $this->identifyMode(0);
|
||||||
|
|
||||||
switch ($mode) {
|
switch ($mode) {
|
||||||
case QR_MODE_NUM: $length = $this->eatNum(); break;
|
case QR_MODE_NUM: $length = $this->eatNum(); break;
|
||||||
case QR_MODE_AN: $length = $this->eatAn(); break;
|
case QR_MODE_AN: $length = $this->eatAn(); break;
|
||||||
case QR_MODE_KANJI:
|
case QR_MODE_KANJI:
|
||||||
if ($this->modeHint == QR_MODE_KANJI)
|
if ($this->modeHint == QR_MODE_KANJI)
|
||||||
$length = $this->eatKanji();
|
$length = $this->eatKanji();
|
||||||
else $length = $this->eat8();
|
else $length = $this->eat8();
|
||||||
break;
|
break;
|
||||||
default: $length = $this->eat8(); break;
|
default: $length = $this->eat8(); break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($length == 0) return 0;
|
if($length == 0) return 0;
|
||||||
if($length < 0) return -1;
|
if($length < 0) return -1;
|
||||||
|
|
||||||
$this->dataStr = substr($this->dataStr, $length);
|
$this->dataStr = substr($this->dataStr, $length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public function toUpper()
|
public function toUpper()
|
||||||
{
|
{
|
||||||
$stringLen = strlen($this->dataStr);
|
$stringLen = strlen($this->dataStr);
|
||||||
$p = 0;
|
$p = 0;
|
||||||
|
|
||||||
while ($p<$stringLen) {
|
while ($p<$stringLen) {
|
||||||
$mode = self::identifyMode(substr($this->dataStr, $p));
|
$mode = self::identifyMode(substr($this->dataStr, $p));
|
||||||
if($mode == QR_MODE_KANJI) {
|
if($mode == QR_MODE_KANJI) {
|
||||||
$p += 2;
|
$p += 2;
|
||||||
} else {
|
} else {
|
||||||
if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
|
if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
|
||||||
$this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
|
$this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
|
||||||
}
|
}
|
||||||
$p++;
|
$p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->dataStr;
|
return $this->dataStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
|
public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
|
||||||
{
|
{
|
||||||
if(is_null($string) || $string == '\0' || $string == '') {
|
if(is_null($string) || $string == '\0' || $string == '') {
|
||||||
throw new Exception('empty string!!!');
|
throw new Exception('empty string!!!');
|
||||||
}
|
}
|
||||||
|
|
||||||
$split = new QRsplit($string, $input, $modeHint);
|
$split = new QRsplit($string, $input, $modeHint);
|
||||||
|
|
||||||
if(!$casesensitive)
|
if(!$casesensitive)
|
||||||
$split->toUpper();
|
$split->toUpper();
|
||||||
|
|
||||||
return $split->splitString();
|
return $split->splitString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,172 +1,172 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Toolset, handy and debug utilites.
|
* Toolset, handy and debug utilites.
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QRtools {
|
class QRtools {
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function binarize($frame)
|
public static function binarize($frame)
|
||||||
{
|
{
|
||||||
$len = count($frame);
|
$len = count($frame);
|
||||||
foreach ($frame as &$frameLine) {
|
foreach ($frame as &$frameLine) {
|
||||||
|
|
||||||
for($i=0; $i<$len; $i++) {
|
for($i=0; $i<$len; $i++) {
|
||||||
$frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
|
$frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $frame;
|
return $frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
|
public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
|
||||||
{
|
{
|
||||||
$barcode_array = array();
|
$barcode_array = array();
|
||||||
|
|
||||||
if (!is_array($mode))
|
if (!is_array($mode))
|
||||||
$mode = explode(',', $mode);
|
$mode = explode(',', $mode);
|
||||||
|
|
||||||
$eccLevel = 'L';
|
$eccLevel = 'L';
|
||||||
|
|
||||||
if (count($mode) > 1) {
|
if (count($mode) > 1) {
|
||||||
$eccLevel = $mode[1];
|
$eccLevel = $mode[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
$qrTab = QRcode::text($code, false, $eccLevel);
|
$qrTab = QRcode::text($code, false, $eccLevel);
|
||||||
$size = count($qrTab);
|
$size = count($qrTab);
|
||||||
|
|
||||||
$barcode_array['num_rows'] = $size;
|
$barcode_array['num_rows'] = $size;
|
||||||
$barcode_array['num_cols'] = $size;
|
$barcode_array['num_cols'] = $size;
|
||||||
$barcode_array['bcode'] = array();
|
$barcode_array['bcode'] = array();
|
||||||
|
|
||||||
foreach ($qrTab as $line) {
|
foreach ($qrTab as $line) {
|
||||||
$arrAdd = array();
|
$arrAdd = array();
|
||||||
foreach(str_split($line) as $char)
|
foreach(str_split($line) as $char)
|
||||||
$arrAdd[] = ($char=='1')?1:0;
|
$arrAdd[] = ($char=='1')?1:0;
|
||||||
$barcode_array['bcode'][] = $arrAdd;
|
$barcode_array['bcode'][] = $arrAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $barcode_array;
|
return $barcode_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function clearCache()
|
public static function clearCache()
|
||||||
{
|
{
|
||||||
self::$frames = array();
|
self::$frames = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function buildCache()
|
public static function buildCache()
|
||||||
{
|
{
|
||||||
QRtools::markTime('before_build_cache');
|
QRtools::markTime('before_build_cache');
|
||||||
|
|
||||||
$mask = new QRmask();
|
$mask = new QRmask();
|
||||||
for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
|
for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
|
||||||
$frame = QRspec::newFrame($a);
|
$frame = QRspec::newFrame($a);
|
||||||
if (QR_IMAGE) {
|
if (QR_IMAGE) {
|
||||||
$fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
|
$fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
|
||||||
QRimage::png(self::binarize($frame), $fileName, 1, 0);
|
QRimage::png(self::binarize($frame), $fileName, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
$width = count($frame);
|
$width = count($frame);
|
||||||
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
|
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
|
||||||
for ($maskNo=0; $maskNo<8; $maskNo++)
|
for ($maskNo=0; $maskNo<8; $maskNo++)
|
||||||
$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
|
$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRtools::markTime('after_build_cache');
|
QRtools::markTime('after_build_cache');
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function log($outfile, $err)
|
public static function log($outfile, $err)
|
||||||
{
|
{
|
||||||
if (QR_LOG_DIR !== false) {
|
if (QR_LOG_DIR !== false) {
|
||||||
if ($err != '') {
|
if ($err != '') {
|
||||||
if ($outfile !== false) {
|
if ($outfile !== false) {
|
||||||
file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
|
file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
|
||||||
} else {
|
} else {
|
||||||
file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
|
file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function dumpMask($frame)
|
public static function dumpMask($frame)
|
||||||
{
|
{
|
||||||
$width = count($frame);
|
$width = count($frame);
|
||||||
for($y=0;$y<$width;$y++) {
|
for($y=0;$y<$width;$y++) {
|
||||||
for($x=0;$x<$width;$x++) {
|
for($x=0;$x<$width;$x++) {
|
||||||
echo ord($frame[$y][$x]).',';
|
echo ord($frame[$y][$x]).',';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function markTime($markerId)
|
public static function markTime($markerId)
|
||||||
{
|
{
|
||||||
list($usec, $sec) = explode(" ", microtime());
|
list($usec, $sec) = explode(" ", microtime());
|
||||||
$time = ((float)$usec + (float)$sec);
|
$time = ((float)$usec + (float)$sec);
|
||||||
|
|
||||||
if (!isset($GLOBALS['qr_time_bench']))
|
if (!isset($GLOBALS['qr_time_bench']))
|
||||||
$GLOBALS['qr_time_bench'] = array();
|
$GLOBALS['qr_time_bench'] = array();
|
||||||
|
|
||||||
$GLOBALS['qr_time_bench'][$markerId] = $time;
|
$GLOBALS['qr_time_bench'][$markerId] = $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
public static function timeBenchmark()
|
public static function timeBenchmark()
|
||||||
{
|
{
|
||||||
self::markTime('finish');
|
self::markTime('finish');
|
||||||
|
|
||||||
$lastTime = 0;
|
$lastTime = 0;
|
||||||
$startTime = 0;
|
$startTime = 0;
|
||||||
$p = 0;
|
$p = 0;
|
||||||
|
|
||||||
echo '<table cellpadding="3" cellspacing="1">
|
echo '<table cellpadding="3" cellspacing="1">
|
||||||
<thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
|
<thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
|
||||||
<tbody>';
|
<tbody>';
|
||||||
|
|
||||||
foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
|
foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
|
||||||
if ($p > 0) {
|
if ($p > 0) {
|
||||||
echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
|
echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
|
||||||
} else {
|
} else {
|
||||||
$startTime = $thisTime;
|
$startTime = $thisTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
$p++;
|
$p++;
|
||||||
$lastTime = $thisTime;
|
$lastTime = $thisTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo '</tbody><tfoot>
|
echo '</tbody><tfoot>
|
||||||
<tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
|
<tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>';
|
</table>';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//##########################################################################
|
//##########################################################################
|
||||||
|
|
||||||
QRtools::markTime('start');
|
QRtools::markTime('start');
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
php ./merge.php
|
php ./merge.php
|
||||||
pause
|
pause
|
|
@ -1,70 +1,70 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Tool for merging all library files into one, simpler to incorporate.
|
* Tool for merging all library files into one, simpler to incorporate.
|
||||||
*
|
*
|
||||||
* MAKE SURE THAT RESULTING PHPQRCode.php (and its dir) ARE WRITABLE!
|
* MAKE SURE THAT RESULTING PHPQRCode.php (and its dir) ARE WRITABLE!
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR;
|
$QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR;
|
||||||
$QR_TOOLSDIR = dirname(__FILE__).DIRECTORY_SEPARATOR;
|
$QR_TOOLSDIR = dirname(__FILE__).DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
$outputFile = $QR_BASEDIR.'phpqrcode.php';
|
$outputFile = $QR_BASEDIR.'phpqrcode.php';
|
||||||
|
|
||||||
// Required libs
|
// Required libs
|
||||||
|
|
||||||
$fileList = array(
|
$fileList = array(
|
||||||
$QR_BASEDIR.'qrconst.php',
|
$QR_BASEDIR.'qrconst.php',
|
||||||
$QR_TOOLSDIR.'merged_config.php',
|
$QR_TOOLSDIR.'merged_config.php',
|
||||||
$QR_BASEDIR.'qrtools.php',
|
$QR_BASEDIR.'qrtools.php',
|
||||||
$QR_BASEDIR.'qrspec.php',
|
$QR_BASEDIR.'qrspec.php',
|
||||||
$QR_BASEDIR.'qrimage.php',
|
$QR_BASEDIR.'qrimage.php',
|
||||||
$QR_BASEDIR.'qrinput.php',
|
$QR_BASEDIR.'qrinput.php',
|
||||||
$QR_BASEDIR.'qrbitstream.php',
|
$QR_BASEDIR.'qrbitstream.php',
|
||||||
$QR_BASEDIR.'qrsplit.php',
|
$QR_BASEDIR.'qrsplit.php',
|
||||||
$QR_BASEDIR.'qrrscode.php',
|
$QR_BASEDIR.'qrrscode.php',
|
||||||
$QR_BASEDIR.'qrmask.php',
|
$QR_BASEDIR.'qrmask.php',
|
||||||
$QR_BASEDIR.'qrencode.php'
|
$QR_BASEDIR.'qrencode.php'
|
||||||
);
|
);
|
||||||
|
|
||||||
$headerFile = $QR_TOOLSDIR.'merged_header.php';
|
$headerFile = $QR_TOOLSDIR.'merged_header.php';
|
||||||
$versionFile = $QR_BASEDIR.'VERSION';
|
$versionFile = $QR_BASEDIR.'VERSION';
|
||||||
|
|
||||||
$outputCode = '';
|
$outputCode = '';
|
||||||
|
|
||||||
foreach($fileList as $fileName) {
|
foreach($fileList as $fileName) {
|
||||||
$outputCode .= "\n\n".'//---- '.basename($fileName).' -----------------------------'."\n\n";
|
$outputCode .= "\n\n".'//---- '.basename($fileName).' -----------------------------'."\n\n";
|
||||||
$anotherCode = file_get_contents($fileName);
|
$anotherCode = file_get_contents($fileName);
|
||||||
$anotherCode = preg_replace ('/^<\?php/', '', $anotherCode);
|
$anotherCode = preg_replace ('/^<\?php/', '', $anotherCode);
|
||||||
$anotherCode = preg_replace ('/\?>\*$/', '', $anotherCode);
|
$anotherCode = preg_replace ('/\?>\*$/', '', $anotherCode);
|
||||||
$outputCode .= "\n\n".$anotherCode."\n\n";
|
$outputCode .= "\n\n".$anotherCode."\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$versionDataEx = explode("\n", file_get_contents($versionFile));
|
$versionDataEx = explode("\n", file_get_contents($versionFile));
|
||||||
|
|
||||||
$outputContents = file_get_contents($headerFile);
|
$outputContents = file_get_contents($headerFile);
|
||||||
$outputContents .= "\n\n/*\n * Version: ".trim($versionDataEx[0])."\n * Build: ".trim($versionDataEx[1])."\n */\n\n";
|
$outputContents .= "\n\n/*\n * Version: ".trim($versionDataEx[0])."\n * Build: ".trim($versionDataEx[1])."\n */\n\n";
|
||||||
$outputContents .= $outputCode;
|
$outputContents .= $outputCode;
|
||||||
|
|
||||||
file_put_contents($outputFile, $outputContents);
|
file_put_contents($outputFile, $outputContents);
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
php ./merge.php
|
php ./merge.php
|
|
@ -1,17 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* Config file, tuned-up for merged verion
|
* Config file, tuned-up for merged verion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there
|
define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there
|
||||||
define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true
|
define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true
|
||||||
define('QR_LOG_DIR', false); // default error logs dir
|
define('QR_LOG_DIR', false); // default error logs dir
|
||||||
|
|
||||||
define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
|
define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
|
||||||
define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
|
define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
|
||||||
define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
|
define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
|
||||||
|
|
||||||
define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
|
define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PHP QR Code encoder
|
* PHP QR Code encoder
|
||||||
*
|
*
|
||||||
* This file contains MERGED version of PHP QR Code library.
|
* This file contains MERGED version of PHP QR Code library.
|
||||||
* It was auto-generated from full version for your convenience.
|
* It was auto-generated from full version for your convenience.
|
||||||
*
|
*
|
||||||
* This merged version was configured to not requre any external files,
|
* This merged version was configured to not requre any external files,
|
||||||
* with disabled cache, error loging and weker but faster mask matching.
|
* with disabled cache, error loging and weker but faster mask matching.
|
||||||
* If you need tune it up please use non-merged version.
|
* If you need tune it up please use non-merged version.
|
||||||
*
|
*
|
||||||
* For full version, documentation, examples of use please visit:
|
* For full version, documentation, examples of use please visit:
|
||||||
*
|
*
|
||||||
* http://phpqrcode.sourceforge.net/
|
* http://phpqrcode.sourceforge.net/
|
||||||
* https://sourceforge.net/projects/phpqrcode/
|
* https://sourceforge.net/projects/phpqrcode/
|
||||||
*
|
*
|
||||||
* PHP QR Code is distributed under LGPL 3
|
* PHP QR Code is distributed under LGPL 3
|
||||||
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* License as published by the Free Software Foundation; either
|
* License as published by the Free Software Foundation; either
|
||||||
* version 3 of the License, or any later version.
|
* version 3 of the License, or any later version.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This library is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|