1
0
mirror of https://git.tt-rss.org/git/tt-rss.git synced 2025-12-13 22:55:55 +00:00

Merge branch 'master' into css-feedtree-counter

Conflicts:
	tt-rss.css
This commit is contained in:
Andrew Dolgov
2013-05-07 15:36:14 +04:00
218 changed files with 24450 additions and 42954 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/messages.mo
*~
*.DS_Store
#*

3
.htaccess Normal file
View File

@@ -0,0 +1,3 @@
AddType image/svg+xml svg
AddType image/svg+xml svgz

View File

@@ -13,6 +13,7 @@
define('TTRSS_SESSION_NAME', 'ttrss_api_sid');
define('NO_SESSION_AUTOSTART', true);
require_once "autoload.php";
require_once "db.php";
require_once "db-prefs.php";
require_once "functions.php";
@@ -30,8 +31,6 @@
ob_start();
}
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$input = file_get_contents("php://input");
if (defined('_API_DEBUG_HTTP_ENABLED') && _API_DEBUG_HTTP_ENABLED) {
@@ -54,11 +53,11 @@
@session_start();
}
if (!init_connection($link)) return;
if (!init_plugins()) return;
$method = strtolower($_REQUEST["op"]);
$handler = new API($link, $_REQUEST);
$handler = new API($_REQUEST);
if ($handler->before($method)) {
if ($method && method_exists($handler, $method)) {
@@ -69,8 +68,6 @@
$handler->after();
}
db_close($link);
header("Api-Content-Length: " . ob_get_length());
ob_end_flush();

View File

@@ -37,6 +37,7 @@
@$csrf_token = $_REQUEST['csrf_token'];
require_once "autoload.php";
require_once "sessions.php";
require_once "functions.php";
require_once "config.php";
@@ -47,9 +48,7 @@
$script_started = microtime(true);
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (!init_connection($link)) return;
if (!init_plugins()) return;
header("Content-Type: text/json; charset=utf-8");
@@ -58,11 +57,16 @@
}
if (SINGLE_USER_MODE) {
authenticate_user($link, "admin", null);
authenticate_user( "admin", null);
}
if ($_SESSION["uid"]) {
load_user_plugins($link, $_SESSION["uid"]);
if (!validate_session()) {
header("Content-Type: text/json");
print json_encode(array("error" => array("code" => 6)));
return;
}
load_user_plugins( $_SESSION["uid"]);
}
$purge_intervals = array(
@@ -100,7 +104,7 @@
5 => __("Power User"),
10 => __("Administrator"));
#$error = sanity_check($link);
#$error = sanity_check();
#if ($error['code'] != 0 && $op != "logout") {
# print json_encode(array("error" => $error));
@@ -109,15 +113,14 @@
$op = str_replace("-", "_", $op);
global $pluginhost;
$override = $pluginhost->lookup_handler($op, $method);
$override = PluginHost::getInstance()->lookup_handler($op, $method);
if (class_exists($op) || $override) {
if ($override) {
$handler = $override;
} else {
$handler = new $op($link, $_REQUEST);
$handler = new $op($_REQUEST);
}
if ($handler && implements_interface($handler, 'IHandler')) {
@@ -148,6 +151,4 @@
header("Content-Type: text/json");
print json_encode(array("error" => array("code" => 7)));
// We close the connection to database.
db_close($link);
?>

View File

@@ -60,6 +60,7 @@ div.cdmContentInner {
div.cdmContentInner img {
border-width : 0px;
max-width : 98%;
height : auto;
}
div.cdmFooter {

2
classes/.htaccess Normal file
View File

@@ -0,0 +1,2 @@
Order deny,allow
Deny from all

View File

@@ -2,7 +2,7 @@
class API extends Handler {
const API_LEVEL = 5;
const API_LEVEL = 6;
const STATUS_OK = 0;
const STATUS_ERR = 1;
@@ -14,12 +14,12 @@ class API extends Handler {
header("Content-Type: text/json");
if (!$_SESSION["uid"] && $method != "login" && $method != "isloggedin") {
print $this->wrap(self::STATUS_ERR, array("error" => 'NOT_LOGGED_IN'));
$this->wrap(self::STATUS_ERR, array("error" => 'NOT_LOGGED_IN'));
return false;
}
if ($_SESSION["uid"] && $method != "logout" && !get_pref($this->link, 'ENABLE_API_ACCESS')) {
print $this->wrap(self::STATUS_ERR, array("error" => 'API_DISABLED'));
if ($_SESSION["uid"] && $method != "logout" && !get_pref('ENABLE_API_ACCESS')) {
$this->wrap(self::STATUS_ERR, array("error" => 'API_DISABLED'));
return false;
}
@@ -38,88 +38,88 @@ class API extends Handler {
function getVersion() {
$rv = array("version" => VERSION);
print $this->wrap(self::STATUS_OK, $rv);
$this->wrap(self::STATUS_OK, $rv);
}
function getApiLevel() {
$rv = array("level" => self::API_LEVEL);
print $this->wrap(self::STATUS_OK, $rv);
$this->wrap(self::STATUS_OK, $rv);
}
function login() {
@session_destroy();
@session_start();
$login = db_escape_string($this->link, $_REQUEST["user"]);
$login = $this->dbh->escape_string($_REQUEST["user"]);
$password = $_REQUEST["password"];
$password_base64 = base64_decode($_REQUEST["password"]);
if (SINGLE_USER_MODE) $login = "admin";
$result = db_query($this->link, "SELECT id FROM ttrss_users WHERE login = '$login'");
$result = $this->dbh->query("SELECT id FROM ttrss_users WHERE login = '$login'");
if (db_num_rows($result) != 0) {
$uid = db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) != 0) {
$uid = $this->dbh->fetch_result($result, 0, "id");
} else {
$uid = 0;
}
if (!$uid) {
print $this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
$this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
return;
}
if (get_pref($this->link, "ENABLE_API_ACCESS", $uid)) {
if (authenticate_user($this->link, $login, $password)) { // try login with normal password
print $this->wrap(self::STATUS_OK, array("session_id" => session_id(),
if (get_pref("ENABLE_API_ACCESS", $uid)) {
if (authenticate_user($login, $password)) { // try login with normal password
$this->wrap(self::STATUS_OK, array("session_id" => session_id(),
"api_level" => self::API_LEVEL));
} else if (authenticate_user($this->link, $login, $password_base64)) { // else try with base64_decoded password
print $this->wrap(self::STATUS_OK, array("session_id" => session_id(),
} else if (authenticate_user($login, $password_base64)) { // else try with base64_decoded password
$this->wrap(self::STATUS_OK, array("session_id" => session_id(),
"api_level" => self::API_LEVEL));
} else { // else we are not logged in
print $this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
$this->wrap(self::STATUS_ERR, array("error" => "LOGIN_ERROR"));
}
} else {
print $this->wrap(self::STATUS_ERR, array("error" => "API_DISABLED"));
$this->wrap(self::STATUS_ERR, array("error" => "API_DISABLED"));
}
}
function logout() {
logout_user();
print $this->wrap(self::STATUS_OK, array("status" => "OK"));
$this->wrap(self::STATUS_OK, array("status" => "OK"));
}
function isLoggedIn() {
print $this->wrap(self::STATUS_OK, array("status" => $_SESSION["uid"] != ''));
$this->wrap(self::STATUS_OK, array("status" => $_SESSION["uid"] != ''));
}
function getUnread() {
$feed_id = db_escape_string($this->link, $_REQUEST["feed_id"]);
$is_cat = db_escape_string($this->link, $_REQUEST["is_cat"]);
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
$is_cat = $this->dbh->escape_string($_REQUEST["is_cat"]);
if ($feed_id) {
print $this->wrap(self::STATUS_OK, array("unread" => getFeedUnread($this->link, $feed_id, $is_cat)));
$this->wrap(self::STATUS_OK, array("unread" => getFeedUnread($feed_id, $is_cat)));
} else {
print $this->wrap(self::STATUS_OK, array("unread" => getGlobalUnread($this->link)));
$this->wrap(self::STATUS_OK, array("unread" => getGlobalUnread()));
}
}
/* Method added for ttrss-reader for Android */
function getCounters() {
print $this->wrap(self::STATUS_OK, getAllCounters($this->link));
$this->wrap(self::STATUS_OK, getAllCounters());
}
function getFeeds() {
$cat_id = db_escape_string($this->link, $_REQUEST["cat_id"]);
$cat_id = $this->dbh->escape_string($_REQUEST["cat_id"]);
$unread_only = sql_bool_to_bool($_REQUEST["unread_only"]);
$limit = (int) db_escape_string($this->link, $_REQUEST["limit"]);
$offset = (int) db_escape_string($this->link, $_REQUEST["offset"]);
$limit = (int) $this->dbh->escape_string($_REQUEST["limit"]);
$offset = (int) $this->dbh->escape_string($_REQUEST["offset"]);
$include_nested = sql_bool_to_bool($_REQUEST["include_nested"]);
$feeds = $this->api_get_feeds($this->link, $cat_id, $unread_only, $limit, $offset, $include_nested);
$feeds = $this->api_get_feeds($cat_id, $unread_only, $limit, $offset, $include_nested);
print $this->wrap(self::STATUS_OK, $feeds);
$this->wrap(self::STATUS_OK, $feeds);
}
function getCategories() {
@@ -134,7 +134,7 @@ class API extends Handler {
else
$nested_qpart = "true";
$result = db_query($this->link, "SELECT
$result = $this->dbh->query("SELECT
id, title, order_id, (SELECT COUNT(id) FROM
ttrss_feeds WHERE
ttrss_feed_categories.id IS NOT NULL AND cat_id = ttrss_feed_categories.id) AS num_feeds,
@@ -147,12 +147,12 @@ class API extends Handler {
$cats = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
if ($include_empty || $line["num_feeds"] > 0 || $line["num_cats"] > 0) {
$unread = getFeedUnread($this->link, $line["id"], true);
$unread = getFeedUnread($line["id"], true);
if ($enable_nested)
$unread += getCategoryChildrenUnread($this->link, $line["id"]);
$unread += getCategoryChildrenUnread($line["id"]);
if ($unread || !$unread_only) {
array_push($cats, array("id" => $line["id"],
@@ -166,36 +166,36 @@ class API extends Handler {
foreach (array(-2,-1,0) as $cat_id) {
if ($include_empty || !$this->isCategoryEmpty($cat_id)) {
$unread = getFeedUnread($this->link, $cat_id, true);
$unread = getFeedUnread($cat_id, true);
if ($unread || !$unread_only) {
array_push($cats, array("id" => $cat_id,
"title" => getCategoryTitle($this->link, $cat_id),
"title" => getCategoryTitle($cat_id),
"unread" => $unread));
}
}
}
print $this->wrap(self::STATUS_OK, $cats);
$this->wrap(self::STATUS_OK, $cats);
}
function getHeadlines() {
$feed_id = db_escape_string($this->link, $_REQUEST["feed_id"]);
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
if ($feed_id != "") {
$limit = (int)db_escape_string($this->link, $_REQUEST["limit"]);
$limit = (int)$this->dbh->escape_string($_REQUEST["limit"]);
if (!$limit || $limit >= 60) $limit = 60;
if (!$limit || $limit >= 200) $limit = 200;
$offset = (int)db_escape_string($this->link, $_REQUEST["skip"]);
$filter = db_escape_string($this->link, $_REQUEST["filter"]);
$offset = (int)$this->dbh->escape_string($_REQUEST["skip"]);
$filter = $this->dbh->escape_string($_REQUEST["filter"]);
$is_cat = sql_bool_to_bool($_REQUEST["is_cat"]);
$show_excerpt = sql_bool_to_bool($_REQUEST["show_excerpt"]);
$show_content = sql_bool_to_bool($_REQUEST["show_content"]);
/* all_articles, unread, adaptive, marked, updated */
$view_mode = db_escape_string($this->link, $_REQUEST["view_mode"]);
$view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]);
$include_attachments = sql_bool_to_bool($_REQUEST["include_attachments"]);
$since_id = (int)db_escape_string($this->link, $_REQUEST["since_id"]);
$since_id = (int)$this->dbh->escape_string($_REQUEST["since_id"]);
$include_nested = sql_bool_to_bool($_REQUEST["include_nested"]);
$sanitize_content = true;
@@ -211,25 +211,25 @@ class API extends Handler {
/* do not rely on params below */
$search = db_escape_string($this->link, $_REQUEST["search"]);
$search_mode = db_escape_string($this->link, $_REQUEST["search_mode"]);
$search = $this->dbh->escape_string($_REQUEST["search"]);
$search_mode = $this->dbh->escape_string($_REQUEST["search_mode"]);
$headlines = $this->api_get_headlines($this->link, $feed_id, $limit, $offset,
$headlines = $this->api_get_headlines($feed_id, $limit, $offset,
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $override_order,
$include_attachments, $since_id, $search, $search_mode,
$include_nested, $sanitize_content);
print $this->wrap(self::STATUS_OK, $headlines);
$this->wrap(self::STATUS_OK, $headlines);
} else {
print $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
$this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
}
}
function updateArticle() {
$article_ids = array_filter(explode(",", db_escape_string($this->link, $_REQUEST["article_ids"])), is_numeric);
$mode = (int) db_escape_string($this->link, $_REQUEST["mode"]);
$data = db_escape_string($this->link, $_REQUEST["data"]);
$field_raw = (int)db_escape_string($this->link, $_REQUEST["field"]);
$article_ids = array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_ids"])), is_numeric);
$mode = (int) $this->dbh->escape_string($_REQUEST["mode"]);
$data = $this->dbh->escape_string($_REQUEST["data"]);
$field_raw = (int)$this->dbh->escape_string($_REQUEST["field"]);
$field = "";
$set_to = "";
@@ -269,16 +269,16 @@ class API extends Handler {
$article_ids = join(", ", $article_ids);
$result = db_query($this->link, "UPDATE ttrss_user_entries SET $field = $set_to $additional_fields WHERE ref_id IN ($article_ids) AND owner_uid = " . $_SESSION["uid"]);
$result = $this->dbh->query("UPDATE ttrss_user_entries SET $field = $set_to $additional_fields WHERE ref_id IN ($article_ids) AND owner_uid = " . $_SESSION["uid"]);
$num_updated = db_affected_rows($this->link, $result);
$num_updated = $this->dbh->affected_rows($result);
if ($num_updated > 0 && $field == "unread") {
$result = db_query($this->link, "SELECT DISTINCT feed_id FROM ttrss_user_entries
$result = $this->dbh->query("SELECT DISTINCT feed_id FROM ttrss_user_entries
WHERE ref_id IN ($article_ids)");
while ($line = db_fetch_assoc($result)) {
ccache_update($this->link, $line["feed_id"], $_SESSION["uid"]);
while ($line = $this->dbh->fetch_assoc($result)) {
ccache_update($line["feed_id"], $_SESSION["uid"]);
}
}
@@ -286,49 +286,49 @@ class API extends Handler {
if (PUBSUBHUBBUB_HUB) {
$rss_link = get_self_url_prefix() .
"/public.php?op=rss&id=-2&key=" .
get_feed_access_key($this->link, -2, false);
get_feed_access_key(-2, false);
$p = new Publisher(PUBSUBHUBBUB_HUB);
$pubsub_result = $p->publish_update($rss_link);
}
}
print $this->wrap(self::STATUS_OK, array("status" => "OK",
$this->wrap(self::STATUS_OK, array("status" => "OK",
"updated" => $num_updated));
} else {
print $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
$this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
}
}
function getArticle() {
$article_id = join(",", array_filter(explode(",", db_escape_string($this->link, $_REQUEST["article_id"])), is_numeric));
$article_id = join(",", array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_id"])), is_numeric));
$query = "SELECT id,title,link,content,cached_content,feed_id,comments,int_id,
marked,unread,published,
marked,unread,published,score,
".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
author
author,(SELECT title FROM ttrss_feeds WHERE id = feed_id) AS feed_title
FROM ttrss_entries,ttrss_user_entries
WHERE id IN ($article_id) AND ref_id = id AND owner_uid = " .
$_SESSION["uid"] ;
$result = db_query($this->link, $query);
$result = $this->dbh->query($query);
$articles = array();
if (db_num_rows($result) != 0) {
if ($this->dbh->num_rows($result) != 0) {
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$attachments = get_article_enclosures($this->link, $line['id']);
$attachments = get_article_enclosures($line['id']);
$article = array(
"id" => $line["id"],
"title" => $line["title"],
"link" => $line["link"],
"labels" => get_article_labels($this->link, $line['id']),
"labels" => get_article_labels($line['id']),
"unread" => sql_bool_to_bool($line["unread"]),
"marked" => sql_bool_to_bool($line["marked"]),
"published" => sql_bool_to_bool($line["published"]),
@@ -337,11 +337,12 @@ class API extends Handler {
"updated" => (int) strtotime($line["updated"]),
"content" => $line["cached_content"] != "" ? $line["cached_content"] : $line["content"],
"feed_id" => $line["feed_id"],
"attachments" => $attachments
"attachments" => $attachments,
"score" => (int)$line["score"],
"feed_title" => $line["feed_title"]
);
global $pluginhost;
foreach ($pluginhost->get_hooks($pluginhost::HOOK_RENDER_ARTICLE_API) as $p) {
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_API) as $p) {
$article = $p->hook_render_article_api(array("article" => $article));
}
@@ -351,7 +352,7 @@ class API extends Handler {
}
}
print $this->wrap(self::STATUS_OK, $articles);
$this->wrap(self::STATUS_OK, $articles);
}
@@ -362,58 +363,58 @@ class API extends Handler {
$config["daemon_is_running"] = file_is_locked("update_daemon.lock");
$result = db_query($this->link, "SELECT COUNT(*) AS cf FROM
$result = $this->dbh->query("SELECT COUNT(*) AS cf FROM
ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);
$num_feeds = db_fetch_result($result, 0, "cf");
$num_feeds = $this->dbh->fetch_result($result, 0, "cf");
$config["num_feeds"] = (int)$num_feeds;
print $this->wrap(self::STATUS_OK, $config);
$this->wrap(self::STATUS_OK, $config);
}
function updateFeed() {
require_once "include/rssfuncs.php";
$feed_id = (int) db_escape_string($this->link, $_REQUEST["feed_id"]);
$feed_id = (int) $this->dbh->escape_string($_REQUEST["feed_id"]);
update_rss_feed($this->link, $feed_id, true);
update_rss_feed($feed_id, true);
print $this->wrap(self::STATUS_OK, array("status" => "OK"));
$this->wrap(self::STATUS_OK, array("status" => "OK"));
}
function catchupFeed() {
$feed_id = db_escape_string($this->link, $_REQUEST["feed_id"]);
$is_cat = db_escape_string($this->link, $_REQUEST["is_cat"]);
$feed_id = $this->dbh->escape_string($_REQUEST["feed_id"]);
$is_cat = $this->dbh->escape_string($_REQUEST["is_cat"]);
catchup_feed($this->link, $feed_id, $is_cat);
catchup_feed($feed_id, $is_cat);
print $this->wrap(self::STATUS_OK, array("status" => "OK"));
$this->wrap(self::STATUS_OK, array("status" => "OK"));
}
function getPref() {
$pref_name = db_escape_string($this->link, $_REQUEST["pref_name"]);
$pref_name = $this->dbh->escape_string($_REQUEST["pref_name"]);
print $this->wrap(self::STATUS_OK, array("value" => get_pref($this->link, $pref_name)));
$this->wrap(self::STATUS_OK, array("value" => get_pref($pref_name)));
}
function getLabels() {
//$article_ids = array_filter(explode(",", db_escape_string($this->link, $_REQUEST["article_ids"])), is_numeric);
//$article_ids = array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_ids"])), is_numeric);
$article_id = (int)$_REQUEST['article_id'];
$rv = array();
$result = db_query($this->link, "SELECT id, caption, fg_color, bg_color
$result = $this->dbh->query("SELECT id, caption, fg_color, bg_color
FROM ttrss_labels2
WHERE owner_uid = '".$_SESSION['uid']."' ORDER BY caption");
if ($article_id)
$article_labels = get_article_labels($this->link, $article_id);
$article_labels = get_article_labels($article_id);
else
$article_labels = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$checked = false;
foreach ($article_labels as $al) {
@@ -431,16 +432,16 @@ class API extends Handler {
"checked" => $checked));
}
print $this->wrap(self::STATUS_OK, $rv);
$this->wrap(self::STATUS_OK, $rv);
}
function setArticleLabel() {
$article_ids = array_filter(explode(",", db_escape_string($this->link, $_REQUEST["article_ids"])), is_numeric);
$label_id = (int) db_escape_string($this->link, $_REQUEST['label_id']);
$assign = (bool) db_escape_string($this->link, $_REQUEST['assign']) == "true";
$article_ids = array_filter(explode(",", $this->dbh->escape_string($_REQUEST["article_ids"])), is_numeric);
$label_id = (int) $this->dbh->escape_string($_REQUEST['label_id']);
$assign = (bool) $this->dbh->escape_string($_REQUEST['assign']) == "true";
$label = db_escape_string($this->link, label_find_caption($this->link,
$label = $this->dbh->escape_string(label_find_caption(
$label_id, $_SESSION["uid"]));
$num_updated = 0;
@@ -450,44 +451,53 @@ class API extends Handler {
foreach ($article_ids as $id) {
if ($assign)
label_add_article($this->link, $id, $label, $_SESSION["uid"]);
label_add_article($id, $label, $_SESSION["uid"]);
else
label_remove_article($this->link, $id, $label, $_SESSION["uid"]);
label_remove_article($id, $label, $_SESSION["uid"]);
++$num_updated;
}
}
print $this->wrap(self::STATUS_OK, array("status" => "OK",
$this->wrap(self::STATUS_OK, array("status" => "OK",
"updated" => $num_updated));
}
function index() {
print $this->wrap(self::STATUS_ERR, array("error" => 'UNKNOWN_METHOD'));
}
function index($method) {
$plugin = PluginHost::getInstance()->get_api_method(strtolower($method));
function shareToPublished() {
$title = db_escape_string($this->link, strip_tags($_REQUEST["title"]));
$url = db_escape_string($this->link, strip_tags($_REQUEST["url"]));
$content = db_escape_string($this->link, strip_tags($_REQUEST["content"]));
if ($plugin && method_exists($plugin, $method)) {
$reply = $plugin->$method();
$this->wrap($reply[0], $reply[1]);
if (Article::create_published_article($this->link, $title, $url, $content, "", $_SESSION["uid"])) {
print $this->wrap(self::STATUS_OK, array("status" => 'OK'));
} else {
print $this->wrap(self::STATUS_ERR, array("error" => 'Publishing failed'));
$this->wrap(self::STATUS_ERR, array("error" => 'UNKNOWN_METHOD', "method" => $method));
}
}
static function api_get_feeds($link, $cat_id, $unread_only, $limit, $offset, $include_nested = false) {
function shareToPublished() {
$title = $this->dbh->escape_string(strip_tags($_REQUEST["title"]));
$url = $this->dbh->escape_string(strip_tags($_REQUEST["url"]));
$content = $this->dbh->escape_string(strip_tags($_REQUEST["content"]));
if (Article::create_published_article($title, $url, $content, "", $_SESSION["uid"])) {
$this->wrap(self::STATUS_OK, array("status" => 'OK'));
} else {
$this->wrap(self::STATUS_ERR, array("error" => 'Publishing failed'));
}
}
static function api_get_feeds($cat_id, $unread_only, $limit, $offset, $include_nested = false) {
$feeds = array();
/* Labels */
if ($cat_id == -4 || $cat_id == -2) {
$counters = getLabelCounters($link, true);
$counters = getLabelCounters(true);
foreach (array_values($counters) as $cv) {
@@ -511,10 +521,10 @@ class API extends Handler {
if ($cat_id == -4 || $cat_id == -1) {
foreach (array(-1, -2, -3, -4, -6, 0) as $i) {
$unread = getFeedUnread($link, $i);
$unread = getFeedUnread($i);
if ($unread || !$unread_only) {
$title = getFeedTitle($link, $i);
$title = getFeedTitle($i);
$row = array(
"id" => $i,
@@ -531,14 +541,14 @@ class API extends Handler {
/* Child cats */
if ($include_nested && $cat_id) {
$result = db_query($link, "SELECT
$result = db_query("SELECT
id, title FROM ttrss_feed_categories
WHERE parent_cat = '$cat_id' AND owner_uid = " . $_SESSION["uid"] .
" ORDER BY id, title");
while ($line = db_fetch_assoc($result)) {
$unread = getFeedUnread($link, $line["id"], true) +
getCategoryChildrenUnread($link, $line["id"]);
$unread = getFeedUnread($line["id"], true) +
getCategoryChildrenUnread($line["id"]);
if ($unread || !$unread_only) {
$row = array(
@@ -561,7 +571,7 @@ class API extends Handler {
}
if ($cat_id == -4 || $cat_id == -3) {
$result = db_query($link, "SELECT
$result = db_query("SELECT
id, feed_url, cat_id, title, order_id, ".
SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"] .
@@ -573,7 +583,7 @@ class API extends Handler {
else
$cat_qpart = "cat_id IS NULL";
$result = db_query($link, "SELECT
$result = db_query("SELECT
id, feed_url, cat_id, title, order_id, ".
SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE
@@ -583,7 +593,7 @@ class API extends Handler {
while ($line = db_fetch_assoc($result)) {
$unread = getFeedUnread($link, $line["id"]);
$unread = getFeedUnread($line["id"]);
$has_icon = feed_has_icon($line['id']);
@@ -607,13 +617,13 @@ class API extends Handler {
return $feeds;
}
static function api_get_headlines($link, $feed_id, $limit, $offset,
static function api_get_headlines($feed_id, $limit, $offset,
$filter, $is_cat, $show_excerpt, $show_content, $view_mode, $order,
$include_attachments, $since_id,
$search = "", $search_mode = "",
$include_nested = false, $sanitize_content = true) {
$qfh_ret = queryFeedHeadlines($link, $feed_id, $limit,
$qfh_ret = queryFeedHeadlines($feed_id, $limit,
$view_mode, $is_cat, $search, $search_mode,
$order, $offset, 0, false, $since_id, $include_nested);
@@ -629,8 +639,8 @@ class API extends Handler {
$tags = explode(",", $line["tag_cache"]);
$labels = json_decode($line["label_cache"], true);
//if (!$tags) $tags = get_article_tags($link, $line["id"]);
//if (!$labels) $labels = get_article_labels($link, $line["id"]);
//if (!$tags) $tags = get_article_tags($line["id"]);
//if (!$labels) $labels = get_article_labels($line["id"]);
$headline_row = array(
"id" => (int)$line["id"],
@@ -646,7 +656,7 @@ class API extends Handler {
);
if ($include_attachments)
$headline_row['attachments'] = get_article_enclosures($link,
$headline_row['attachments'] = get_article_enclosures(
$line['id']);
if ($show_excerpt) {
@@ -661,7 +671,7 @@ class API extends Handler {
}
if ($sanitize_content) {
$headline_row["content"] = sanitize($link,
$headline_row["content"] = sanitize(
$line["content_preview"],
sql_bool_to_bool($line['hide_images']),
false, $line["site_url"]);
@@ -675,7 +685,8 @@ class API extends Handler {
$headline_row["labels"] = $labels;
$headline_row["feed_title"] = $line["feed_title"];
$headline_row["feed_title"] = $line["feed_title"] ? $line["feed_title"] :
$feed_title;
$headline_row["comments_count"] = (int)$line["num_comments"];
$headline_row["comments_link"] = $line["comments"];
@@ -683,9 +694,9 @@ class API extends Handler {
$headline_row["always_display_attachments"] = sql_bool_to_bool($line["always_display_enclosures"]);
$headline_row["author"] = $line["author"];
$headline_row["score"] = (int)$line["score"];
global $pluginhost;
foreach ($pluginhost->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));
}
@@ -696,48 +707,47 @@ class API extends Handler {
}
function unsubscribeFeed() {
$feed_id = (int) db_escape_string($this->link, $_REQUEST["feed_id"]);
$feed_id = (int) $this->dbh->escape_string($_REQUEST["feed_id"]);
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
id = '$feed_id' AND owner_uid = ".$_SESSION["uid"]);
if (db_num_rows($result) != 0) {
Pref_Feeds::remove_feed($this->link, $feed_id, $_SESSION["uid"]);
print $this->wrap(self::STATUS_OK, array("status" => "OK"));
if ($this->dbh->num_rows($result) != 0) {
Pref_Feeds::remove_feed($feed_id, $_SESSION["uid"]);
$this->wrap(self::STATUS_OK, array("status" => "OK"));
} else {
print $this->wrap(self::STATUS_ERR, array("error" => "FEED_NOT_FOUND"));
$this->wrap(self::STATUS_ERR, array("error" => "FEED_NOT_FOUND"));
}
}
function subscribeToFeed() {
$feed_url = db_escape_string($this->link, $_REQUEST["feed_url"]);
$category_id = (int) db_escape_string($this->link, $_REQUEST["category_id"]);
$login = db_escape_string($this->link, $_REQUEST["login"]);
$password = db_escape_string($this->link, $_REQUEST["password"]);
$feed_url = $this->dbh->escape_string($_REQUEST["feed_url"]);
$category_id = (int) $this->dbh->escape_string($_REQUEST["category_id"]);
$login = $this->dbh->escape_string($_REQUEST["login"]);
$password = $this->dbh->escape_string($_REQUEST["password"]);
if ($feed_url) {
$rc = subscribe_to_feed($this->link, $feed_url, $category_id,
$login, $password, false);
$rc = subscribe_to_feed($feed_url, $category_id, $login, $password);
print $this->wrap(self::STATUS_OK, array("status" => $rc));
$this->wrap(self::STATUS_OK, array("status" => $rc));
} else {
print $this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
$this->wrap(self::STATUS_ERR, array("error" => 'INCORRECT_USAGE'));
}
}
function getFeedTree() {
$include_empty = sql_bool_to_bool($_REQUEST['include_empty']);
$pf = new Pref_Feeds($this->link, $_REQUEST);
$pf = new Pref_Feeds($_REQUEST);
$_REQUEST['mode'] = 2;
$_REQUEST['force_show_empty'] = $include_empty;
if ($pf){
$data = $pf->makefeedtree();
print $this->wrap(self::STATUS_OK, array("categories" => $data));
$this->wrap(self::STATUS_OK, array("categories" => $data));
} else {
print $this->wrap(self::STATUS_ERR, array("error" =>
$this->wrap(self::STATUS_ERR, array("error" =>
'UNABLE_TO_INSTANTIATE_OBJECT'));
}
@@ -747,16 +757,16 @@ class API extends Handler {
private function isCategoryEmpty($id) {
if ($id == -2) {
$result = db_query($this->link, "SELECT COUNT(*) AS count FROM ttrss_labels2
$result = $this->dbh->query("SELECT COUNT(*) AS count FROM ttrss_labels2
WHERE owner_uid = " . $_SESSION["uid"]);
return db_fetch_result($result, 0, "count") == 0;
return $this->dbh->fetch_result($result, 0, "count") == 0;
} else if ($id == 0) {
$result = db_query($this->link, "SELECT COUNT(*) AS count FROM ttrss_feeds
$result = $this->dbh->query("SELECT COUNT(*) AS count FROM ttrss_feeds
WHERE cat_id IS NULL AND owner_uid = " . $_SESSION["uid"]);
return db_fetch_result($result, 0, "count") == 0;
return $this->dbh->fetch_result($result, 0, "count") == 0;
}

View File

@@ -8,14 +8,14 @@ class Article extends Handler_Protected {
}
function redirect() {
$id = db_escape_string($this->link, $_REQUEST['id']);
$id = $this->dbh->escape_string($_REQUEST['id']);
$result = db_query($this->link, "SELECT link FROM ttrss_entries, ttrss_user_entries
$result = $this->dbh->query("SELECT link FROM ttrss_entries, ttrss_user_entries
WHERE id = '$id' AND id = ref_id AND owner_uid = '".$_SESSION['uid']."'
LIMIT 1");
if (db_num_rows($result) == 1) {
$article_url = db_fetch_result($result, 0, 'link');
if ($this->dbh->num_rows($result) == 1) {
$article_url = $this->dbh->fetch_result($result, 0, 'link');
$article_url = str_replace("\n", "", $article_url);
header("Location: $article_url");
@@ -27,10 +27,10 @@ class Article extends Handler_Protected {
}
function view() {
$id = db_escape_string($this->link, $_REQUEST["id"]);
$cids = explode(",", db_escape_string($this->link, $_REQUEST["cids"]));
$mode = db_escape_string($this->link, $_REQUEST["mode"]);
$omode = db_escape_string($this->link, $_REQUEST["omode"]);
$id = $this->dbh->escape_string($_REQUEST["id"]);
$cids = explode(",", $this->dbh->escape_string($_REQUEST["cids"]));
$mode = $this->dbh->escape_string($_REQUEST["mode"]);
$omode = $this->dbh->escape_string($_REQUEST["omode"]);
// in prefetch mode we only output requested cids, main article
// just gets marked as read (it already exists in client cache)
@@ -38,26 +38,26 @@ class Article extends Handler_Protected {
$articles = array();
if ($mode == "") {
array_push($articles, format_article($this->link, $id, false));
array_push($articles, format_article($id, false));
} else if ($mode == "zoom") {
array_push($articles, format_article($this->link, $id, true, true));
array_push($articles, format_article($id, true, true));
} else if ($mode == "raw") {
if ($_REQUEST['html']) {
header("Content-Type: text/html");
print '<link rel="stylesheet" type="text/css" href="tt-rss.css"/>';
}
$article = format_article($this->link, $id, false);
$article = format_article($id, false);
print $article['content'];
return;
}
$this->catchupArticleById($this->link, $id, 0);
$this->catchupArticleById($id, 0);
if (!$_SESSION["bw_limit"]) {
foreach ($cids as $cid) {
if ($cid) {
array_push($articles, format_article($this->link, $cid, false, false));
array_push($articles, format_article($cid, false, false));
}
}
}
@@ -65,30 +65,30 @@ class Article extends Handler_Protected {
print json_encode($articles);
}
private function catchupArticleById($link, $id, $cmode) {
private function catchupArticleById($id, $cmode) {
if ($cmode == 0) {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
unread = false,last_read = NOW()
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
} else if ($cmode == 1) {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
unread = true
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
} else {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
unread = NOT unread,last_read = NOW()
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
}
$feed_id = getArticleFeed($link, $id);
ccache_update($link, $feed_id, $_SESSION["uid"]);
$feed_id = getArticleFeed($id);
ccache_update($feed_id, $_SESSION["uid"]);
}
static function create_published_article($link, $title, $url, $content, $labels_str,
static function create_published_article($title, $url, $content, $labels_str,
$owner_uid) {
$guid = sha1($url . $owner_uid); // include owner_uid to prevent global GUID clash
$guid = 'SHA1:' . sha1("ttshared:" . $url . $owner_uid); // include owner_uid to prevent global GUID clash
$content_hash = sha1($content);
if ($labels_str != "") {
@@ -104,30 +104,30 @@ class Article extends Handler_Protected {
if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) return false;
db_query($link, "BEGIN");
db_query("BEGIN");
// only check for our user data here, others might have shared this with different content etc
$result = db_query($link, "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");
if (db_num_rows($result) != 0) {
$ref_id = db_fetch_result($result, 0, "id");
$result = db_query($link, "SELECT int_id FROM ttrss_user_entries WHERE
$result = db_query("SELECT int_id FROM ttrss_user_entries WHERE
ref_id = '$ref_id' AND owner_uid = '$owner_uid' LIMIT 1");
if (db_num_rows($result) != 0) {
$int_id = db_fetch_result($result, 0, "int_id");
db_query($link, "UPDATE ttrss_entries SET
db_query("UPDATE ttrss_entries SET
content = '$content', content_hash = '$content_hash' WHERE id = '$ref_id'");
db_query($link, "UPDATE ttrss_user_entries SET published = true,
db_query("UPDATE ttrss_user_entries SET published = true,
last_published = NOW() WHERE
int_id = '$int_id' AND owner_uid = '$owner_uid'");
} else {
db_query($link, "INSERT INTO ttrss_user_entries
db_query("INSERT INTO ttrss_user_entries
(ref_id, uuid, feed_id, orig_feed_id, owner_uid, published, tag_cache, label_cache,
last_read, note, unread, last_published)
VALUES
@@ -136,24 +136,24 @@ class Article extends Handler_Protected {
if (count($labels) != 0) {
foreach ($labels as $label) {
label_add_article($link, $ref_id, trim($label), $owner_uid);
label_add_article($ref_id, trim($label), $owner_uid);
}
}
$rc = true;
} else {
$result = db_query($link, "INSERT INTO ttrss_entries
$result = db_query("INSERT INTO ttrss_entries
(title, guid, link, updated, content, content_hash, date_entered, date_updated)
VALUES
('$title', '$guid', '$url', NOW(), '$content', '$content_hash', NOW(), NOW())");
$result = db_query($link, "SELECT id FROM ttrss_entries WHERE guid = '$guid'");
$result = db_query("SELECT id FROM ttrss_entries WHERE guid = '$guid'");
if (db_num_rows($result) != 0) {
$ref_id = db_fetch_result($result, 0, "id");
db_query($link, "INSERT INTO ttrss_user_entries
db_query("INSERT INTO ttrss_user_entries
(ref_id, uuid, feed_id, orig_feed_id, owner_uid, published, tag_cache, label_cache,
last_read, note, unread, last_published)
VALUES
@@ -161,7 +161,7 @@ class Article extends Handler_Protected {
if (count($labels) != 0) {
foreach ($labels as $label) {
label_add_article($link, $ref_id, trim($label), $owner_uid);
label_add_article($ref_id, trim($label), $owner_uid);
}
}
@@ -169,7 +169,7 @@ class Article extends Handler_Protected {
}
}
db_query($link, "COMMIT");
db_query("COMMIT");
return $rc;
}
@@ -178,9 +178,9 @@ class Article extends Handler_Protected {
print __("Tags for this article (separated by commas):")."<br>";
$param = db_escape_string($this->link, $_REQUEST['param']);
$param = $this->dbh->escape_string($_REQUEST['param']);
$tags = get_article_tags($this->link, db_escape_string($this->link, $param));
$tags = get_article_tags($this->dbh->escape_string($param));
$tags_str = join(", ", $tags);
@@ -209,36 +209,36 @@ class Article extends Handler_Protected {
}
function setScore() {
$ids = db_escape_string($this->link, $_REQUEST['id']);
$score = (int)db_escape_string($this->link, $_REQUEST['score']);
$ids = $this->dbh->escape_string($_REQUEST['id']);
$score = (int)$this->dbh->escape_string($_REQUEST['score']);
db_query($this->link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
score = '$score' WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
print json_encode(array("id" => $id,
print json_encode(array("id" => $ids,
"score_pic" => get_score_pic($score)));
}
function setArticleTags() {
$id = db_escape_string($this->link, $_REQUEST["id"]);
$id = $this->dbh->escape_string($_REQUEST["id"]);
$tags_str = db_escape_string($this->link, $_REQUEST["tags_str"]);
$tags_str = $this->dbh->escape_string($_REQUEST["tags_str"]);
$tags = array_unique(trim_array(explode(",", $tags_str)));
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
$result = db_query($this->link, "SELECT int_id FROM ttrss_user_entries WHERE
$result = $this->dbh->query("SELECT int_id FROM ttrss_user_entries WHERE
ref_id = '$id' AND owner_uid = '".$_SESSION["uid"]."' LIMIT 1");
if (db_num_rows($result) == 1) {
if ($this->dbh->num_rows($result) == 1) {
$tags_to_cache = array();
$int_id = db_fetch_result($result, 0, "int_id");
$int_id = $this->dbh->fetch_result($result, 0, "int_id");
db_query($this->link, "DELETE FROM ttrss_tags WHERE
$this->dbh->query("DELETE FROM ttrss_tags WHERE
post_int_id = $int_id AND owner_uid = '".$_SESSION["uid"]."'");
foreach ($tags as $tag) {
@@ -255,7 +255,7 @@ class Article extends Handler_Protected {
// print "<!-- $id : $int_id : $tag -->";
if ($tag != '') {
db_query($this->link, "INSERT INTO ttrss_tags
$this->dbh->query("INSERT INTO ttrss_tags
(post_int_id, owner_uid, tag_name) VALUES ('$int_id', '".$_SESSION["uid"]."', '$tag')");
}
@@ -267,14 +267,14 @@ class Article extends Handler_Protected {
sort($tags_to_cache);
$tags_str = join(",", $tags_to_cache);
db_query($this->link, "UPDATE ttrss_user_entries
$this->dbh->query("UPDATE ttrss_user_entries
SET tag_cache = '$tags_str' WHERE ref_id = '$id'
AND owner_uid = " . $_SESSION["uid"]);
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
$tags = get_article_tags($this->link, $id);
$tags = get_article_tags($id);
$tags_str = format_tags_string($tags, $id);
$tags_str_full = join(", ", $tags);
@@ -286,15 +286,15 @@ class Article extends Handler_Protected {
function completeTags() {
$search = db_escape_string($this->link, $_REQUEST["search"]);
$search = $this->dbh->escape_string($_REQUEST["search"]);
$result = db_query($this->link, "SELECT DISTINCT tag_name FROM ttrss_tags
$result = $this->dbh->query("SELECT DISTINCT tag_name FROM ttrss_tags
WHERE owner_uid = '".$_SESSION["uid"]."' AND
tag_name LIKE '$search%' ORDER BY tag_name
LIMIT 10");
print "<ul>";
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
print "<li>" . $line["tag_name"] . "</li>";
}
print "</ul>";
@@ -311,10 +311,10 @@ class Article extends Handler_Protected {
private function labelops($assign) {
$reply = array();
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$label_id = db_escape_string($this->link, $_REQUEST["lid"]);
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
$label_id = $this->dbh->escape_string($_REQUEST["lid"]);
$label = db_escape_string($this->link, label_find_caption($this->link, $label_id,
$label = $this->dbh->escape_string(label_find_caption($label_id,
$_SESSION["uid"]));
$reply["info-for-headlines"] = array();
@@ -324,11 +324,11 @@ class Article extends Handler_Protected {
foreach ($ids as $id) {
if ($assign)
label_add_article($this->link, $id, $label, $_SESSION["uid"]);
label_add_article($id, $label, $_SESSION["uid"]);
else
label_remove_article($this->link, $id, $label, $_SESSION["uid"]);
label_remove_article($id, $label, $_SESSION["uid"]);
$labels = get_article_labels($this->link, $id, $_SESSION["uid"]);
$labels = get_article_labels($id, $_SESSION["uid"]);
array_push($reply["info-for-headlines"],
array("id" => $id, "labels" => format_article_labels($labels, $id)));

View File

@@ -1,9 +1,9 @@
<?php
class Auth_Base {
protected $link;
private $dbh;
function __construct($link) {
$this->link = $link;
function __construct() {
$this->dbh = Db::get();
}
function check_password($owner_uid, $password) {
@@ -16,12 +16,14 @@ class Auth_Base {
// Auto-creates specified user if allowed by system configuration
// Can be used instead of find_user_by_login() by external auth modules
function auto_create_user($login) {
function auto_create_user($login, $password = false) {
if ($login && defined('AUTH_AUTO_CREATE') && AUTH_AUTO_CREATE) {
$user_id = $this->find_user_by_login($login);
if (!$password) $password = make_password();
if (!$user_id) {
$login = db_escape_string($this->link, $login);
$login = $this->dbh->escape_string($login);
$salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
$pwd_hash = encrypt_password($password, $salt, true);
@@ -29,7 +31,7 @@ class Auth_Base {
(login,access_level,last_login,created,pwd_hash,salt)
VALUES ('$login', 0, null, NOW(), '$pwd_hash','$salt')";
db_query($this->link, $query);
$this->dbh->query($query);
return $this->find_user_by_login($login);
@@ -42,13 +44,13 @@ class Auth_Base {
}
function find_user_by_login($login) {
$login = db_escape_string($this->link, $login);
$login = $this->dbh->escape_string($login);
$result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_users WHERE
login = '$login'");
if (db_num_rows($result) > 0) {
return db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) > 0) {
return $this->dbh->fetch_result($result, 0, "id");
} else {
return false;
}

View File

@@ -11,7 +11,7 @@ class Backend extends Handler {
require_once "digest.php";
$rv = prepare_headlines_digest($this->link, $_SESSION['uid'], 1, 1000);
$rv = prepare_headlines_digest($_SESSION['uid'], 1, 1000);
$rv[3] = "<pre>" . $rv[3] . "</pre>";
@@ -19,8 +19,8 @@ class Backend extends Handler {
}
private function display_main_help() {
$info = get_hotkeys_info($this->link);
$imap = get_hotkeys_map($this->link);
$info = get_hotkeys_info();
$imap = get_hotkeys_map();
$omap = array();
foreach ($imap[1] as $sequence => $action) {

98
classes/db.php Normal file
View File

@@ -0,0 +1,98 @@
<?php
class Db implements IDb {
private static $instance;
private $adapter;
private $link;
private function __construct() {
$er = error_reporting(E_ALL);
if (defined('_ENABLE_PDO') && _ENABLE_PDO && class_exists("PDO")) {
$this->adapter = new Db_PDO();
} else {
switch (DB_TYPE) {
case "mysql":
if (function_exists("mysqli_connect")) {
$this->adapter = new Db_Mysqli();
} else {
$this->adapter = new Db_Mysql();
}
break;
case "pgsql":
$this->adapter = new Db_Pgsql();
break;
default:
die("Unknown DB_TYPE: " . DB_TYPE);
}
}
if (!$this->adapter) die("Error initializing database adapter for " . DB_TYPE);
$this->link = $this->adapter->connect(DB_HOST, DB_USER, DB_PASS, DB_NAME, defined('DB_PORT') ? DB_PORT : "");
if (!$this->link) {
die("Error connecting through adapter: " . $this->adapter->last_error());
}
error_reporting($er);
}
private function __clone() {
//
}
public static function get() {
if (self::$instance == null)
self::$instance = new self();
return self::$instance;
}
static function quote($str){
return("'$str'");
}
function reconnect() {
$this->link = $this->adapter->connect(DB_HOST, DB_USER, DB_PASS, DB_NAME, defined('DB_PORT') ? DB_PORT : "");
}
function connect($host, $user, $pass, $db, $port) {
//return $this->adapter->connect($host, $user, $pass, $db, $port);
return ;
}
function escape_string($s, $strip_tags = true) {
return $this->adapter->escape_string($s, $strip_tags);
}
function query($query, $die_on_error = true) {
return $this->adapter->query($query, $die_on_error);
}
function fetch_assoc($result) {
return $this->adapter->fetch_assoc($result);
}
function num_rows($result) {
return $this->adapter->num_rows($result);
}
function fetch_result($result, $row, $param) {
return $this->adapter->fetch_result($result, $row, $param);
}
function close() {
return $this->adapter->close();
}
function affected_rows($result) {
return $this->adapter->affected_rows($result);
}
function last_error() {
return $this->adapter->last_error();
}
}
?>

73
classes/db/mysql.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
class Db_Mysql implements IDb {
private $link;
function connect($host, $user, $pass, $db, $port) {
$this->link = mysql_connect($host, $user, $pass);
if ($this->link) {
$result = mysql_select_db($db, $this->link);
if (!$result) {
die("Can't select DB: " . mysql_error($this->link));
}
$this->init();
return $this->link;
} else {
die("Unable to connect to database (as $user to $host, database $db): " . mysql_error());
}
}
function escape_string($s, $strip_tags = true) {
if ($strip_tags) $s = strip_tags($s);
return mysql_real_escape_string($s, $this->link);
}
function query($query, $die_on_error = true) {
$result = mysql_query($query, $this->link);
if (!$result) {
user_error("Query $query failed: " . ($this->link ? mysql_error($this->link) : "No connection"),
$die_on_error ? E_USER_ERROR : E_USER_WARNING);
}
return $result;
}
function fetch_assoc($result) {
return mysql_fetch_assoc($result);
}
function num_rows($result) {
return mysql_num_rows($result);
}
function fetch_result($result, $row, $param) {
return mysql_result($result, $row, $param);
}
function close() {
return mysql_close($this->link);
}
function affected_rows($result) {
return mysql_affected_rows($this->link);
}
function last_error() {
return mysql_error();
}
function init() {
$this->query("SET time_zone = '+0:0'");
if (defined('MYSQL_CHARSET') && MYSQL_CHARSET) {
$this->query("SET NAMES " . MYSQL_CHARSET);
}
return true;
}
}
?>

77
classes/db/mysqli.php Normal file
View File

@@ -0,0 +1,77 @@
<?php
class Db_Mysqli implements IDb {
private $link;
function connect($host, $user, $pass, $db, $port) {
if ($port)
$this->link = mysqli_connect($host, $user, $pass, $db, $port);
else
$this->link = mysqli_connect($host, $user, $pass, $db);
if ($this->link) {
$this->init();
return $this->link;
} else {
die("Unable to connect to database (as $user to $host, database $db): " . mysqli_error());
}
}
function escape_string($s, $strip_tags = true) {
if ($strip_tags) $s = strip_tags($s);
return mysqli_real_escape_string($this->link, $s);
}
function query($query, $die_on_error = true) {
$result = mysqli_query($this->link, $query);
if (!$result) {
user_error("Query $query failed: " . ($this->link ? mysqli_error($this->link) : "No connection"),
$die_on_error ? E_USER_ERROR : E_USER_WARNING);
}
return $result;
}
function fetch_assoc($result) {
return mysqli_fetch_assoc($result);
}
function num_rows($result) {
return mysqli_num_rows($result);
}
function fetch_result($result, $row, $param) {
if (mysqli_data_seek($result, $row)) {
$line = mysqli_fetch_assoc($result);
return $line[$param];
} else {
return false;
}
}
function close() {
return mysqli_close($this->link);
}
function affected_rows($result) {
return mysqli_affected_rows($this->link);
}
function last_error() {
return mysqli_error();
}
function init() {
$this->query("SET time_zone = '+0:0'");
if (defined('MYSQL_CHARSET') && MYSQL_CHARSET) {
$this->query("SET NAMES " . MYSQL_CHARSET);
}
return true;
}
}
?>

100
classes/db/pdo.php Normal file
View File

@@ -0,0 +1,100 @@
<?php
class Db_PDO implements IDb {
private $pdo;
function connect($host, $user, $pass, $db, $port) {
$connstr = DB_TYPE . ":host=$host;dbname=$db";
if (DB_TYPE == "mysql") $connstr .= ";charset=utf8";
try {
$this->pdo = new PDO($connstr, $user, $pass);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->init();
} catch (PDOException $e) {
die($e->getMessage());
}
return $this->pdo;
}
function escape_string($s, $strip_tags = true) {
if ($strip_tags) $s = strip_tags($s);
$qs = $this->pdo->quote($s);
return mb_substr($qs, 1, mb_strlen($qs)-2);
}
function query($query, $die_on_error = true) {
try {
return new Db_Stmt($this->pdo->query($query));
} catch (PDOException $e) {
user_error($e->getMessage(), $die_on_error ? E_USER_ERROR : E_USER_WARNING);
}
}
function fetch_assoc($result) {
try {
if ($result) {
return $result->fetch();
} else {
return null;
}
} catch (PDOException $e) {
user_error($e->getMessage(), E_USER_WARNING);
}
}
function num_rows($result) {
try {
if ($result) {
return $result->rowCount();
} else {
return false;
}
} catch (PDOException $e) {
user_error($e->getMessage(), E_USER_WARNING);
}
}
function fetch_result($result, $row, $param) {
return $result->fetch_result($row, $param);
}
function close() {
$this->pdo = null;
}
function affected_rows($result) {
try {
if ($result) {
return $result->rowCount();
} else {
return null;
}
} catch (PDOException $e) {
user_error($e->getMessage(), E_USER_WARNING);
}
}
function last_error() {
return join(" ", $this->pdo->errorInfo());
}
function init() {
switch (DB_TYPE) {
case "pgsql":
$this->query("set client_encoding = 'UTF-8'");
$this->query("set datestyle = 'ISO, european'");
$this->query("set TIME ZONE 0");
case "mysql":
$this->query("SET time_zone = '+0:0'");
return;
}
return true;
}
}
?>

82
classes/db/pgsql.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
class Db_Pgsql implements IDb {
private $link;
function connect($host, $user, $pass, $db, $port) {
$string = "dbname=$db user=$user";
if ($pass) {
$string .= " password=$pass";
}
if ($host) {
$string .= " host=$host";
}
if (is_numeric($port) && $port > 0) {
$string = "$string port=" . $port;
}
$this->link = pg_connect($string);
if (!$this->link) {
die("Unable to connect to database (as $user to $host, database $db):" . pg_last_error());
}
$this->init();
return $this->link;
}
function escape_string($s, $strip_tags = true) {
if ($strip_tags) $s = strip_tags($s);
return pg_escape_string($s);
}
function query($query, $die_on_error = true) {
$result = pg_query($query);
if (!$result) {
$query = htmlspecialchars($query); // just in case
user_error("Query $query failed: " . ($this->link ? pg_last_error($this->link) : "No connection"),
$die_on_error ? E_USER_ERROR : E_USER_WARNING);
}
return $result;
}
function fetch_assoc($result) {
return pg_fetch_assoc($result);
}
function num_rows($result) {
return pg_num_rows($result);
}
function fetch_result($result, $row, $param) {
return pg_fetch_result($result, $row, $param);
}
function close() {
return pg_close($this->link);
}
function affected_rows($result) {
return pg_affected_rows($result);
}
function last_error() {
return pg_last_error($this->link);
}
function init() {
$this->query("set client_encoding = 'UTF-8'");
pg_set_client_encoding("UNICODE");
$this->query("set datestyle = 'ISO, european'");
$this->query("set TIME ZONE 0");
return true;
}
}
?>

190
classes/db/prefs.php Normal file
View File

@@ -0,0 +1,190 @@
<?php
class Db_Prefs {
private $dbh;
private static $instance;
private $cache;
function __construct() {
$this->dbh = Db::get();
$this->cache = array();
if ($_SESSION["uid"]) $this->cache();
}
private function __clone() {
//
}
public static function get() {
if (self::$instance == null)
self::$instance = new self();
return self::$instance;
}
function cache() {
$profile = false;
$user_id = $_SESSION["uid"];
@$profile = $_SESSION["profile"];
if ($profile) {
$profile_qpart = "profile = '$profile' AND";
} else {
$profile_qpart = "profile IS NULL AND";
}
if (get_schema_version() < 63) $profile_qpart = "";
$result = db_query("SELECT
value,ttrss_prefs_types.type_name as type_name,ttrss_prefs.pref_name AS pref_name
FROM
ttrss_user_prefs,ttrss_prefs,ttrss_prefs_types
WHERE
$profile_qpart
ttrss_prefs.pref_name NOT LIKE '_MOBILE%' AND
ttrss_prefs_types.id = type_id AND
owner_uid = '$user_id' AND
ttrss_user_prefs.pref_name = ttrss_prefs.pref_name");
while ($line = db_fetch_assoc($result)) {
if ($user_id == $_SESSION["uid"]) {
$pref_name = $line["pref_name"];
$this->cache[$pref_name]["type"] = $line["type_name"];
$this->cache[$pref_name]["value"] = $line["value"];
}
}
}
function read($pref_name, $user_id = false, $die_on_error = false) {
$pref_name = db_escape_string($pref_name);
$profile = false;
if (!$user_id) {
$user_id = $_SESSION["uid"];
@$profile = $_SESSION["profile"];
} else {
$user_id = sprintf("%d", $user_id);
}
if (isset($this->cache[$pref_name])) {
$tuple = $this->cache[$pref_name];
return $this->convert($tuple["value"], $tuple["type"]);
}
if ($profile) {
$profile_qpart = "profile = '$profile' AND";
} else {
$profile_qpart = "profile IS NULL AND";
}
if (get_schema_version() < 63) $profile_qpart = "";
$result = db_query("SELECT
value,ttrss_prefs_types.type_name as type_name
FROM
ttrss_user_prefs,ttrss_prefs,ttrss_prefs_types
WHERE
$profile_qpart
ttrss_user_prefs.pref_name = '$pref_name' AND
ttrss_prefs_types.id = type_id AND
owner_uid = '$user_id' AND
ttrss_user_prefs.pref_name = ttrss_prefs.pref_name");
if (db_num_rows($result) > 0) {
$value = db_fetch_result($result, 0, "value");
$type_name = db_fetch_result($result, 0, "type_name");
if ($user_id == $_SESSION["uid"]) {
$this->cache[$pref_name]["type"] = $type_name;
$this->cache[$pref_name]["value"] = $value;
}
return $this->convert($value, $type_name);
} else {
user_error("Fatal error, unknown preferences key: $pref_name", $die_on_error ? E_USER_ERROR : E_USER_WARNING);
return null;
}
}
function convert($value, $type_name) {
if ($type_name == "bool") {
return $value == "true";
} else if ($type_name == "integer") {
return (int)$value;
} else {
return $value;
}
}
function write($pref_name, $value, $user_id = false, $strip_tags = true) {
$pref_name = db_escape_string($pref_name);
$value = db_escape_string($value, $strip_tags);
if (!$user_id) {
$user_id = $_SESSION["uid"];
@$profile = $_SESSION["profile"];
} else {
$user_id = sprintf("%d", $user_id);
$prefs_cache = false;
}
if ($profile) {
$profile_qpart = "AND profile = '$profile'";
} else {
$profile_qpart = "AND profile IS NULL";
}
if (get_schema_version() < 63) $profile_qpart = "";
$type_name = "";
$current_value = "";
if (isset($this->cache[$pref_name])) {
$type_name = $this->cache[$pref_name]["type"];
$current_value = $this->cache[$pref_name]["value"];
}
if (!$type_name) {
$result = db_query("SELECT type_name
FROM ttrss_prefs,ttrss_prefs_types
WHERE pref_name = '$pref_name' AND type_id = ttrss_prefs_types.id");
if (db_num_rows($result) > 0)
$type_name = db_fetch_result($result, 0, "type_name");
} else if ($current_value == $value) {
return;
}
if ($type_name) {
if ($type_name == "bool") {
if ($value == "1" || $value == "true") {
$value = "true";
} else {
$value = "false";
}
} else if ($type_name == "integer") {
$value = sprintf("%d", $value);
}
if ($pref_name == 'USER_TIMEZONE' && $value == '') {
$value = 'UTC';
}
db_query("UPDATE ttrss_user_prefs SET
value = '$value' WHERE pref_name = '$pref_name'
$profile_qpart
AND owner_uid = " . $_SESSION["uid"]);
if ($user_id == $_SESSION["uid"]) {
$this->cache[$pref_name]["type"] = $type_name;
$this->cache[$pref_name]["value"] = $value;
}
}
}
}
?>

32
classes/db/stmt.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
class Db_Stmt {
private $stmt;
private $cache;
function __construct($stmt) {
$this->stmt = $stmt;
$this->cache = false;
}
function fetch_result($row, $param) {
if (!$this->cache) {
$this->cache = $this->stmt->fetchAll();
}
if (isset($this->cache[$row])) {
return $this->cache[$row][$param];
} else {
user_error("Unable to jump to row $row", E_USER_WARNING);
return false;
}
}
function rowCount() {
return $this->stmt->rowCount();
}
function fetch() {
return $this->stmt->fetch();
}
}
?>

View File

@@ -1,18 +1,18 @@
<?php
class DbUpdater {
private $link;
private $dbh;
private $db_type;
private $need_version;
function __construct($link, $db_type, $need_version) {
$this->link = $link;
function __construct($dbh, $db_type, $need_version) {
$this->dbh = $dbh;
$this->db_type = $db_type;
$this->need_version = (int) $need_version;
}
function getSchemaVersion() {
$result = db_query($this->link, "SELECT schema_version FROM ttrss_version");
$result = db_query("SELECT schema_version FROM ttrss_version");
return (int) db_fetch_result($result, 0, "schema_version");
}
@@ -37,21 +37,21 @@ class DbUpdater {
if (is_array($lines)) {
db_query($this->link, "BEGIN");
db_query("BEGIN");
foreach ($lines as $line) {
if (strpos($line, "--") !== 0 && $line) {
db_query($this->link, $line);
db_query($line);
}
}
$db_version = $this->getSchemaVersion();
if ($db_version == $version) {
db_query($this->link, "COMMIT");
db_query("COMMIT");
return true;
} else {
db_query($this->link, "ROLLBACK");
db_query("ROLLBACK");
return false;
}
} else {

View File

@@ -6,7 +6,7 @@ class Dlg extends Handler_Protected {
if (parent::before($method)) {
header("Content-Type: text/html"); # required for iframe
$this->param = db_escape_string($this->link, $_REQUEST["param"]);
$this->param = $this->dbh->escape_string($_REQUEST["param"]);
return true;
}
return false;
@@ -18,15 +18,15 @@ class Dlg extends Handler_Protected {
print "<div class=\"prefFeedOPMLHolder\">";
$owner_uid = $_SESSION["uid"];
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
print "<ul class='nomarks'>";
$opml = new Opml($this->link, $_REQUEST);
$opml = new Opml($_REQUEST);
$opml->opml_import($_SESSION["uid"]);
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
print "</ul>";
print "</div>";
@@ -43,7 +43,7 @@ class Dlg extends Handler_Protected {
}
function pubOPMLUrl() {
$url_path = Opml::opml_publish_url($this->link);
$url_path = Opml::opml_publish_url();
print __("Your Public OPML URL is:");
@@ -106,15 +106,15 @@ class Dlg extends Handler_Protected {
FROM ttrss_tags WHERE owner_uid = ".$_SESSION["uid"]."
GROUP BY tag_name ORDER BY count DESC LIMIT 50";
$result = db_query($this->link, $query);
$result = $this->dbh->query($query);
$tags = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$tags[$line["tag_name"]] = $line["count"];
}
if( count($tags) == 0 ){ return; }
if(count($tags) == 0 ){ return; }
ksort($tags);
@@ -171,10 +171,10 @@ class Dlg extends Handler_Protected {
print "<label for=\"tag_mode_all\">".__("All tags.")."</input>";
print "<select id=\"all_tags\" name=\"all_tags\" title=\"" . __('Which Tags?') . "\" multiple=\"multiple\" size=\"10\" style=\"width : 100%\">";
$result = db_query($this->link, "SELECT DISTINCT tag_name FROM ttrss_tags WHERE owner_uid = ".$_SESSION['uid']."
$result = $this->dbh->query("SELECT DISTINCT tag_name FROM ttrss_tags WHERE owner_uid = ".$_SESSION['uid']."
AND LENGTH(tag_name) <= 30 ORDER BY tag_name ASC");
while ($row = db_fetch_assoc($result)) {
while ($row = $this->dbh->fetch_assoc($result)) {
$tmp = htmlspecialchars($row["tag_name"]);
print "<option value=\"" . str_replace(" ", "%20", $tmp) . "\">$tmp</option>";
}
@@ -195,10 +195,10 @@ class Dlg extends Handler_Protected {
function generatedFeed() {
$this->params = explode(":", $this->param, 3);
$feed_id = db_escape_string($this->link, $this->params[0]);
$feed_id = $this->dbh->escape_string($this->params[0]);
$is_cat = (bool) $this->params[1];
$key = get_feed_access_key($this->link, $feed_id, $is_cat);
$key = get_feed_access_key($feed_id, $is_cat);
$url_path = htmlspecialchars($this->params[2]) . "&key=" . $key;
@@ -223,7 +223,7 @@ class Dlg extends Handler_Protected {
function newVersion() {
$version_data = check_for_update($this->link);
$version_data = check_for_update();
$version = $version_data['version'];
$id = $version_data['version_id'];

View File

@@ -0,0 +1,7 @@
<?php
class FeedEnclosure {
public $link;
public $type;
public $length;
}
?>

15
classes/feeditem.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
abstract class FeedItem {
abstract function get_id();
abstract function get_date();
abstract function get_link();
abstract function get_title();
abstract function get_description();
abstract function get_content();
abstract function get_comments_url();
abstract function get_comments_count();
abstract function get_categories();
abstract function get_enclosures();
abstract function get_author();
}
?>

109
classes/feeditem/atom.php Normal file
View File

@@ -0,0 +1,109 @@
<?php
class FeedItem_Atom extends FeedItem_Common {
function get_id() {
$id = $this->elem->getElementsByTagName("id")->item(0);
if ($id) {
return $id->nodeValue;
} else {
return $this->get_link();
}
}
function get_date() {
$updated = $this->elem->getElementsByTagName("updated")->item(0);
if ($updated) {
return strtotime($updated->nodeValue);
}
}
function get_link() {
$links = $this->elem->getElementsByTagName("link");
foreach ($links as $link) {
if ($link && $link->hasAttribute("href") && (!$link->hasAttribute("rel")
|| $link->getAttribute("rel") == "alternate")) {
return $link->getAttribute("href");
}
}
}
function get_title() {
$title = $this->elem->getElementsByTagName("title")->item(0);
if ($title) {
return $title->nodeValue;
}
}
function get_content() {
$content = $this->elem->getElementsByTagName("content")->item(0);
if ($content) {
return $content->nodeValue;
}
}
function get_description() {
$summary = $this->elem->getElementsByTagName("summary")->item(0);
if ($summary) {
return $summary->nodeValue;
}
}
function get_categories() {
$categories = $this->elem->getElementsByTagName("category");
$cats = array();
foreach ($categories as $cat) {
if ($cat->hasAttribute("term"))
array_push($cats, $cat->getAttribute("term"));
}
$categories = $this->xpath->query("dc:subject", $this->elem);
foreach ($categories as $cat) {
array_push($cats, $cat->nodeValue);
}
return $cats;
}
function get_enclosures() {
$links = $this->elem->getElementsByTagName("link");
$encs = array();
foreach ($links as $link) {
if ($link && $link->hasAttribute("href") && $link->hasAttribute("rel")) {
if ($link->getAttribute("rel") == "enclosure") {
$enc = new FeedEnclosure();
$enc->type = $link->getAttribute("type");
$enc->link = $link->getAttribute("href");
$enc->length = $link->getAttribute("length");
array_push($encs, $enc);
}
}
}
$enclosures = $this->xpath->query("media:content", $this->elem);
foreach ($enclosures as $enclosure) {
$enc = new FeedEnclosure();
$enc->type = $enclosure->getAttribute("type");
$enc->link = $enclosure->getAttribute("url");
$enc->length = $enclosure->getAttribute("length");
array_push($encs, $enc);
}
return $encs;
}
}
?>

View File

@@ -0,0 +1,51 @@
<?php
abstract class FeedItem_Common extends FeedItem {
protected $elem;
protected $xpath;
protected $doc;
function __construct($elem, $doc, $xpath) {
$this->elem = $elem;
$this->xpath = $xpath;
$this->doc = $doc;
}
function get_author() {
$author = $this->elem->getElementsByTagName("author")->item(0);
if ($author) {
$name = $author->getElementsByTagName("name")->item(0);
if ($name) return $name->nodeValue;
$email = $author->getElementsByTagName("email")->item(0);
if ($email) return $email->nodeValue;
if ($author->nodeValue)
return $author->nodeValue;
}
$author = $this->xpath->query("dc:creator", $this->elem)->item(0);
if ($author) {
return $author->nodeValue;
}
}
// todo
function get_comments_url() {
}
function get_comments_count() {
$comments = $this->xpath->query("slash:comments", $this->elem)->item(0);
if ($comments) {
return $comments->nodeValue;
}
}
}
?>

107
classes/feeditem/rss.php Normal file
View File

@@ -0,0 +1,107 @@
<?php
class FeedItem_RSS extends FeedItem_Common {
function get_id() {
$id = $this->elem->getElementsByTagName("guid")->item(0);
if ($id) {
return $id->nodeValue;
} else {
return $this->get_link();
}
}
function get_date() {
$pubDate = $this->elem->getElementsByTagName("pubDate")->item(0);
if ($pubDate) {
return strtotime($pubDate->nodeValue);
}
}
function get_link() {
$link = $this->elem->getElementsByTagName("link")->item(0);
if ($link) {
return $link->nodeValue;
}
}
function get_title() {
$title = $this->elem->getElementsByTagName("title")->item(0);
if ($title) {
return $title->nodeValue;
}
}
function get_content() {
$content = $this->xpath->query("content:encoded", $this->elem)->item(0);
if ($content) {
return $content->nodeValue;
}
$content = $this->elem->getElementsByTagName("description")->item(0);
if ($content) {
return $content->nodeValue;
}
}
function get_description() {
$summary = $this->elem->getElementsByTagName("description")->item(0);
if ($summary) {
return $summary->nodeValue;
}
}
function get_categories() {
$categories = $this->elem->getElementsByTagName("category");
$cats = array();
foreach ($categories as $cat) {
array_push($cats, $cat->nodeValue);
}
$categories = $this->xpath->query("dc:subject", $this->elem);
foreach ($categories as $cat) {
array_push($cats, $cat->nodeValue);
}
return $cats;
}
function get_enclosures() {
$enclosures = $this->elem->getElementsByTagName("enclosure");
$encs = array();
foreach ($enclosures as $enclosure) {
$enc = new FeedEnclosure();
$enc->type = $enclosure->getAttribute("type");
$enc->link = $enclosure->getAttribute("url");
$enc->length = $enclosure->getAttribute("length");
array_push($encs, $enc);
}
$enclosures = $this->xpath->query("media:content", $this->elem);
foreach ($enclosures as $enclosure) {
$enc = new FeedEnclosure();
$enc->type = $enclosure->getAttribute("type");
$enc->link = $enclosure->getAttribute("url");
$enc->length = $enclosure->getAttribute("length");
array_push($encs, $enc);
}
return $encs;
}
}
?>

180
classes/feedparser.php Normal file
View File

@@ -0,0 +1,180 @@
<?php
class FeedParser {
private $doc;
private $error;
private $items;
private $link;
private $title;
private $type;
private $xpath;
const FEED_RDF = 0;
const FEED_RSS = 1;
const FEED_ATOM = 2;
function __construct($data) {
libxml_use_internal_errors(true);
libxml_clear_errors();
$this->doc = new DOMDocument();
$this->doc->loadXML($data);
$this->error = $this->format_error(libxml_get_last_error());
libxml_clear_errors();
$this->items = array();
}
function init() {
$root = $this->doc->firstChild;
$xpath = new DOMXPath($this->doc);
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
$xpath->registerNamespace('media', 'http://search.yahoo.com/mrss/');
$xpath->registerNamespace('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
$xpath->registerNamespace('slash', 'http://purl.org/rss/1.0/modules/slash/');
$xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
$xpath->registerNamespace('content', 'http://purl.org/rss/1.0/modules/content/');
$this->xpath = $xpath;
$root = $xpath->query("(//atom:feed|//channel|//rdf:rdf|//rdf:RDF)")->item(0);
if ($root) {
switch (mb_strtolower($root->tagName)) {
case "rdf:rdf":
$this->type = $this::FEED_RDF;
break;
case "channel":
$this->type = $this::FEED_RSS;
break;
case "feed":
$this->type = $this::FEED_ATOM;
break;
default:
$this->error = "Unknown/unsupported feed type";
return;
}
switch ($this->type) {
case $this::FEED_ATOM:
$title = $xpath->query("//atom:feed/atom:title")->item(0);
if ($title) {
$this->title = $title->nodeValue;
}
$link = $xpath->query("//atom:feed/atom:link[not(@rel)]")->item(0);
if ($link && $link->hasAttributes()) {
$this->link = $link->getAttribute("href");
}
$articles = $xpath->query("//atom:entry");
foreach ($articles as $article) {
array_push($this->items, new FeedItem_Atom($article, $this->doc, $this->xpath));
}
break;
case $this::FEED_RSS:
$title = $xpath->query("//channel/title")->item(0);
if ($title) {
$this->title = $title->nodeValue;
}
$link = $xpath->query("//channel/link")->item(0);
if ($link && $link->hasAttributes()) {
$this->link = $link->getAttribute("href");
}
$articles = $xpath->query("//channel/item");
foreach ($articles as $article) {
array_push($this->items, new FeedItem_RSS($article, $this->doc, $this->xpath));
}
break;
case $this::FEED_RDF:
$xpath->registerNamespace('rssfake', 'http://purl.org/rss/1.0/');
$title = $xpath->query("//rssfake:channel/rssfake:title")->item(0);
if ($title) {
$this->title = $title->nodeValue;
}
$link = $xpath->query("//rssfake:channel/rssfake:link")->item(0);
if ($link) {
$this->link = $link->nodeValue;
}
$articles = $xpath->query("//rssfake:item");
foreach ($articles as $article) {
array_push($this->items, new FeedItem_RSS($article, $this->doc, $this->xpath));
}
break;
}
} else {
$this->error = "Unknown/unsupported feed type";
return;
}
}
function format_error($error) {
if ($error) {
return sprintf("LibXML error %s at line %d (column %d): %s",
$error->code, $error->line, $error->column,
$error->message);
} else {
return "";
}
}
function error() {
return $this->error;
}
function get_link() {
return $this->link;
}
function get_title() {
return $this->title;
}
function get_items() {
return $this->items;
}
function get_links($rel) {
$rv = array();
switch ($this->type) {
case $this::FEED_ATOM:
$links = $this->xpath->query("//atom:feed/atom:link");
foreach ($links as $link) {
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
array_push($rv, $link->getAttribute('href'));
}
}
break;
case $this::FEED_RSS:
$links = $this->xpath->query("//channel/link");
foreach ($links as $link) {
if (!$rel || $link->hasAttribute('rel') && $link->getAttribute('rel') == $rel) {
array_push($rv, $link->getAttribute('href'));
}
}
break;
}
return $rv;
}
} ?>

View File

@@ -9,21 +9,9 @@ class Feeds extends Handler_Protected {
return array_search($method, $csrf_ignored) !== false;
}
private function make_gradient($end, $class) {
$start = $class == "even" ? "#f0f0f0" : "#ffffff";
return "style='background: linear-gradient(left , $start 6%, $end 100%);
background: -o-linear-gradient(left , $start 6%, $end 100%);
background: -moz-linear-gradient(left , $start 6%, $end 100%);
background: -webkit-linear-gradient(left , $start 6%, $end 100%);
background: -ms-linear-gradient(left , $start 6%, $end 100%);
background: -webkit-gradient(linear, left top, right top,
color-stop(0.06, $start), color-stop(1, $end));'";
}
private function format_headline_subtoolbar($feed_site_url, $feed_title,
$feed_id, $is_cat, $search,
$search_mode, $view_mode, $error) {
$search_mode, $view_mode, $error, $feed_last_updated) {
$page_prev_link = "viewFeedGoPage(-1)";
$page_next_link = "viewFeedGoPage(1)";
@@ -61,11 +49,15 @@ class Feeds extends Handler_Protected {
// right part
$reply .= "<span class='r'>";
$reply .= "<span id='selected_prompt'></span>";
$reply .= "<span id='feed_title'>";
if ($feed_site_url) {
$last_updated = T_sprintf("Last updated: %s",
$feed_last_updated);
$target = "target=\"_blank\"";
$reply .= "<a title=\"".__("Visit the website")."\" $target href=\"$feed_site_url\">".
$reply .= "<a title=\"$last_updated\" $target href=\"$feed_site_url\">".
truncate_string($feed_title,30)."</a>";
if ($error) {
@@ -119,14 +111,12 @@ class Feeds extends Handler_Protected {
}
global $pluginhost;
if ($pluginhost->get_plugin("mail")) {
if (PluginHost::getInstance()->get_plugin("mail")) {
$reply .= "<option value=\"emailArticle(false)\">".__('Forward by email').
"</option>";
}
if ($pluginhost->get_plugin("mailto")) {
if (PluginHost::getInstance()->get_plugin("mailto")) {
$reply .= "<option value=\"mailtoArticle(false)\">".__('Forward by email').
"</option>";
}
@@ -143,7 +133,7 @@ class Feeds extends Handler_Protected {
//$reply .= "</h2";
foreach ($pluginhost->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);
}
@@ -161,6 +151,8 @@ class Feeds extends Handler_Protected {
$reply = array();
$rgba_cache = array();
$timing_info = microtime(true);
$topmost_article_ids = array();
@@ -173,62 +165,60 @@ class Feeds extends Handler_Protected {
if ($method == "ForceUpdate" && $feed > 0 && is_numeric($feed)) {
// Update the feed if required with some basic flood control
$result = db_query($this->link,
$result = $this->dbh->query(
"SELECT cache_images,".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
FROM ttrss_feeds WHERE id = '$feed'");
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 ($this->dbh->num_rows($result) != 0) {
$last_updated = strtotime($this->dbh->fetch_result($result, 0, "last_updated"));
$cache_images = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "cache_images"));
if (!$cache_images && time() - $last_updated > 120 || isset($_REQUEST['DevForceUpdate'])) {
include "rssfuncs.php";
update_rss_feed($this->link, $feed, true, true);
update_rss_feed($feed, true, true);
} else {
db_query($this->link, "UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
$this->dbh->query("UPDATE ttrss_feeds SET last_updated = '1970-01-01', last_update_started = '1970-01-01'
WHERE id = '$feed'");
}
}
}
if ($method_split[0] == "MarkAllReadGR") {
catchup_feed($this->link, $method_split[1], false);
catchup_feed($method_split[1], false);
}
// FIXME: might break tag display?
if (is_numeric($feed) && $feed > 0 && !$cat_view) {
$result = db_query($this->link,
$result = $this->dbh->query(
"SELECT id FROM ttrss_feeds WHERE id = '$feed' LIMIT 1");
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
$reply['content'] = "<div align='center'>".__('Feed not found.')."</div>";
}
}
@$search = db_escape_string($this->link, $_REQUEST["query"]);
@$search = $this->dbh->escape_string($_REQUEST["query"]);
if ($search) {
$disable_cache = true;
}
@$search_mode = db_escape_string($this->link, $_REQUEST["search_mode"]);
@$search_mode = $this->dbh->escape_string($_REQUEST["search_mode"]);
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("H0", $timing_info);
// error_log("format_headlines_list: [" . $feed . "] method [" . $method . "]");
if( $search_mode == '' && $method != '' ){
if($search_mode == '' && $method != '' ){
$search_mode = $method;
}
// error_log("search_mode: " . $search_mode);
if (!$cat_view && is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) {
global $pluginhost;
$handler = $pluginhost->get_feed_handler(
$handler = PluginHost::getInstance()->get_feed_handler(
PluginHost::feed_to_pfeed_id($feed));
// function queryFeedHeadlines($link, $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) {
// 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) {
if ($handler) {
$options = array(
@@ -249,7 +239,7 @@ class Feeds extends Handler_Protected {
}
} else {
$qfh_ret = queryFeedHeadlines($this->link, $feed, $limit, $view_mode, $cat_view,
$qfh_ret = queryFeedHeadlines($feed, $limit, $view_mode, $cat_view,
$search, $search_mode, $override_order, $offset, 0,
false, 0, $include_children);
}
@@ -260,51 +250,48 @@ class Feeds extends Handler_Protected {
$feed_title = $qfh_ret[1];
$feed_site_url = $qfh_ret[2];
$last_error = $qfh_ret[3];
$last_updated = strpos($qfh_ret[4], '1970-') === FALSE ?
make_local_datetime($qfh_ret[4], false) : __("Never");
$vgroup_last_feed = $vgr_last_feed;
$reply['toolbar'] = $this->format_headline_subtoolbar($feed_site_url,
$feed_title,
$feed, $cat_view, $search, $search_mode, $view_mode,
$last_error);
$last_error, $last_updated);
$headlines_count = db_num_rows($result);
$headlines_count = $this->dbh->num_rows($result);
/* if (get_pref($this->link, 'COMBINED_DISPLAY_MODE')) {
/* if (get_pref('COMBINED_DISPLAY_MODE')) {
$button_plugins = array();
foreach (explode(",", ARTICLE_BUTTON_PLUGINS) as $p) {
$pclass = "button_" . trim($p);
if (class_exists($pclass)) {
$plugin = new $pclass($link);
$plugin = new $pclass();
array_push($button_plugins, $plugin);
}
}
} */
global $pluginhost;
if (db_num_rows($result) > 0) {
if ($this->dbh->num_rows($result) > 0) {
$lnum = $offset;
$num_unread = 0;
$cur_feed_title = '';
$fresh_intl = get_pref($this->link, "FRESH_ARTICLE_MAX_AGE") * 60 * 60;
$fresh_intl = get_pref("FRESH_ARTICLE_MAX_AGE") * 60 * 60;
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("PS", $timing_info);
$expand_cdm = get_pref($this->link, 'CDM_EXPANDED');
while ($line = db_fetch_assoc($result)) {
$class = ($lnum % 2) ? "even" : "odd";
$expand_cdm = get_pref('CDM_EXPANDED');
while ($line = $this->dbh->fetch_assoc($result)) {
$id = $line["id"];
$feed_id = $line["feed_id"];
$label_cache = $line["label_cache"];
$labels = false;
$label_row_style = "";
if ($label_cache) {
$label_cache = json_decode($label_cache, true);
@@ -317,23 +304,7 @@ class Feeds extends Handler_Protected {
}
}
if (!is_array($labels)) $labels = get_article_labels($this->link, $id);
if (count($labels) > 0) {
for ($i = 0; $i < min(4, count($labels)); $i++) {
$bg = rgb2hsl(_color_unpack($labels[$i][3]));
if ($bg && $bg[1] > 0) {
$bg[1] = 0.1;
$bg[2] = 1;
$bg = _color_pack(hsl2rgb($bg));
$label_row_style = $this->make_gradient($bg, $class);;
break;
}
}
}
if (!is_array($labels)) $labels = get_article_labels($id);
$labels_str = "<span id=\"HLLCTR-$id\">";
$labels_str .= format_article_labels($labels, $id);
@@ -343,6 +314,8 @@ class Feeds extends Handler_Protected {
array_push($topmost_article_ids, $id);
}
$class = "";
if (sql_bool_to_bool($line["unread"])) {
$class .= " Unread";
++$num_unread;
@@ -383,13 +356,13 @@ class Feeds extends Handler_Protected {
# $content_link = "<a href=\"javascript:viewContentUrl('".$line["link"]."');\">" .
# $line["title"] . "</a>";
$updated_fmt = make_local_datetime($this->link, $line["updated"], false);
$updated_fmt = make_local_datetime($line["updated"], false);
$date_entered_fmt = T_sprintf("Imported at %s",
make_local_datetime($this->link, $line["date_entered"], false));
make_local_datetime($line["date_entered"], false));
if (get_pref($this->link, 'SHOW_CONTENT_PREVIEW')) {
if (get_pref('SHOW_CONTENT_PREVIEW')) {
$content_preview = truncate_string(strip_tags($line["content_preview"]),
100);
250);
}
$score = $line["score"];
@@ -414,7 +387,7 @@ class Feeds extends Handler_Protected {
$entry_author = $line["author"];
if ($entry_author) {
$entry_author = " - $entry_author";
$entry_author = " &mdash; $entry_author";
}
$has_feed_icon = feed_has_icon($feed_id);
@@ -427,9 +400,37 @@ class Feeds extends Handler_Protected {
$entry_site_url = $line["site_url"];
if (!get_pref($this->link, 'COMBINED_DISPLAY_MODE')) {
//setting feed headline background color, needs to change text color based on dark/light
$fav_color = $line['favicon_avg_color'];
if (get_pref($this->link, 'VFEED_GROUP_BY_FEED')) {
require_once "colors.php";
if ($fav_color && $fav_color != 'fail') {
if (!isset($rgba_cache[$feed_id])) {
$rgba_cache[$feed_id] = join(",", _color_unpack($fav_color));
}
$rgba = $rgba_cache[$feed_id];
if (sql_bool_to_bool($line["unread"]))
$endalpha = '0.3';
else
$endalpha = '0.1';
// W3C definition seems to work in FF and Chrome
$row_background = "background-image : linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba($rgba, $endalpha) 100%);";
/* $row_background = "background-image : -moz-linear-gradient(left, rgba(255, 255, 255, 0) 50%, rgba($rgba, 0.2) 100%);".
"background-image : linear-gradient(to right, rgba(255, 255, 255, 0) 50%, rgba($rgba, 0.2) 100%);";
"background-image : -webkit-gradient(linear, left top, right top, color-stop(50%, rgba(255,255,255,0)),
color-stop(100%, rgba($rgba, 0.2)));"; */
} else {
$row_background = "";
}
if (!get_pref('COMBINED_DISPLAY_MODE')) {
if (get_pref('VFEED_GROUP_BY_FEED')) {
if ($feed_id != $vgroup_last_feed && $line["feed_title"]) {
$cur_feed_title = $line["feed_title"];
@@ -450,7 +451,7 @@ class Feeds extends Handler_Protected {
$mouseover_attrs = "onmouseover='postMouseIn(event, $id)'
onmouseout='postMouseOut($id)'";
$reply['content'] .= "<div class='hl $class' id='RROW-$id' $label_row_style $mouseover_attrs>";
$reply['content'] .= "<div class='hl $class' id='RROW-$id' $mouseover_attrs style='$row_background'>";
$reply['content'] .= "<div class='hlLeft'>";
@@ -470,7 +471,7 @@ class Feeds extends Handler_Protected {
onclick=\"\">" .
truncate_string($line["title"], 200);
if (get_pref($this->link, 'SHOW_CONTENT_PREVIEW')) {
if (get_pref('SHOW_CONTENT_PREVIEW')) {
if ($content_preview) {
$reply['content'] .= "<span class=\"contentPreview\"> - $content_preview</span>";
}
@@ -484,7 +485,7 @@ class Feeds extends Handler_Protected {
$reply['content'] .= "<span class=\"hlUpdated\">";
if (!get_pref($this->link, 'VFEED_GROUP_BY_FEED')) {
if (!get_pref('VFEED_GROUP_BY_FEED')) {
if (@$line["feed_title"]) {
$reply['content'] .= "<div class=\"hlFeed\">
<a href=\"#\" onclick=\"viewfeed($feed_id)\">".
@@ -500,7 +501,7 @@ class Feeds extends Handler_Protected {
$reply['content'] .= $score_pic;
if ($line["feed_title"] && !get_pref($this->link, 'VFEED_GROUP_BY_FEED')) {
if ($line["feed_title"] && !get_pref('VFEED_GROUP_BY_FEED')) {
$reply['content'] .= "<span onclick=\"viewfeed($feed_id)\"
style=\"cursor : pointer\"
@@ -513,17 +514,19 @@ class Feeds extends Handler_Protected {
} else {
$line["tags"] = get_article_tags($this->link, $id, $_SESSION["uid"], $line["tag_cache"]);
unset($line["tag_cache"]);
if ($line["tag_cache"])
$tags = explode(",", $line["tag_cache"]);
else
$tags = false;
$line["content"] = sanitize($this->link, $line["content_preview"],
$line["content"] = sanitize($line["content_preview"],
sql_bool_to_bool($line['hide_images']), false, $entry_site_url);
foreach ($pluginhost->get_hooks($pluginhost::HOOK_RENDER_ARTICLE_CDM) as $p) {
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_RENDER_ARTICLE_CDM) as $p) {
$line = $p->hook_render_article_cdm($line);
}
if (get_pref($this->link, 'VFEED_GROUP_BY_FEED') && $line["feed_title"]) {
if (get_pref('VFEED_GROUP_BY_FEED') && $line["feed_title"]) {
if ($feed_id != $vgroup_last_feed) {
$cur_feed_title = $line["feed_title"];
@@ -554,10 +557,9 @@ class Feeds extends Handler_Protected {
$expanded_class = $expand_cdm ? "expanded" : "expandable";
$reply['content'] .= "<div class=\"cdm $expanded_class $class\"
id=\"RROW-$id\" $mouseover_attrs'>";
$reply['content'] .= "<div class=\"cdmHeader\">";
id=\"RROW-$id\" $mouseover_attrs>";
$reply['content'] .= "<div class=\"cdmHeader\" style=\"$row_background\">";
$reply['content'] .= "<div style=\"vertical-align : middle\">";
$reply['content'] .= "<input dojoType=\"dijit.form.CheckBox\"
@@ -593,7 +595,7 @@ class Feeds extends Handler_Protected {
id=\"CEXC-$id\" class=\"cdmExcerpt\"> - $content_preview</span>";
$reply['content'] .= "</span>";
if (!get_pref($this->link, 'VFEED_GROUP_BY_FEED')) {
if (!get_pref('VFEED_GROUP_BY_FEED')) {
if (@$line["feed_title"]) {
$reply['content'] .= "<div class=\"hlFeed\">
<a href=\"#\" onclick=\"viewfeed($feed_id)\">".
@@ -608,7 +610,7 @@ class Feeds extends Handler_Protected {
$reply['content'] .= "<div style=\"vertical-align : middle\">";
$reply['content'] .= "$score_pic";
if (!get_pref($this->link, "VFEED_GROUP_BY_FEED") && $line["feed_title"]) {
if (!get_pref("VFEED_GROUP_BY_FEED") && $line["feed_title"]) {
$reply['content'] .= "<span style=\"cursor : pointer\"
title=\"".htmlspecialchars($line["feed_title"])."\"
onclick=\"viewfeed($feed_id)\">$feed_icon_img</span>";
@@ -627,22 +629,21 @@ class Feeds extends Handler_Protected {
}
$reply['content'] .= "</div>";
$reply['content'] .= "<div class=\"cdmContentInner\">";
if ($line["orig_feed_id"]) {
$tmp_result = db_query($this->link, "SELECT * FROM ttrss_archived_feeds
$tmp_result = $this->dbh->query("SELECT * FROM ttrss_archived_feeds
WHERE id = ".$line["orig_feed_id"]);
if (db_num_rows($tmp_result) != 0) {
if ($this->dbh->num_rows($tmp_result) != 0) {
$reply['content'] .= "<div clear='both'>";
$reply['content'] .= __("Originally from:");
$reply['content'] .= "&nbsp;";
$tmp_line = db_fetch_assoc($tmp_result);
$tmp_line = $this->dbh->fetch_assoc($tmp_result);
$reply['content'] .= "<a target='_blank'
href=' " . htmlspecialchars($tmp_line['site_url']) . "'>" .
@@ -672,22 +673,22 @@ class Feeds extends Handler_Protected {
$always_display_enclosures = sql_bool_to_bool($line["always_display_enclosures"]);
$reply['content'] .= format_article_enclosures($this->link, $id, $always_display_enclosures, $line["content"], sql_bool_to_bool($line["hide_images"]));
$reply['content'] .= format_article_enclosures($id, $always_display_enclosures, $line["content"], sql_bool_to_bool($line["hide_images"]));
$reply['content'] .= "</div>";
$reply['content'] .= "<div class=\"cdmFooter\">";
foreach ($pluginhost->get_hooks($pluginhost::HOOK_ARTICLE_LEFT_BUTTON) as $p) {
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_LEFT_BUTTON) as $p) {
$reply['content'] .= $p->hook_article_left_button($line);
}
$tags_str = format_tags_string($line["tags"], $id);
$tags_str = format_tags_string($tags, $id);
$reply['content'] .= "<img src='images/tag.png' alt='Tags' title='Tags'>
<span id=\"ATSTR-$id\">$tags_str</span>
<a title=\"".__('Edit tags for this article')."\"
href=\"#\" onclick=\"editArticleTags($id, $feed_id, true)\">(+)</a>";
href=\"#\" onclick=\"editArticleTags($id)\">(+)</a>";
$num_comments = $line["num_comments"];
$entry_comments = "";
@@ -712,7 +713,7 @@ class Feeds extends Handler_Protected {
// $reply['content'] .= "$marked_pic";
// $reply['content'] .= "$published_pic";
foreach ($pluginhost->get_hooks($pluginhost::HOOK_ARTICLE_BUTTON) as $p) {
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ARTICLE_BUTTON) as $p) {
$reply['content'] .= $p->hook_article_button($line);
}
@@ -756,18 +757,18 @@ class Feeds extends Handler_Protected {
$reply['content'] .= "<p><span class=\"insensitive\">";
$result = db_query($this->link, "SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds
$result = $this->dbh->query("SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds
WHERE owner_uid = " . $_SESSION['uid']);
$last_updated = db_fetch_result($result, 0, "last_updated");
$last_updated = make_local_datetime($this->link, $last_updated, false);
$last_updated = $this->dbh->fetch_result($result, 0, "last_updated");
$last_updated = make_local_datetime($last_updated, false);
$reply['content'] .= sprintf(__("Feeds last updated at %s"), $last_updated);
$result = db_query($this->link, "SELECT COUNT(id) AS num_errors
$result = $this->dbh->query("SELECT COUNT(id) AS num_errors
FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
$num_errors = db_fetch_result($result, 0, "num_errors");
$num_errors = $this->dbh->fetch_result($result, 0, "num_errors");
if ($num_errors > 0) {
$reply['content'] .= "<br/>";
@@ -785,9 +786,9 @@ class Feeds extends Handler_Protected {
}
function catchupAll() {
db_query($this->link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
last_read = NOW(), unread = false WHERE unread = true AND owner_uid = " . $_SESSION["uid"]);
ccache_zero_all($this->link, $_SESSION["uid"]);
ccache_zero_all($_SESSION["uid"]);
}
function view() {
@@ -797,17 +798,17 @@ class Feeds extends Handler_Protected {
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info);
$omode = db_escape_string($this->link, $_REQUEST["omode"]);
$omode = $this->dbh->escape_string($_REQUEST["omode"]);
$feed = db_escape_string($this->link, $_REQUEST["feed"]);
$method = db_escape_string($this->link, $_REQUEST["m"]);
$view_mode = db_escape_string($this->link, $_REQUEST["view_mode"]);
$feed = $this->dbh->escape_string($_REQUEST["feed"]);
$method = $this->dbh->escape_string($_REQUEST["m"]);
$view_mode = $this->dbh->escape_string($_REQUEST["view_mode"]);
$limit = 30;
@$cat_view = $_REQUEST["cat"] == "true";
@$next_unread_feed = db_escape_string($this->link, $_REQUEST["nuf"]);
@$offset = db_escape_string($this->link, $_REQUEST["skip"]);
@$vgroup_last_feed = db_escape_string($this->link, $_REQUEST["vgrlf"]);
$order_by = db_escape_string($this->link, $_REQUEST["order_by"]);
@$next_unread_feed = $this->dbh->escape_string($_REQUEST["nuf"]);
@$offset = $this->dbh->escape_string($_REQUEST["skip"]);
@$vgroup_last_feed = $this->dbh->escape_string($_REQUEST["vgrlf"]);
$order_by = $this->dbh->escape_string($_REQUEST["order_by"]);
if (is_numeric($feed)) $feed = (int) $feed;
@@ -815,7 +816,7 @@ class Feeds extends Handler_Protected {
* when there's nothing to load - e.g. no stuff in fresh feed */
if ($feed == -5) {
print json_encode($this->generate_dashboard_feed($this->link));
print json_encode($this->generate_dashboard_feed());
return;
}
@@ -823,18 +824,18 @@ class Feeds extends Handler_Protected {
if ($feed < LABEL_BASE_INDEX) {
$label_feed = feed_to_label_id($feed);
$result = db_query($this->link, "SELECT id FROM ttrss_labels2 WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_labels2 WHERE
id = '$label_feed' AND owner_uid = " . $_SESSION['uid']);
} else if (!$cat_view && is_numeric($feed) && $feed > 0) {
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
id = '$feed' AND owner_uid = " . $_SESSION['uid']);
} else if ($cat_view && is_numeric($feed) && $feed > 0) {
$result = db_query($this->link, "SELECT id FROM ttrss_feed_categories WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feed_categories WHERE
id = '$feed' AND owner_uid = " . $_SESSION['uid']);
}
if ($result && db_num_rows($result) == 0) {
print json_encode($this->generate_error_feed($this->link, __("Feed not found.")));
if ($result && $this->dbh->num_rows($result) == 0) {
print json_encode($this->generate_error_feed(__("Feed not found.")));
return;
}
@@ -842,21 +843,21 @@ class Feeds extends Handler_Protected {
* so for performance reasons we don't do that here */
if ($feed >= 0) {
ccache_update($this->link, $feed, $_SESSION["uid"], $cat_view);
ccache_update($feed, $_SESSION["uid"], $cat_view);
}
set_pref($this->link, "_DEFAULT_VIEW_MODE", $view_mode);
set_pref($this->link, "_DEFAULT_VIEW_ORDER_BY", $order_by);
set_pref("_DEFAULT_VIEW_MODE", $view_mode);
set_pref("_DEFAULT_VIEW_ORDER_BY", $order_by);
/* bump login timestamp if needed */
if (time() - $_SESSION["last_login_update"] > 3600) {
db_query($this->link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " .
$this->dbh->query("UPDATE ttrss_users SET last_login = NOW() WHERE id = " .
$_SESSION["uid"]);
$_SESSION["last_login_update"] = time();
}
if (!$cat_view && is_numeric($feed) && $feed > 0) {
db_query($this->link, "UPDATE ttrss_feeds SET last_viewed = NOW()
$this->dbh->query("UPDATE ttrss_feeds SET last_viewed = NOW()
WHERE id = '$feed' AND owner_uid = ".$_SESSION["uid"]);
}
@@ -906,13 +907,13 @@ class Feeds extends Handler_Protected {
if ($_REQUEST["debug"]) $timing_info = print_checkpoint("30", $timing_info);
$reply['runtime-info'] = make_runtime_info($this->link);
$reply['runtime-info'] = make_runtime_info();
print json_encode($reply);
}
private function generate_dashboard_feed($link) {
private function generate_dashboard_feed() {
$reply = array();
$reply['headlines']['id'] = -5;
@@ -923,18 +924,18 @@ class Feeds extends Handler_Protected {
$reply['headlines']['content'] .= "<p><span class=\"insensitive\">";
$result = db_query($link, "SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds
$result = $this->dbh->query("SELECT ".SUBSTRING_FOR_DATE."(MAX(last_updated), 1, 19) AS last_updated FROM ttrss_feeds
WHERE owner_uid = " . $_SESSION['uid']);
$last_updated = db_fetch_result($result, 0, "last_updated");
$last_updated = make_local_datetime($link, $last_updated, false);
$last_updated = $this->dbh->fetch_result($result, 0, "last_updated");
$last_updated = make_local_datetime($last_updated, false);
$reply['headlines']['content'] .= sprintf(__("Feeds last updated at %s"), $last_updated);
$result = db_query($link, "SELECT COUNT(id) AS num_errors
$result = $this->dbh->query("SELECT COUNT(id) AS num_errors
FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
$num_errors = db_fetch_result($result, 0, "num_errors");
$num_errors = $this->dbh->fetch_result($result, 0, "num_errors");
if ($num_errors > 0) {
$reply['headlines']['content'] .= "<br/>";
@@ -951,7 +952,7 @@ class Feeds extends Handler_Protected {
return $reply;
}
private function generate_error_feed($link, $error) {
private function generate_error_feed($error) {
$reply = array();
$reply['headlines']['id'] = -6;
@@ -985,9 +986,9 @@ class Feeds extends Handler_Protected {
print "<hr/>";
if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
if (get_pref('ENABLE_FEED_CATS')) {
print __('Place in category:') . " ";
print_feed_cat_select($this->link, "cat", false, 'dojoType="dijit.form.Select"');
print_feed_cat_select("cat", false, 'dojoType="dijit.form.Select"');
}
print "</div>";
@@ -1043,7 +1044,7 @@ class Feeds extends Handler_Protected {
function feedBrowser() {
if (defined('_DISABLE_FEED_BROWSER') && _DISABLE_FEED_BROWSER) return;
$browser_search = db_escape_string($this->link, $_REQUEST["search"]);
$browser_search = $this->dbh->escape_string($_REQUEST["search"]);
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=\"updateFeedBrowser\">";
@@ -1080,7 +1081,7 @@ class Feeds extends Handler_Protected {
require_once "feedbrowser.php";
print "<ul class='browseFeedList' id='browseFeedList'>";
print make_feed_browser($this->link, $search, 25);
print make_feed_browser($search, 25);
print "</ul>";
print "<div align='center'>
@@ -1091,7 +1092,7 @@ class Feeds extends Handler_Protected {
}
function search() {
$this->params = explode(":", db_escape_string($this->link, $_REQUEST["param"]), 2);
$this->params = explode(":", $this->dbh->escape_string($_REQUEST["param"]), 2);
$active_feed_id = sprintf("%d", $this->params[0]);
$is_cat = $this->params[1] != "false";
@@ -1109,12 +1110,12 @@ class Feeds extends Handler_Protected {
print "<select name=\"search_mode\" dojoType=\"dijit.form.Select\">
<option value=\"all_feeds\">".__('All feeds')."</option>";
$feed_title = getFeedTitle($this->link, $active_feed_id);
$feed_title = getFeedTitle($active_feed_id);
if (!$is_cat) {
$feed_cat_title = getFeedCatTitle($this->link, $active_feed_id);
$feed_cat_title = getFeedCatTitle($active_feed_id);
} else {
$feed_cat_title = getCategoryTitle($this->link, $active_feed_id);
$feed_cat_title = getCategoryTitle($active_feed_id);
}
if ($active_feed_id && !$is_cat) {
@@ -1127,7 +1128,7 @@ class Feeds extends Handler_Protected {
$cat_preselected = "selected=\"1\"";
}
if (get_pref($this->link, 'ENABLE_FEED_CATS') && ($active_feed_id > 0 || $is_cat)) {
if (get_pref('ENABLE_FEED_CATS') && ($active_feed_id > 0 || $is_cat)) {
print "<option $cat_preselected value=\"this_cat\">$feed_cat_title</option>";
} else {
//print "<option disabled>".__('This category')."</option>";

View File

@@ -1,10 +1,10 @@
<?php
class Handler implements IHandler {
protected $link;
protected $dbh;
protected $args;
function __construct($link, $args) {
$this->link = $link;
function __construct($args) {
$this->dbh = Db::get();
$this->args = $args;
}

View File

@@ -21,15 +21,15 @@ class Handler_Public extends Handler {
else if ($feed == -1)
$date_sort_field = "last_marked DESC";
$qfh_ret = queryFeedHeadlines($this->link, $feed,
$qfh_ret = queryFeedHeadlines($feed,
1, $view_mode, $is_cat, $search, $search_mode,
$date_sort_field, $offset, $owner_uid,
false, 0, false, true);
$result = $qfh_ret[0];
if (db_num_rows($result) != 0) {
$ts = strtotime(db_fetch_result($result, 0, "date_entered"));
if ($this->dbh->num_rows($result) != 0) {
$ts = strtotime($this->dbh->fetch_result($result, 0, "date_entered"));
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $ts) {
@@ -41,7 +41,7 @@ class Handler_Public extends Handler {
header("Last-Modified: $last_modified", true);
}
$qfh_ret = queryFeedHeadlines($this->link, $feed,
$qfh_ret = queryFeedHeadlines($feed,
$limit, $view_mode, $is_cat, $search, $search_mode,
$date_sort_field, $offset, $owner_uid,
false, 0, false, true);
@@ -54,7 +54,7 @@ class Handler_Public extends Handler {
$feed_self_url = get_self_url_prefix() .
"/public.php?op=rss&id=-2&key=" .
get_feed_access_key($this->link, -2, false, $owner_uid);
get_feed_access_key(-2, false, $owner_uid);
if (!$feed_site_url) $feed_site_url = get_self_url_prefix();
@@ -74,7 +74,7 @@ class Handler_Public extends Handler {
$tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$tpl->setVariable('ARTICLE_ID', htmlspecialchars($line['link']), true);
$tpl->setVariable('ARTICLE_LINK', htmlspecialchars($line['link']), true);
@@ -82,7 +82,7 @@ class Handler_Public extends Handler {
$tpl->setVariable('ARTICLE_EXCERPT',
truncate_string(strip_tags($line["content_preview"]), 100, '...'), true);
$content = sanitize($this->link, $line["content_preview"], false, $owner_uid);
$content = sanitize($line["content_preview"], false, $owner_uid);
if ($line['note']) {
$content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
@@ -99,14 +99,14 @@ class Handler_Public extends Handler {
$tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
$tags = get_article_tags($this->link, $line["id"], $owner_uid);
$tags = get_article_tags($line["id"], $owner_uid);
foreach ($tags as $tag) {
$tpl->setVariable('ARTICLE_CATEGORY', htmlspecialchars($tag), true);
$tpl->addBlock('category');
}
$enclosures = get_article_enclosures($this->link, $line["id"]);
$enclosures = get_article_enclosures($line["id"]);
foreach ($enclosures as $e) {
$type = htmlspecialchars($e['content_type']);
@@ -151,20 +151,20 @@ class Handler_Public extends Handler {
$feed['articles'] = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$article = array();
$article['id'] = $line['link'];
$article['link'] = $line['link'];
$article['title'] = $line['title'];
$article['excerpt'] = truncate_string(strip_tags($line["content_preview"]), 100, '...');
$article['content'] = sanitize($this->link, $line["content_preview"], false, $owner_uid);
$article['content'] = sanitize($line["content_preview"], false, $owner_uid);
$article['updated'] = date('c', strtotime($line["updated"]));
if ($line['note']) $article['note'] = $line['note'];
if ($article['author']) $article['author'] = $line['author'];
$tags = get_article_tags($this->link, $line["id"], $owner_uid);
$tags = get_article_tags($line["id"], $owner_uid);
if (count($tags) > 0) {
$article['tags'] = array();
@@ -174,7 +174,7 @@ class Handler_Public extends Handler {
}
}
$enclosures = get_article_enclosures($this->link, $line["id"]);
$enclosures = get_article_enclosures($line["id"]);
if (count($enclosures) > 0) {
$article['enclosures'] = array();
@@ -201,19 +201,19 @@ class Handler_Public extends Handler {
}
function getUnread() {
$login = db_escape_string($this->link, $_REQUEST["login"]);
$login = $this->dbh->escape_string($_REQUEST["login"]);
$fresh = $_REQUEST["fresh"] == "1";
$result = db_query($this->link, "SELECT id FROM ttrss_users WHERE login = '$login'");
$result = $this->dbh->query("SELECT id FROM ttrss_users WHERE login = '$login'");
if (db_num_rows($result) == 1) {
$uid = db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) == 1) {
$uid = $this->dbh->fetch_result($result, 0, "id");
print getGlobalUnread($this->link, $uid);
print getGlobalUnread($uid);
if ($fresh) {
print ";";
print getFeedArticles($this->link, -3, false, true, $uid);
print getFeedArticles(-3, false, true, $uid);
}
} else {
@@ -223,16 +223,16 @@ class Handler_Public extends Handler {
}
function getProfiles() {
$login = db_escape_string($this->link, $_REQUEST["login"]);
$login = $this->dbh->escape_string($_REQUEST["login"]);
$result = db_query($this->link, "SELECT * FROM ttrss_settings_profiles,ttrss_users
$result = $this->dbh->query("SELECT * FROM ttrss_settings_profiles,ttrss_users
WHERE ttrss_users.id = ttrss_settings_profiles.owner_uid AND login = '$login' ORDER BY title");
print "<select dojoType='dijit.form.Select' style='width : 220px; margin : 0px' name='profile'>";
print "<option value='0'>" . __("Default profile") . "</option>";
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$id = $line["id"];
$title = $line["title"];
@@ -243,9 +243,9 @@ class Handler_Public extends Handler {
}
function pubsub() {
$mode = db_escape_string($this->link, $_REQUEST['hub_mode']);
$feed_id = (int) db_escape_string($this->link, $_REQUEST['id']);
$feed_url = db_escape_string($this->link, $_REQUEST['hub_topic']);
$mode = $this->dbh->escape_string($_REQUEST['hub_mode']);
$feed_id = (int) $this->dbh->escape_string($_REQUEST['id']);
$feed_url = $this->dbh->escape_string($_REQUEST['hub_topic']);
if (!PUBSUBHUBBUB_ENABLED) {
header('HTTP/1.0 404 Not Found');
@@ -255,17 +255,17 @@ class Handler_Public extends Handler {
// TODO: implement hub_verifytoken checking
$result = db_query($this->link, "SELECT feed_url FROM ttrss_feeds
$result = $this->dbh->query("SELECT feed_url FROM ttrss_feeds
WHERE id = '$feed_id'");
if (db_num_rows($result) != 0) {
if ($this->dbh->num_rows($result) != 0) {
$check_feed_url = db_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)) {
if ($mode == "subscribe") {
db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 2
$this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 2
WHERE id = '$feed_id'");
print $_REQUEST['hub_challenge'];
@@ -273,7 +273,7 @@ class Handler_Public extends Handler {
} else if ($mode == "unsubscribe") {
db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0
$this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 0
WHERE id = '$feed_id'");
print $_REQUEST['hub_challenge'];
@@ -282,9 +282,9 @@ class Handler_Public extends Handler {
} else if (!$mode) {
// Received update ping, schedule feed update.
//update_rss_feed($this->link, $feed_id, true, true);
//update_rss_feed($feed_id, true, true);
db_query($this->link, "UPDATE ttrss_feeds SET
$this->dbh->query("UPDATE ttrss_feeds SET
last_update_started = '1970-01-01',
last_updated = '1970-01-01' WHERE id = '$feed_id'");
@@ -306,18 +306,18 @@ class Handler_Public extends Handler {
}
function share() {
$uuid = db_escape_string($this->link, $_REQUEST["key"]);
$uuid = $this->dbh->escape_string($_REQUEST["key"]);
$result = db_query($this->link, "SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE
$result = $this->dbh->query("SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE
uuid = '$uuid'");
if (db_num_rows($result) != 0) {
if ($this->dbh->num_rows($result) != 0) {
header("Content-Type: text/html");
$id = db_fetch_result($result, 0, "ref_id");
$owner_uid = db_fetch_result($result, 0, "owner_uid");
$id = $this->dbh->fetch_result($result, 0, "ref_id");
$owner_uid = $this->dbh->fetch_result($result, 0, "owner_uid");
$article = format_article($this->link, $id, false, true, $owner_uid);
$article = format_article($id, false, true, $owner_uid);
print_r($article['content']);
@@ -328,32 +328,32 @@ class Handler_Public extends Handler {
}
function rss() {
$feed = db_escape_string($this->link, $_REQUEST["id"]);
$key = db_escape_string($this->link, $_REQUEST["key"]);
$feed = $this->dbh->escape_string($_REQUEST["id"]);
$key = $this->dbh->escape_string($_REQUEST["key"]);
$is_cat = $_REQUEST["is_cat"] != false;
$limit = (int)db_escape_string($this->link, $_REQUEST["limit"]);
$offset = (int)db_escape_string($this->link, $_REQUEST["offset"]);
$limit = (int)$this->dbh->escape_string($_REQUEST["limit"]);
$offset = (int)$this->dbh->escape_string($_REQUEST["offset"]);
$search = db_escape_string($this->link, $_REQUEST["q"]);
$search_mode = db_escape_string($this->link, $_REQUEST["smode"]);
$view_mode = db_escape_string($this->link, $_REQUEST["view-mode"]);
$search = $this->dbh->escape_string($_REQUEST["q"]);
$search_mode = $this->dbh->escape_string($_REQUEST["smode"]);
$view_mode = $this->dbh->escape_string($_REQUEST["view-mode"]);
$format = db_escape_string($this->link, $_REQUEST['format']);
$format = $this->dbh->escape_string($_REQUEST['format']);
if (!$format) $format = 'atom';
if (SINGLE_USER_MODE) {
authenticate_user($this->link, "admin", null);
authenticate_user("admin", null);
}
$owner_id = false;
if ($key) {
$result = db_query($this->link, "SELECT owner_uid FROM
$result = $this->dbh->query("SELECT owner_uid FROM
ttrss_access_keys WHERE access_key = '$key' AND feed_id = '$feed'");
if (db_num_rows($result) == 1)
$owner_id = db_fetch_result($result, 0, "owner_uid");
if ($this->dbh->num_rows($result) == 1)
$owner_id = $this->dbh->fetch_result($result, 0, "owner_uid");
}
if ($owner_id) {
@@ -367,32 +367,24 @@ class Handler_Public extends Handler {
function globalUpdateFeeds() {
include "rssfuncs.php";
// Update all feeds needing a update.
update_daemon_common($this->link, 0, true, false);
update_daemon_common(0, true, false);
housekeeping_common(false);
// Update feedbrowser
update_feedbrowser_cache($this->link);
// Purge orphans and cleanup tags
purge_orphans($this->link);
cleanup_tags($this->link, 14, 50000);
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_UPDATE_TASK, "hook_update_task", $op);
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", $op);
}
function sharepopup() {
if (SINGLE_USER_MODE) {
login_sequence($this->link);
login_sequence();
}
header('Content-Type: text/html; charset=utf-8');
print "<html><head><title>Tiny Tiny RSS</title>";
print stylesheet_tag("utility.css");
print javascript_tag("lib/prototype.js");
print javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls");
stylesheet_tag("utility.css");
javascript_tag("lib/prototype.js");
javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,dragdrop,controls");
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
</head><body id='sharepopup'>";
@@ -402,12 +394,12 @@ class Handler_Public extends Handler {
if ($action == 'share') {
$title = db_escape_string($this->link, strip_tags($_REQUEST["title"]));
$url = db_escape_string($this->link, strip_tags($_REQUEST["url"]));
$content = db_escape_string($this->link, strip_tags($_REQUEST["content"]));
$labels = db_escape_string($this->link, strip_tags($_REQUEST["labels"]));
$title = $this->dbh->escape_string(strip_tags($_REQUEST["title"]));
$url = $this->dbh->escape_string(strip_tags($_REQUEST["url"]));
$content = $this->dbh->escape_string(strip_tags($_REQUEST["content"]));
$labels = $this->dbh->escape_string(strip_tags($_REQUEST["labels"]));
Article::create_published_article($this->link, $title, $url, $content, $labels,
Article::create_published_article($title, $url, $content, $labels,
$_SESSION["uid"]);
print "<script type='text/javascript'>";
@@ -486,14 +478,6 @@ class Handler_Public extends Handler {
<tr><td align="right"><?php echo __("Password:") ?></td>
<td align="right"><input type="password" name="password"
value="<?php echo $_SESSION["fake_password"] ?>"></td></tr>
<tr><td align="right"><?php echo __("Language:") ?></td>
<td align="right">
<?php
print_select_hash("language", $_COOKIE["ttrss_lang"], get_translations(),
"style='width : 100%''");
?>
</td></tr>
<tr><td colspan='2'>
<button type="submit">
<?php echo __('Log in') ?></button>
@@ -509,11 +493,9 @@ class Handler_Public extends Handler {
}
function login() {
$_SESSION["prefs_cache"] = array();
if (!SINGLE_USER_MODE) {
$login = db_escape_string($this->link, $_POST["login"]);
$login = $this->dbh->escape_string($_POST["login"]);
$password = $_POST["password"];
$remember_me = $_POST["remember_me"];
@@ -525,23 +507,25 @@ class Handler_Public extends Handler {
@session_start();
if (authenticate_user($this->link, $login, $password)) {
if (authenticate_user($login, $password)) {
$_POST["password"] = "";
$_SESSION["language"] = $_POST["language"];
$_SESSION["ref_schema_version"] = get_schema_version($this->link, true);
if (get_schema_version() >= 120) {
$_SESSION["language"] = get_pref("USER_LANGUAGE", $_SESSION["uid"]);
}
$_SESSION["ref_schema_version"] = get_schema_version(true);
$_SESSION["bw_limit"] = !!$_POST["bw_limit"];
if ($_POST["profile"]) {
$profile = db_escape_string($this->link, $_POST["profile"]);
$profile = $this->dbh->escape_string($_POST["profile"]);
$result = db_query($this->link, "SELECT id FROM ttrss_settings_profiles
$result = $this->dbh->query("SELECT id FROM ttrss_settings_profiles
WHERE id = '$profile' AND owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($result) != 0) {
if ($this->dbh->num_rows($result) != 0) {
$_SESSION["profile"] = $profile;
$_SESSION["prefs_cache"] = array();
}
}
} else {
@@ -558,12 +542,12 @@ class Handler_Public extends Handler {
function subscribe() {
if (SINGLE_USER_MODE) {
login_sequence($this->link);
login_sequence();
}
if ($_SESSION["uid"]) {
$feed_url = db_escape_string($this->link, trim($_REQUEST["feed_url"]));
$feed_url = $this->dbh->escape_string(trim($_REQUEST["feed_url"]));
header('Content-Type: text/html; charset=utf-8');
print "<html>
@@ -577,7 +561,7 @@ class Handler_Public extends Handler {
alt=\"Tiny Tiny RSS\"/>
<h1>".__("Subscribe to feed...")."</h1><div class='content'>";
$rc = subscribe_to_feed($this->link, $feed_url);
$rc = subscribe_to_feed($feed_url);
switch ($rc['code']) {
case 0:
@@ -625,10 +609,10 @@ class Handler_Public extends Handler {
$tt_uri = get_self_url_prefix();
if ($rc['code'] <= 2){
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
$feed_id = db_fetch_result($result, 0, "id");
$feed_id = $this->dbh->fetch_result($result, 0, "id");
} else {
$feed_id = 0;
}
@@ -651,21 +635,22 @@ class Handler_Public extends Handler {
print "</div></body></html>";
} else {
render_login_form($this->link);
render_login_form();
}
}
function subscribe2() {
$feed_url = db_escape_string($this->link, trim($_REQUEST["feed_url"]));
$cat_id = db_escape_string($this->link, $_REQUEST["cat_id"]);
$from = db_escape_string($this->link, $_REQUEST["from"]);
$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 = db_escape_string($this->link, trim($_POST["auth_login"]));
$auth_pass = db_escape_string($this->link, trim($_POST["auth_pass"]));
$auth_login = $this->dbh->escape_string(trim($_POST["auth_login"]));
$auth_pass = $this->dbh->escape_string(trim($_POST["auth_pass"]));
$rc = subscribe_to_feed($this->link, $feed_url, $cat_id, $auth_login, $auth_pass);
$rc = subscribe_to_feed($feed_url, $cat_id, $auth_login, $auth_pass);
switch ($rc) {
case 1:
@@ -682,8 +667,10 @@ class Handler_Public extends Handler {
break;
case 4:
print_notice(__("Multiple feed URLs found."));
$feed_urls = get_feeds_from_html($feed_url);
$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));
@@ -712,10 +699,10 @@ class Handler_Public extends Handler {
$tt_uri = get_self_url_prefix();
if ($rc <= 2){
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
$feed_id = db_fetch_result($result, 0, "id");
$feed_id = $this->dbh->fetch_result($result, 0, "id");
} else {
$feed_id = 0;
}
@@ -748,8 +735,8 @@ class Handler_Public extends Handler {
header('Content-Type: text/html; charset=utf-8');
print "<html><head><title>Tiny Tiny RSS</title>";
print stylesheet_tag("utility.css");
print javascript_tag("lib/prototype.js");
stylesheet_tag("utility.css");
javascript_tag("lib/prototype.js");
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
</head><body id='forgotpass'>";
@@ -788,9 +775,9 @@ class Handler_Public extends Handler {
print "</form>";
} else if ($method == 'do') {
$login = db_escape_string($this->link, $_POST["login"]);
$email = db_escape_string($this->link, $_POST["email"]);
$test = db_escape_string($this->link, $_POST["test"]);
$login = $this->dbh->escape_string($_POST["login"]);
$email = $this->dbh->escape_string($_POST["email"]);
$test = $this->dbh->escape_string($_POST["test"]);
if (($test != 4 && $test != 'four') || !$email || !$login) {
print_error(__('Some of the required form parameters are missing or incorrect.'));
@@ -802,13 +789,13 @@ class Handler_Public extends Handler {
} else {
$result = db_query($this->link, "SELECT id FROM ttrss_users
$result = $this->dbh->query("SELECT id FROM ttrss_users
WHERE login = '$login' AND email = '$email'");
if (db_num_rows($result) != 0) {
$id = db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) != 0) {
$id = $this->dbh->fetch_result($result, 0, "id");
Pref_Users::resetUserPassword($this->link, $id, false);
Pref_Users::resetUserPassword($id, false);
print "<p>";
@@ -840,7 +827,7 @@ class Handler_Public extends Handler {
function dbupdate() {
if (!SINGLE_USER_MODE && $_SESSION["access_level"] < 10) {
$_SESSION["login_error_msg"] = __("Your access level is insufficient to run this script.");
render_login_form($link);
render_login_form();
exit;
}
@@ -869,7 +856,7 @@ class Handler_Public extends Handler {
<?php
@$op = $_REQUEST["subop"];
$updater = new DbUpdater($this->link, DB_TYPE, SCHEMA_VERSION);
$updater = new DbUpdater(Db::get(), DB_TYPE, SCHEMA_VERSION);
if ($op == "performupdate") {
if ($updater->isUpdateRequired()) {
@@ -933,7 +920,7 @@ class Handler_Public extends Handler {
} else {
print "<h2>" . "Tiny Tiny RSS database is up to date." . "</h2>";
print_notice("Tiny Tiny RSS database is up to date.");
print "<p><form method=\"GET\" action=\"index.php\">
<input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">

13
classes/idb.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
interface IDb {
function connect($host, $user, $pass, $db, $port);
function escape_string($s, $strip_tags = true);
function query($query, $die_on_error = true);
function fetch_assoc($result);
function num_rows($result);
function fetch_result($result, $row, $param);
function close();
function affected_rows($result);
function last_error();
}
?>

65
classes/logger.php Normal file
View File

@@ -0,0 +1,65 @@
<?php
class Logger {
private static $instance;
private $adapter;
public static $errornames = array(
1 => 'E_ERROR',
2 => 'E_WARNING',
4 => 'E_PARSE',
8 => 'E_NOTICE',
16 => 'E_CORE_ERROR',
32 => 'E_CORE_WARNING',
64 => 'E_COMPILE_ERROR',
128 => 'E_COMPILE_WARNING',
256 => 'E_USER_ERROR',
512 => 'E_USER_WARNING',
1024 => 'E_USER_NOTICE',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
32767 => 'E_ALL');
function log_error($errno, $errstr, $file, $line, $context) {
if ($errno == E_NOTICE) return false;
if ($this->adapter)
return $this->adapter->log_error($errno, $errstr, $file, $line, $context);
else
return false;
}
function log($string) {
if ($this->adapter)
return $this->adapter->log($string);
else
return false;
}
private function __clone() {
//
}
function __construct() {
switch (LOG_DESTINATION) {
case "sql":
$this->adapter = new Logger_SQL();
break;
case "syslog":
$this->adapter = new Logger_Syslog();
break;
default:
$this->adapter = false;
}
}
public static function get() {
if (self::$instance == null)
self::$instance = new self();
return self::$instance;
}
}
?>

28
classes/logger/sql.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
class Logger_SQL {
function log_error($errno, $errstr, $file, $line, $context) {
if (Db::get() && get_schema_version() > 117) {
$errno = Db::get()->escape_string($errno);
$errstr = Db::get()->escape_string($errstr);
$file = Db::get()->escape_string($file);
$line = Db::get()->escape_string($line);
$context = ''; // backtrace is a lot of data which is not really critical to store
//$context = $this->dbh->escape_string(serialize($context));
$owner_uid = $_SESSION["uid"] ? $_SESSION["uid"] : "NULL";
$result = Db::get()->query(
"INSERT INTO ttrss_error_log
(errno, errstr, filename, lineno, context, owner_uid, created_at) VALUES
($errno, '$errstr', '$file', '$line', '$context', $owner_uid, NOW())");
return Db::get()->affected_rows($result) != 0;
}
return false;
}
}
?>

31
classes/logger/syslog.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
class Logger_Syslog {
function log_error($errno, $errstr, $file, $line, $context) {
switch ($errno) {
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$priority = LOG_ERR;
break;
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
$priority = LOG_WARNING;
break;
default:
$priority = LOG_INFO;
}
$errname = Logger::$errornames[$errno] . " ($errno)";
syslog($priority, "[tt-rss] $errname ($file:$line) $errstr");
}
}
?>

View File

@@ -32,7 +32,7 @@ class Opml extends Handler_Protected {
<div class=\"floatingLogo\"><img src=\"images/logo_small.png\"></div>
<h1>".__('OPML Utility')."</h1><div class='content'>";
add_feed_category($this->link, "Imported feeds");
add_feed_category("Imported feeds");
$this->opml_notice(__("Importing OPML..."));
$this->opml_import($owner_uid);
@@ -66,27 +66,27 @@ class Opml extends Handler_Protected {
$out = "";
if ($cat_id) {
$result = db_query($this->link, "SELECT title FROM ttrss_feed_categories WHERE id = '$cat_id'
$result = $this->dbh->query("SELECT title FROM ttrss_feed_categories WHERE id = '$cat_id'
AND owner_uid = '$owner_uid'");
$cat_title = htmlspecialchars(db_fetch_result($result, 0, "title"));
$cat_title = htmlspecialchars($this->dbh->fetch_result($result, 0, "title"));
}
if ($cat_title) $out .= "<outline text=\"$cat_title\">\n";
$result = db_query($this->link, "SELECT id,title
$result = $this->dbh->query("SELECT id,title
FROM ttrss_feed_categories WHERE
$cat_qpart AND owner_uid = '$owner_uid' ORDER BY order_id, title");
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$title = htmlspecialchars($line["title"]);
$out .= $this->opml_export_category($owner_uid, $line["id"], $hide_private_feeds);
}
$feeds_result = db_query($this->link, "select title, feed_url, site_url
$feeds_result = $this->dbh->query("select title, feed_url, site_url
from ttrss_feeds where $feed_cat_qpart AND owner_uid = '$owner_uid' AND $hide_qpart
order by order_id, title");
while ($fline = db_fetch_assoc($feeds_result)) {
while ($fline = $this->dbh->fetch_assoc($feeds_result)) {
$title = htmlspecialchars($fline["title"]);
$url = htmlspecialchars($fline["feed_url"]);
$site_url = htmlspecialchars($fline["site_url"]);
@@ -131,10 +131,10 @@ class Opml extends Handler_Protected {
if ($include_settings) {
$out .= "<outline text=\"tt-rss-prefs\" schema-version=\"".SCHEMA_VERSION."\">";
$result = db_query($this->link, "SELECT pref_name, value FROM ttrss_user_prefs WHERE
$result = $this->dbh->query("SELECT pref_name, value FROM ttrss_user_prefs WHERE
profile IS NULL AND owner_uid = " . $_SESSION["uid"] . " ORDER BY pref_name");
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$name = $line["pref_name"];
$value = htmlspecialchars($line["value"]);
@@ -145,10 +145,10 @@ class Opml extends Handler_Protected {
$out .= "<outline text=\"tt-rss-labels\" schema-version=\"".SCHEMA_VERSION."\">";
$result = db_query($this->link, "SELECT * FROM ttrss_labels2 WHERE
$result = $this->dbh->query("SELECT * FROM ttrss_labels2 WHERE
owner_uid = " . $_SESSION['uid']);
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$name = htmlspecialchars($line['caption']);
$fg_color = htmlspecialchars($line['fg_color']);
$bg_color = htmlspecialchars($line['bg_color']);
@@ -161,10 +161,10 @@ class Opml extends Handler_Protected {
$out .= "<outline text=\"tt-rss-filters\" schema-version=\"".SCHEMA_VERSION."\">";
$result = db_query($this->link, "SELECT * FROM ttrss_filters2
$result = $this->dbh->query("SELECT * FROM ttrss_filters2
WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY id");
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
foreach (array('enabled', 'match_any_rule') as $b) {
$line[$b] = sql_bool_to_bool($line[$b]);
}
@@ -172,17 +172,17 @@ class Opml extends Handler_Protected {
$line["rules"] = array();
$line["actions"] = array();
$tmp_result = db_query($this->link, "SELECT * FROM ttrss_filters2_rules
$tmp_result = $this->dbh->query("SELECT * FROM ttrss_filters2_rules
WHERE filter_id = ".$line["id"]);
while ($tmp_line = db_fetch_assoc($tmp_result)) {
while ($tmp_line = $this->dbh->fetch_assoc($tmp_result)) {
unset($tmp_line["id"]);
unset($tmp_line["filter_id"]);
$cat_filter = sql_bool_to_bool($tmp_line["cat_filter"]);
if ($cat_filter && $tmp_line["cat_id"] || $tmp_line["feed_id"]) {
$tmp_line["feed"] = getFeedTitle($this->link,
$tmp_line["feed"] = getFeedTitle(
$cat_filter ? $tmp_line["cat_id"] : $tmp_line["feed_id"],
$cat_filter);
} else {
@@ -197,10 +197,10 @@ class Opml extends Handler_Protected {
array_push($line["rules"], $tmp_line);
}
$tmp_result = db_query($this->link, "SELECT * FROM ttrss_filters2_actions
$tmp_result = $this->dbh->query("SELECT * FROM ttrss_filters2_actions
WHERE filter_id = ".$line["id"]);
while ($tmp_line = db_fetch_assoc($tmp_result)) {
while ($tmp_line = $this->dbh->fetch_assoc($tmp_result)) {
unset($tmp_line["id"]);
unset($tmp_line["filter_id"]);
@@ -253,19 +253,19 @@ class Opml extends Handler_Protected {
private function opml_import_feed($doc, $node, $cat_id, $owner_uid) {
$attrs = $node->attributes;
$feed_title = db_escape_string($this->link, mb_substr($attrs->getNamedItem('text')->nodeValue, 0, 250));
if (!$feed_title) $feed_title = db_escape_string($this->link, mb_substr($attrs->getNamedItem('title')->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));
$feed_url = db_escape_string($this->link, mb_substr($attrs->getNamedItem('xmlUrl')->nodeValue, 0, 250));
if (!$feed_url) $feed_url = db_escape_string($this->link, mb_substr($attrs->getNamedItem('xmlURL')->nodeValue, 0, 250));
$feed_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('xmlUrl')->nodeValue, 0, 250));
if (!$feed_url) $feed_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('xmlURL')->nodeValue, 0, 250));
$site_url = db_escape_string($this->link, mb_substr($attrs->getNamedItem('htmlUrl')->nodeValue, 0, 250));
$site_url = $this->dbh->escape_string(mb_substr($attrs->getNamedItem('htmlUrl')->nodeValue, 0, 250));
if ($feed_url && $feed_title) {
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
feed_url = '$feed_url' AND owner_uid = '$owner_uid'");
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
#$this->opml_notice("[FEED] [$feed_title/$feed_url] dst_CAT=$cat_id");
$this->opml_notice(T_sprintf("Adding feed: %s", $feed_title));
@@ -275,7 +275,7 @@ class Opml extends Handler_Protected {
(title, feed_url, owner_uid, cat_id, site_url, order_id) VALUES
('$feed_title', '$feed_url', '$owner_uid',
$cat_id, '$site_url', 0)";
db_query($this->link, $query);
$this->dbh->query($query);
} else {
$this->opml_notice(T_sprintf("Duplicate feed: %s", $feed_title));
@@ -285,15 +285,15 @@ class Opml extends Handler_Protected {
private function opml_import_label($doc, $node, $owner_uid) {
$attrs = $node->attributes;
$label_name = db_escape_string($this->link, $attrs->getNamedItem('label-name')->nodeValue);
$label_name = $this->dbh->escape_string($attrs->getNamedItem('label-name')->nodeValue);
if ($label_name) {
$fg_color = db_escape_string($this->link, $attrs->getNamedItem('label-fg-color')->nodeValue);
$bg_color = db_escape_string($this->link, $attrs->getNamedItem('label-bg-color')->nodeValue);
$fg_color = $this->dbh->escape_string($attrs->getNamedItem('label-fg-color')->nodeValue);
$bg_color = $this->dbh->escape_string($attrs->getNamedItem('label-bg-color')->nodeValue);
if (!label_find_id($this->link, $label_name, $_SESSION['uid'])) {
if (!label_find_id($label_name, $_SESSION['uid'])) {
$this->opml_notice(T_sprintf("Adding label %s", htmlspecialchars($label_name)));
label_create($this->link, $label_name, $fg_color, $bg_color, $owner_uid);
label_create($label_name, $fg_color, $bg_color, $owner_uid);
} else {
$this->opml_notice(T_sprintf("Duplicate label: %s", htmlspecialchars($label_name)));
}
@@ -302,22 +302,22 @@ class Opml extends Handler_Protected {
private function opml_import_preference($doc, $node, $owner_uid) {
$attrs = $node->attributes;
$pref_name = db_escape_string($this->link, $attrs->getNamedItem('pref-name')->nodeValue);
$pref_name = $this->dbh->escape_string($attrs->getNamedItem('pref-name')->nodeValue);
if ($pref_name) {
$pref_value = db_escape_string($this->link, $attrs->getNamedItem('value')->nodeValue);
$pref_value = $this->dbh->escape_string($attrs->getNamedItem('value')->nodeValue);
$this->opml_notice(T_sprintf("Setting preference key %s to %s",
$pref_name, $pref_value));
set_pref($this->link, $pref_name, $pref_value);
set_pref($pref_name, $pref_value);
}
}
private function opml_import_filter($doc, $node, $owner_uid) {
$attrs = $node->attributes;
$filter_type = db_escape_string($this->link, $attrs->getNamedItem('filter-type')->nodeValue);
$filter_type = $this->dbh->escape_string($attrs->getNamedItem('filter-type')->nodeValue);
if ($filter_type == '2') {
$filter = json_decode($node->nodeValue, true);
@@ -326,14 +326,14 @@ class Opml extends Handler_Protected {
$match_any_rule = bool_to_sql_bool($filter["match_any_rule"]);
$enabled = bool_to_sql_bool($filter["enabled"]);
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
db_query($this->link, "INSERT INTO ttrss_filters2 (match_any_rule,enabled,owner_uid)
$this->dbh->query("INSERT INTO ttrss_filters2 (match_any_rule,enabled,owner_uid)
VALUES ($match_any_rule, $enabled,".$_SESSION["uid"].")");
$result = db_query($this->link, "SELECT MAX(id) AS id FROM ttrss_filters2 WHERE
$result = $this->dbh->query("SELECT MAX(id) AS id FROM ttrss_filters2 WHERE
owner_uid = ".$_SESSION["uid"]);
$filter_id = db_fetch_result($result, 0, "id");
$filter_id = $this->dbh->fetch_result($result, 0, "id");
if ($filter_id) {
$this->opml_notice(T_sprintf("Adding filter..."));
@@ -343,39 +343,39 @@ class Opml extends Handler_Protected {
$cat_id = "NULL";
if (!$rule["cat_filter"]) {
$tmp_result = db_query($this->link, "SELECT id FROM ttrss_feeds
WHERE title = '".db_escape_string($this->link, $rule["feed"])."' AND owner_uid = ".$_SESSION["uid"]);
if (db_num_rows($tmp_result) > 0) {
$feed_id = db_fetch_result($tmp_result, 0, "id");
$tmp_result = $this->dbh->query("SELECT id FROM ttrss_feeds
WHERE title = '".$this->dbh->escape_string($rule["feed"])."' AND owner_uid = ".$_SESSION["uid"]);
if ($this->dbh->num_rows($tmp_result) > 0) {
$feed_id = $this->dbh->fetch_result($tmp_result, 0, "id");
}
} else {
$tmp_result = db_query($this->link, "SELECT id FROM ttrss_feed_categories
WHERE title = '".db_escape_string($this->link, $rule["feed"])."' AND owner_uid = ".$_SESSION["uid"]);
$tmp_result = $this->dbh->query("SELECT id FROM ttrss_feed_categories
WHERE title = '".$this->dbh->escape_string($rule["feed"])."' AND owner_uid = ".$_SESSION["uid"]);
if (db_num_rows($tmp_result) > 0) {
$cat_id = db_fetch_result($tmp_result, 0, "id");
if ($this->dbh->num_rows($tmp_result) > 0) {
$cat_id = $this->dbh->fetch_result($tmp_result, 0, "id");
}
}
$cat_filter = bool_to_sql_bool($rule["cat_filter"]);
$reg_exp = db_escape_string($this->link, $rule["reg_exp"]);
$reg_exp = $this->dbh->escape_string($rule["reg_exp"]);
$filter_type = (int)$rule["filter_type"];
db_query($this->link, "INSERT INTO ttrss_filters2_rules (feed_id,cat_id,filter_id,filter_type,reg_exp,cat_filter)
$this->dbh->query("INSERT INTO ttrss_filters2_rules (feed_id,cat_id,filter_id,filter_type,reg_exp,cat_filter)
VALUES ($feed_id, $cat_id, $filter_id, $filter_type, '$reg_exp', $cat_filter)");
}
foreach ($filter["actions"] as $action) {
$action_id = (int)$action["action_id"];
$action_param = db_escape_string($this->link, $action["action_param"]);
$action_param = $this->dbh->escape_string($action["action_param"]);
db_query($this->link, "INSERT INTO ttrss_filters2_actions (filter_id,action_id,action_param)
$this->dbh->query("INSERT INTO ttrss_filters2_actions (filter_id,action_id,action_param)
VALUES ($filter_id, $action_id, '$action_param')");
}
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
}
}
@@ -383,22 +383,22 @@ class Opml extends Handler_Protected {
private function opml_import_category($doc, $root_node, $owner_uid, $parent_id) {
$body = $doc->getElementsByTagName('body');
$default_cat_id = (int) get_feed_category($this->link, 'Imported feeds', false);
$default_cat_id = (int) get_feed_category('Imported feeds', false);
if ($root_node) {
$cat_title = db_escape_string($this->link, mb_substr($root_node->attributes->getNamedItem('text')->nodeValue, 0, 250));
$cat_title = $this->dbh->escape_string(mb_substr($root_node->attributes->getNamedItem('text')->nodeValue, 0, 250));
if (!$cat_title)
$cat_title = db_escape_string($this->link, mb_substr($root_node->attributes->getNamedItem('title')->nodeValue, 0, 250));
$cat_title = $this->dbh->escape_string(mb_substr($root_node->attributes->getNamedItem('title')->nodeValue, 0, 250));
if (!in_array($cat_title, array("tt-rss-filters", "tt-rss-labels", "tt-rss-prefs"))) {
$cat_id = get_feed_category($this->link, $cat_title, $parent_id);
db_query($this->link, "BEGIN");
$cat_id = get_feed_category($cat_title, $parent_id);
$this->dbh->query("BEGIN");
if ($cat_id === false) {
add_feed_category($this->link, $cat_title, $parent_id);
$cat_id = get_feed_category($this->link, $cat_title, $parent_id);
add_feed_category($cat_title, $parent_id);
$cat_id = get_feed_category($cat_title, $parent_id);
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
} else {
$cat_id = 0;
}
@@ -418,12 +418,12 @@ class Opml extends Handler_Protected {
foreach ($outlines as $node) {
if ($node->hasAttributes() && strtolower($node->tagName) == "outline") {
$attrs = $node->attributes;
$node_cat_title = db_escape_string($this->link, $attrs->getNamedItem('text')->nodeValue);
$node_cat_title = $this->dbh->escape_string($attrs->getNamedItem('text')->nodeValue);
if (!$node_cat_title)
$node_cat_title = db_escape_string($this->link, $attrs->getNamedItem('title')->nodeValue);
$node_cat_title = $this->dbh->escape_string($attrs->getNamedItem('title')->nodeValue);
$node_feed_url = db_escape_string($this->link, $attrs->getNamedItem('xmlUrl')->nodeValue);
$node_feed_url = $this->dbh->escape_string($attrs->getNamedItem('xmlUrl')->nodeValue);
if ($node_cat_title && !$node_feed_url) {
$this->opml_import_category($doc, $node, $owner_uid, $cat_id);
@@ -461,14 +461,38 @@ class Opml extends Handler_Protected {
# if ($debug) $doc = DOMDocument::load("/tmp/test.opml");
if (is_file($_FILES['opml_file']['tmp_name'])) {
$doc = new DOMDocument();
$doc->load($_FILES['opml_file']['tmp_name']);
} else if (!$doc) {
if ($_FILES['opml_file']['error'] != 0) {
print_error(T_sprintf("Upload failed with error code %d",
$_FILES['opml_file']['error']));
return;
}
$tmp_file = false;
if (is_uploaded_file($_FILES['opml_file']['tmp_name'])) {
$tmp_file = tempnam(CACHE_DIR . '/upload', 'opml');
$result = move_uploaded_file($_FILES['opml_file']['tmp_name'],
$tmp_file);
if (!$result) {
print_error(__("Unable to move uploaded file."));
return;
}
} else {
print_error(__('Error: please upload OPML file.'));
return;
}
if (is_file($tmp_file)) {
$doc = new DOMDocument();
$doc->load($tmp_file);
unlink($tmp_file);
} else if (!$doc) {
print_error(__('Error: unable to find moved OPML file.'));
return;
}
if ($doc) {
$this->opml_import_category($doc, false, $owner_uid, false);
} else {
@@ -480,11 +504,11 @@ class Opml extends Handler_Protected {
print "$msg<br/>";
}
static function opml_publish_url($link){
static function opml_publish_url(){
$url_path = get_self_url_prefix();
$url_path .= "/opml.php?op=publish&key=" .
get_feed_access_key($link, 'OPML:Publish', false, $_SESSION["uid"]);
get_feed_access_key('OPML:Publish', false, $_SESSION["uid"]);
return $url_path;
}

View File

@@ -1,10 +1,12 @@
<?php
class Plugin {
private $link;
private $dbh;
private $host;
const API_VERSION_COMPAT = 1;
function init($host) {
$this->link = $host->get_link();
$this->dbh = $host->get_dbh();
$this->host = $host;
}
@@ -20,5 +22,9 @@ class Plugin {
function get_prefs_js() {
return "";
}
function api_version() {
return Plugin::API_VERSION_COMPAT;
}
}
?>

View File

@@ -5,9 +5,7 @@ class PluginHandler extends Handler_Protected {
}
function catchall($method) {
global $pluginhost;
$plugin = $pluginhost->get_plugin($_REQUEST["plugin"]);
$plugin = PluginHost::getInstance()->get_plugin($_REQUEST["plugin"]);
if ($plugin) {
if (method_exists($plugin, $method)) {

View File

@@ -1,14 +1,19 @@
<?php
class PluginHost {
private $link;
private $dbh;
private $hooks = array();
private $plugins = array();
private $handlers = array();
private $commands = array();
private $storage = array();
private $feeds = array();
private $api_methods = array();
private $owner_uid;
private $debug;
private $last_registered;
private static $instance;
const API_VERSION = 2;
const HOOK_ARTICLE_BUTTON = 1;
const HOOK_ARTICLE_FILTER = 2;
@@ -29,17 +34,28 @@ class PluginHost {
const HOOK_HEADLINE_TOOLBAR_BUTTON = 17;
const HOOK_HOTKEY_INFO = 18;
const HOOK_ARTICLE_LEFT_BUTTON = 19;
const HOOK_PREFS_EDIT_FEED = 20;
const HOOK_PREFS_SAVE_FEED = 21;
const KIND_ALL = 1;
const KIND_SYSTEM = 2;
const KIND_USER = 3;
function __construct($link) {
$this->link = $link;
function __construct() {
$this->dbh = Db::get();
$this->storage = $_SESSION["plugin_storage"];
$this->storage = array();
}
if (!$this->storage) $this->storage = array();
private function __clone() {
//
}
public static function getInstance() {
if (self::$instance == null)
self::$instance = new self();
return self::$instance;
}
private function register_plugin($name, $plugin) {
@@ -47,8 +63,13 @@ class PluginHost {
$this->plugins[$name] = $plugin;
}
// needed for compatibility with API 1
function get_link() {
return $this->link;
return false;
}
function get_dbh() {
return $this->dbh;
}
function get_plugins() {
@@ -102,6 +123,9 @@ class PluginHost {
foreach ($plugins as $class) {
$class = trim($class);
$class_file = strtolower(basename($class));
if (!is_dir(dirname(__FILE__)."/../plugins/$class_file")) continue;
$file = dirname(__FILE__)."/../plugins/$class_file/init.php";
if (!isset($this->plugins[$class])) {
@@ -110,6 +134,15 @@ class PluginHost {
if (class_exists($class) && is_subclass_of($class, "Plugin")) {
$plugin = new $class($this);
$plugin_api = $plugin->api_version();
if ($plugin_api < PluginHost::API_VERSION) {
user_error("Plugin $class is not compatible with current API version (need: " . PluginHost::API_VERSION . ", got: $plugin_api)", E_USER_WARNING);
continue;
}
$this->last_registered = $class;
switch ($kind) {
case $this::KIND_SYSTEM:
if ($this->is_system($plugin)) {
@@ -153,7 +186,7 @@ class PluginHost {
}
}
function del_handler($handler, $method) {
function del_handler($handler, $method, $sender) {
$handler = str_replace("-", "_", strtolower($handler));
$method = strtolower($method);
@@ -218,45 +251,41 @@ class PluginHost {
}
function load_data($force = false) {
if ($this->owner_uid && (!$_SESSION["plugin_storage"] || $force)) {
$plugin = db_escape_string($this->link, $plugin);
$result = db_query($this->link, "SELECT name, content FROM ttrss_plugin_storage
if ($this->owner_uid) {
$result = $this->dbh->query("SELECT name, content FROM ttrss_plugin_storage
WHERE owner_uid = '".$this->owner_uid."'");
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$this->storage[$line["name"]] = unserialize($line["content"]);
}
$_SESSION["plugin_storage"] = $this->storage;
}
}
private function save_data($plugin) {
if ($this->owner_uid) {
$plugin = db_escape_string($this->link, $plugin);
$plugin = $this->dbh->escape_string($plugin);
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
$result = db_query($this->link,"SELECT id FROM ttrss_plugin_storage WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_plugin_storage WHERE
owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
if (!isset($this->storage[$plugin]))
$this->storage[$plugin] = array();
$content = db_escape_string($this->link, serialize($this->storage[$plugin]));
$content = $this->dbh->escape_string(serialize($this->storage[$plugin]));
if (db_num_rows($result) != 0) {
db_query($this->link, "UPDATE ttrss_plugin_storage SET content = '$content'
if ($this->dbh->num_rows($result) != 0) {
$this->dbh->query("UPDATE ttrss_plugin_storage SET content = '$content'
WHERE owner_uid= '".$this->owner_uid."' AND name = '$plugin'");
} else {
db_query($this->link, "INSERT INTO ttrss_plugin_storage
$this->dbh->query("INSERT INTO ttrss_plugin_storage
(name,owner_uid,content) VALUES
('$plugin','".$this->owner_uid."','$content')");
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
}
@@ -268,8 +297,6 @@ class PluginHost {
$this->storage[$idx][$name] = $value;
$_SESSION["plugin_storage"] = $this->storage;
if ($sync) $this->save_data(get_class($sender));
}
@@ -295,10 +322,8 @@ class PluginHost {
unset($this->storage[$idx]);
db_query($this->link, "DELETE FROM ttrss_plugin_storage WHERE name = '$idx'
$this->dbh->query("DELETE FROM ttrss_plugin_storage WHERE name = '$idx'
AND owner_uid = " . $this->owner_uid);
$_SESSION["plugin_storage"] = $this->storage;
}
}
@@ -347,5 +372,14 @@ class PluginHost {
return PLUGIN_FEED_BASE_INDEX - 1 + abs($feed);
}
function add_api_method($name, $sender) {
if ($this->is_system($sender)) {
$this->api_methods[strtolower($name)] = $sender;
}
}
function get_api_method($name) {
return $this->api_methods[$name];
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ class Pref_Filters extends Handler_Protected {
}
function filtersortreset() {
db_query($this->link, "UPDATE ttrss_filters2
$this->dbh->query("UPDATE ttrss_filters2
SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
return;
}
@@ -31,7 +31,7 @@ class Pref_Filters extends Handler_Protected {
if ($filter_id > 0) {
db_query($this->link, "UPDATE ttrss_filters2 SET
$this->dbh->query("UPDATE ttrss_filters2 SET
order_id = $index WHERE id = '$filter_id' AND
owner_uid = " .$_SESSION["uid"]);
@@ -49,16 +49,16 @@ class Pref_Filters extends Handler_Protected {
$filter["enabled"] = true;
$filter["match_any_rule"] = sql_bool_to_bool(
checkbox_to_sql_bool(db_escape_string($this->link, $_REQUEST["match_any_rule"])));
checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["match_any_rule"])));
$filter["inverse"] = sql_bool_to_bool(
checkbox_to_sql_bool(db_escape_string($this->link, $_REQUEST["inverse"])));
checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["inverse"])));
$filter["rules"] = array();
$result = db_query($this->link, "SELECT id,name FROM ttrss_filter_types");
$result = $this->dbh->query("SELECT id,name FROM ttrss_filter_types");
$filter_types = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$filter_types[$line["id"]] = $line["name"];
}
@@ -83,9 +83,7 @@ class Pref_Filters extends Handler_Protected {
}
}
$feed_title = getFeedTitle($this->link, $feed);
$qfh_ret = queryFeedHeadlines($this->link, -4, 30, "", false, false, false,
$qfh_ret = queryFeedHeadlines(-4, 30, "", false, false, false,
"date_entered DESC", 0, $_SESSION["uid"], $filter);
$result = $qfh_ret[0];
@@ -98,10 +96,10 @@ class Pref_Filters extends Handler_Protected {
print "<div class=\"filterTestHolder\">";
print "<table width=\"100%\" cellspacing=\"0\" id=\"prefErrorFeedList\">";
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$entry_timestamp = strtotime($line["updated"]);
$entry_tags = get_article_tags($this->link, $line["id"], $_SESSION["uid"]);
$entry_tags = get_article_tags($line["id"], $_SESSION["uid"]);
$content_preview = truncate_string(
strip_tags($line["content_preview"]), 100, '...');
@@ -158,7 +156,7 @@ class Pref_Filters extends Handler_Protected {
$filter_search = $_SESSION["prefs_filter_search"];
$result = db_query($this->link, "SELECT *,
$result = $this->dbh->query("SELECT *,
(SELECT action_param FROM ttrss_filters2_actions
WHERE filter_id = ttrss_filters2.id ORDER BY id LIMIT 1) AS action_param,
(SELECT action_id FROM ttrss_filters2_actions
@@ -176,7 +174,7 @@ class Pref_Filters extends Handler_Protected {
$folder = array();
$folder['items'] = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
/* if ($action_id != $line["action_id"]) {
if (count($folder['items']) > 0) {
@@ -194,10 +192,10 @@ class Pref_Filters extends Handler_Protected {
$match_ok = false;
if ($filter_search) {
$rules_result = db_query($this->link,
$rules_result = $this->dbh->query(
"SELECT reg_exp FROM ttrss_filters2_rules WHERE filter_id = ".$line["id"]);
while ($rule_line = db_fetch_assoc($rules_result)) {
while ($rule_line = $this->dbh->fetch_assoc($rules_result)) {
if (mb_strpos($rule_line['reg_exp'], $filter_search) !== false) {
$match_ok = true;
break;
@@ -206,13 +204,13 @@ class Pref_Filters extends Handler_Protected {
}
if ($line['action_id'] == 7) {
$label_result = db_query($this->link, "SELECT fg_color, bg_color
FROM ttrss_labels2 WHERE caption = '".db_escape_string($this->link, $line['action_param'])."' AND
$label_result = $this->dbh->query("SELECT fg_color, bg_color
FROM ttrss_labels2 WHERE caption = '".$this->dbh->escape_string($line['action_param'])."' AND
owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($label_result) > 0) {
$fg_color = db_fetch_result($label_result, 0, "fg_color");
$bg_color = db_fetch_result($label_result, 0, "bg_color");
if ($this->dbh->num_rows($label_result) > 0) {
$fg_color = $this->dbh->fetch_result($label_result, 0, "fg_color");
$bg_color = $this->dbh->fetch_result($label_result, 0, "bg_color");
$name[1] = "<span class=\"labelColorIndicator\" id=\"label-editor-indicator\" style='color : $fg_color; background-color : $bg_color; margin-right : 4px'>&alpha;</span>" . $name[1];
}
@@ -248,15 +246,15 @@ class Pref_Filters extends Handler_Protected {
function edit() {
$filter_id = db_escape_string($this->link, $_REQUEST["id"]);
$filter_id = $this->dbh->escape_string($_REQUEST["id"]);
$result = db_query($this->link,
$result = $this->dbh->query(
"SELECT * FROM ttrss_filters2 WHERE id = '$filter_id' AND owner_uid = " . $_SESSION["uid"]);
$enabled = sql_bool_to_bool(db_fetch_result($result, 0, "enabled"));
$match_any_rule = sql_bool_to_bool(db_fetch_result($result, 0, "match_any_rule"));
$inverse = sql_bool_to_bool(db_fetch_result($result, 0, "inverse"));
$title = htmlspecialchars(db_fetch_result($result, 0, "title"));
$enabled = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "enabled"));
$match_any_rule = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "match_any_rule"));
$inverse = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "inverse"));
$title = htmlspecialchars($this->dbh->fetch_result($result, 0, "title"));
print "<form id=\"filter_edit_form\" onsubmit='return false'>";
@@ -294,10 +292,10 @@ class Pref_Filters extends Handler_Protected {
print "<ul id='filterDlg_Matches'>";
$rules_result = db_query($this->link, "SELECT * FROM ttrss_filters2_rules
$rules_result = $this->dbh->query("SELECT * FROM ttrss_filters2_rules
WHERE filter_id = '$filter_id' ORDER BY reg_exp, id");
while ($line = db_fetch_assoc($rules_result)) {
while ($line = $this->dbh->fetch_assoc($rules_result)) {
if (sql_bool_to_bool($line["cat_filter"])) {
$line["feed_id"] = "CAT:" . (int)$line["cat_id"];
}
@@ -342,10 +340,10 @@ class Pref_Filters extends Handler_Protected {
print "<ul id='filterDlg_Actions'>";
$actions_result = db_query($this->link, "SELECT * FROM ttrss_filters2_actions
$actions_result = $this->dbh->query("SELECT * FROM ttrss_filters2_actions
WHERE filter_id = '$filter_id' ORDER BY id");
while ($line = db_fetch_assoc($actions_result)) {
while ($line = $this->dbh->fetch_assoc($actions_result)) {
$line["action_param_label"] = $line["action_param"];
unset($line["filter_id"]);
@@ -417,19 +415,19 @@ class Pref_Filters extends Handler_Protected {
if (strpos($feed_id, "CAT:") === 0) {
$feed_id = (int) substr($feed_id, 4);
$feed = getCategoryTitle($this->link, $feed_id);
$feed = getCategoryTitle($feed_id);
} else {
$feed_id = (int) $feed_id;
if ($rule["feed_id"])
$feed = getFeedTitle($this->link, (int)$rule["feed_id"]);
$feed = getFeedTitle((int)$rule["feed_id"]);
else
$feed = __("All feeds");
}
$result = db_query($this->link, "SELECT description FROM ttrss_filter_types
$result = $this->dbh->query("SELECT description FROM ttrss_filter_types
WHERE id = ".(int)$rule["filter_type"]);
$filter_type = db_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"]),
$filter_type, $feed, isset($rule["inverse"]) ? __("(inverse)") : "");
@@ -440,10 +438,10 @@ class Pref_Filters extends Handler_Protected {
}
private function getActionName($action) {
$result = db_query($this->link, "SELECT description FROM
$result = $this->dbh->query("SELECT description FROM
ttrss_filter_actions WHERE id = " .(int)$action["action_id"]);
$title = __(db_fetch_result($result, 0, "description"));
$title = __($this->dbh->fetch_result($result, 0, "description"));
if ($action["action_id"] == 4 || $action["action_id"] == 6 ||
$action["action_id"] == 7)
@@ -463,13 +461,13 @@ class Pref_Filters extends Handler_Protected {
# print_r($_REQUEST);
$filter_id = db_escape_string($this->link, $_REQUEST["id"]);
$enabled = checkbox_to_sql_bool(db_escape_string($this->link, $_REQUEST["enabled"]));
$match_any_rule = checkbox_to_sql_bool(db_escape_string($this->link, $_REQUEST["match_any_rule"]));
$inverse = checkbox_to_sql_bool(db_escape_string($this->link, $_REQUEST["inverse"]));
$title = db_escape_string($this->link, $_REQUEST["title"]);
$filter_id = $this->dbh->escape_string($_REQUEST["id"]);
$enabled = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["enabled"]));
$match_any_rule = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["match_any_rule"]));
$inverse = checkbox_to_sql_bool($this->dbh->escape_string($_REQUEST["inverse"]));
$title = $this->dbh->escape_string($_REQUEST["title"]);
$result = db_query($this->link, "UPDATE ttrss_filters2 SET enabled = $enabled,
$result = $this->dbh->query("UPDATE ttrss_filters2 SET enabled = $enabled,
match_any_rule = $match_any_rule,
inverse = $inverse,
title = '$title'
@@ -482,17 +480,17 @@ class Pref_Filters extends Handler_Protected {
function remove() {
$ids = split(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
foreach ($ids as $id) {
db_query($this->link, "DELETE FROM ttrss_filters2 WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
$this->dbh->query("DELETE FROM ttrss_filters2 WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
}
}
private function saveRulesAndActions($filter_id) {
db_query($this->link, "DELETE FROM ttrss_filters2_rules WHERE filter_id = '$filter_id'");
db_query($this->link, "DELETE FROM ttrss_filters2_actions WHERE filter_id = '$filter_id'");
$this->dbh->query("DELETE FROM ttrss_filters2_rules WHERE filter_id = '$filter_id'");
$this->dbh->query("DELETE FROM ttrss_filters2_actions WHERE filter_id = '$filter_id'");
if ($filter_id) {
/* create rules */
@@ -521,11 +519,11 @@ class Pref_Filters extends Handler_Protected {
foreach ($rules as $rule) {
if ($rule) {
$reg_exp = strip_tags(db_escape_string($this->link, trim($rule["reg_exp"])));
$reg_exp = strip_tags($this->dbh->escape_string(trim($rule["reg_exp"])));
$inverse = isset($rule["inverse"]) ? "true" : "false";
$filter_type = (int) db_escape_string($this->link, trim($rule["filter_type"]));
$feed_id = db_escape_string($this->link, trim($rule["feed_id"]));
$filter_type = (int) $this->dbh->escape_string(trim($rule["filter_type"]));
$feed_id = $this->dbh->escape_string(trim($rule["feed_id"]));
if (strpos($feed_id, "CAT:") === 0) {
@@ -546,16 +544,16 @@ class Pref_Filters extends Handler_Protected {
(filter_id, reg_exp,filter_type,feed_id,cat_id,cat_filter,inverse) VALUES
('$filter_id', '$reg_exp', '$filter_type', $feed_id, $cat_id, $cat_filter, $inverse)";
db_query($this->link, $query);
$this->dbh->query($query);
}
}
foreach ($actions as $action) {
if ($action) {
$action_id = (int) db_escape_string($this->link, $action["action_id"]);
$action_param = db_escape_string($this->link, $action["action_param"]);
$action_param_label = db_escape_string($this->link, $action["action_param_label"]);
$action_id = (int) $this->dbh->escape_string($action["action_id"]);
$action_param = $this->dbh->escape_string($action["action_param"]);
$action_param_label = $this->dbh->escape_string($action["action_param_label"]);
if ($action_id == 7) {
$action_param = $action_param_label;
@@ -569,7 +567,7 @@ class Pref_Filters extends Handler_Protected {
(filter_id, action_id, action_param) VALUES
('$filter_id', '$action_id', '$action_param')";
db_query($this->link, $query);
$this->dbh->query($query);
}
}
}
@@ -586,35 +584,35 @@ class Pref_Filters extends Handler_Protected {
$enabled = checkbox_to_sql_bool($_REQUEST["enabled"]);
$match_any_rule = checkbox_to_sql_bool($_REQUEST["match_any_rule"]);
$title = db_escape_string($this->link, $_REQUEST["title"]);
$title = $this->dbh->escape_string($_REQUEST["title"]);
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
/* create base filter */
$result = db_query($this->link, "INSERT INTO ttrss_filters2
$result = $this->dbh->query("INSERT INTO ttrss_filters2
(owner_uid, match_any_rule, enabled, title) VALUES
(".$_SESSION["uid"].",$match_any_rule,$enabled, '$title')");
$result = db_query($this->link, "SELECT MAX(id) AS id FROM ttrss_filters2
$result = $this->dbh->query("SELECT MAX(id) AS id FROM ttrss_filters2
WHERE owner_uid = ".$_SESSION["uid"]);
$filter_id = db_fetch_result($result, 0, "id");
$filter_id = $this->dbh->fetch_result($result, 0, "id");
$this->saveRulesAndActions($filter_id);
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
function index() {
$sort = db_escape_string($this->link, $_REQUEST["sort"]);
$sort = $this->dbh->escape_string($_REQUEST["sort"]);
if (!$sort || $sort == "undefined") {
$sort = "reg_exp";
}
$filter_search = db_escape_string($this->link, $_REQUEST["search"]);
$filter_search = $this->dbh->escape_string($_REQUEST["search"]);
if (array_key_exists("search", $_REQUEST)) {
$_SESSION["prefs_filter_search"] = $filter_search;
@@ -626,7 +624,7 @@ class Pref_Filters extends Handler_Protected {
print "<div id=\"pref-filter-header\" dojoType=\"dijit.layout.ContentPane\" region=\"top\">";
print "<div id=\"pref-filter-toolbar\" dojoType=\"dijit.Toolbar\">";
$filter_search = db_escape_string($this->link, $_REQUEST["search"]);
$filter_search = $this->dbh->escape_string($_REQUEST["search"]);
if (array_key_exists("search", $_REQUEST)) {
$_SESSION["prefs_filter_search"] = $filter_search;
@@ -706,8 +704,7 @@ class Pref_Filters extends Handler_Protected {
print "</div>"; #pane
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB,
"hook_prefs_tab", "prefFilters");
print "</div>"; #container
@@ -832,12 +829,12 @@ class Pref_Filters extends Handler_Protected {
print "<form name='filter_new_rule_form' id='filter_new_rule_form'>";
$result = db_query($this->link, "SELECT id,description
$result = $this->dbh->query("SELECT id,description
FROM ttrss_filter_types WHERE id != 5 ORDER BY description");
$filter_types = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$filter_types[$line["id"]] = __($line["description"]);
}
@@ -864,7 +861,7 @@ class Pref_Filters extends Handler_Protected {
print __("in") . " ";
print "<span id='filterDlg_feeds'>";
print_feed_select($this->link, "feed_id",
print_feed_select("feed_id",
$cat_filter ? "CAT:$feed_id" : $feed_id,
'dojoType="dijit.form.FilteringSelect"');
print "</span>";
@@ -888,7 +885,7 @@ class Pref_Filters extends Handler_Protected {
$action = json_decode($_REQUEST["action"], true);
if ($action) {
$action_param = db_escape_string($this->link, $action["action_param"]);
$action_param = $this->dbh->escape_string($action["action_param"]);
$action_id = (int)$action["action_id"];
} else {
$action_param = "";
@@ -904,10 +901,10 @@ class Pref_Filters extends Handler_Protected {
print "<select name=\"action_id\" dojoType=\"dijit.form.Select\"
onchange=\"filterDlgCheckAction(this)\">";
$result = db_query($this->link, "SELECT id,description FROM ttrss_filter_actions
$result = $this->dbh->query("SELECT id,description FROM ttrss_filter_actions
ORDER BY name");
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$is_selected = ($line["id"] == $action_id) ? "selected='1'" : "";
printf("<option $is_selected value='%d'>%s</option>", $line["id"], __($line["description"]));
}
@@ -928,7 +925,7 @@ class Pref_Filters extends Handler_Protected {
id=\"filterDlg_actionParam\" style=\"$param_hidden\"
name=\"action_param\" value=\"$action_param\">";
print_label_select($this->link, "action_param_label", $action_param,
print_label_select("action_param_label", $action_param,
"id=\"filterDlg_actionParamLabel\" style=\"$label_param_hidden\"
dojoType=\"dijit.form.Select\"");
@@ -953,28 +950,28 @@ class Pref_Filters extends Handler_Protected {
private function getFilterName($id) {
$result = db_query($this->link,
$result = $this->dbh->query(
"SELECT title,COUNT(DISTINCT r.id) AS num_rules,COUNT(DISTINCT a.id) AS num_actions
FROM ttrss_filters2 AS f LEFT JOIN ttrss_filters2_rules AS r
ON (r.filter_id = f.id)
LEFT JOIN ttrss_filters2_actions AS a
ON (a.filter_id = f.id) WHERE f.id = '$id' GROUP BY f.title");
$title = db_fetch_result($result, 0, "title");
$num_rules = db_fetch_result($result, 0, "num_rules");
$num_actions = db_fetch_result($result, 0, "num_actions");
$title = $this->dbh->fetch_result($result, 0, "title");
$num_rules = $this->dbh->fetch_result($result, 0, "num_rules");
$num_actions = $this->dbh->fetch_result($result, 0, "num_actions");
if (!$title) $title = __("[No caption]");
$title = sprintf(_ngettext("%s (%d rule)", "%s (%d rules)", $num_rules), $title, $num_rules);
$result = db_query($this->link,
$result = $this->dbh->query(
"SELECT * FROM ttrss_filters2_actions WHERE filter_id = '$id' ORDER BY id LIMIT 1");
$actions = "";
if (db_num_rows($result) > 0) {
$line = db_fetch_assoc($result);
if ($this->dbh->num_rows($result) > 0) {
$line = $this->dbh->fetch_assoc($result);
$actions = $this->getActionName($line);
$num_actions -= 1;
@@ -987,22 +984,22 @@ class Pref_Filters extends Handler_Protected {
}
function join() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
if (count($ids) > 1) {
$base_id = array_shift($ids);
$ids_str = join(",", $ids);
db_query($this->link, "BEGIN");
db_query($this->link, "UPDATE ttrss_filters2_rules
$this->dbh->query("BEGIN");
$this->dbh->query("UPDATE ttrss_filters2_rules
SET filter_id = '$base_id' WHERE filter_id IN ($ids_str)");
db_query($this->link, "UPDATE ttrss_filters2_actions
$this->dbh->query("UPDATE ttrss_filters2_actions
SET filter_id = '$base_id' WHERE filter_id IN ($ids_str)");
db_query($this->link, "DELETE FROM ttrss_filters2 WHERE id IN ($ids_str)");
db_query($this->link, "UPDATE ttrss_filters2 SET match_any_rule = true WHERE id = '$base_id'");
$this->dbh->query("DELETE FROM ttrss_filters2 WHERE id IN ($ids_str)");
$this->dbh->query("UPDATE ttrss_filters2 SET match_any_rule = true WHERE id = '$base_id'");
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
$this->optimizeFilter($base_id);
@@ -1010,14 +1007,14 @@ class Pref_Filters extends Handler_Protected {
}
private function optimizeFilter($id) {
db_query($this->link, "BEGIN");
$result = db_query($this->link, "SELECT * FROM ttrss_filters2_actions
$this->dbh->query("BEGIN");
$result = $this->dbh->query("SELECT * FROM ttrss_filters2_actions
WHERE filter_id = '$id'");
$tmp = array();
$dupe_ids = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$id = $line["id"];
unset($line["id"]);
@@ -1030,17 +1027,17 @@ class Pref_Filters extends Handler_Protected {
if (count($dupe_ids) > 0) {
$ids_str = join(",", $dupe_ids);
db_query($this->link, "DELETE FROM ttrss_filters2_actions
$this->dbh->query("DELETE FROM ttrss_filters2_actions
WHERE id IN ($ids_str)");
}
$result = db_query($this->link, "SELECT * FROM ttrss_filters2_rules
$result = $this->dbh->query("SELECT * FROM ttrss_filters2_rules
WHERE filter_id = '$id'");
$tmp = array();
$dupe_ids = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$id = $line["id"];
unset($line["id"]);
@@ -1053,11 +1050,11 @@ class Pref_Filters extends Handler_Protected {
if (count($dupe_ids) > 0) {
$ids_str = join(",", $dupe_ids);
db_query($this->link, "DELETE FROM ttrss_filters2_rules
$this->dbh->query("DELETE FROM ttrss_filters2_rules
WHERE id IN ($ids_str)");
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
}
?>

View File

@@ -8,12 +8,12 @@ class Pref_Labels extends Handler_Protected {
}
function edit() {
$label_id = db_escape_string($this->link, $_REQUEST['id']);
$label_id = $this->dbh->escape_string($_REQUEST['id']);
$result = db_query($this->link, "SELECT * FROM ttrss_labels2 WHERE
$result = $this->dbh->query("SELECT * FROM ttrss_labels2 WHERE
id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
$line = db_fetch_assoc($result);
$line = $this->dbh->fetch_assoc($result);
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$label_id\">";
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-labels\">";
@@ -90,12 +90,12 @@ class Pref_Labels extends Handler_Protected {
$root['name'] = __('Labels');
$root['items'] = array();
$result = db_query($this->link, "SELECT *
$result = $this->dbh->query("SELECT *
FROM ttrss_labels2
WHERE owner_uid = ".$_SESSION["uid"]."
ORDER BY caption");
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$label = array();
$label['id'] = 'LABEL:' . $line['id'];
$label['bare_id'] = $line['id'];
@@ -118,29 +118,29 @@ class Pref_Labels extends Handler_Protected {
}
function colorset() {
$kind = db_escape_string($this->link, $_REQUEST["kind"]);
$ids = split(',', db_escape_string($this->link, $_REQUEST["ids"]));
$color = db_escape_string($this->link, $_REQUEST["color"]);
$fg = db_escape_string($this->link, $_REQUEST["fg"]);
$bg = db_escape_string($this->link, $_REQUEST["bg"]);
$kind = $this->dbh->escape_string($_REQUEST["kind"]);
$ids = explode(',', $this->dbh->escape_string($_REQUEST["ids"]));
$color = $this->dbh->escape_string($_REQUEST["color"]);
$fg = $this->dbh->escape_string($_REQUEST["fg"]);
$bg = $this->dbh->escape_string($_REQUEST["bg"]);
foreach ($ids as $id) {
if ($kind == "fg" || $kind == "bg") {
db_query($this->link, "UPDATE ttrss_labels2 SET
$this->dbh->query("UPDATE ttrss_labels2 SET
${kind}_color = '$color' WHERE id = '$id'
AND owner_uid = " . $_SESSION["uid"]);
} else {
db_query($this->link, "UPDATE ttrss_labels2 SET
$this->dbh->query("UPDATE ttrss_labels2 SET
fg_color = '$fg', bg_color = '$bg' WHERE id = '$id'
AND owner_uid = " . $_SESSION["uid"]);
}
$caption = db_escape_string($this->link, label_find_caption($this->link, $id, $_SESSION["uid"]));
$caption = $this->dbh->escape_string(label_find_caption($id, $_SESSION["uid"]));
/* Remove cached data */
db_query($this->link, "UPDATE ttrss_user_entries SET label_cache = ''
$this->dbh->query("UPDATE ttrss_user_entries SET label_cache = ''
WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $_SESSION["uid"]);
}
@@ -149,18 +149,18 @@ class Pref_Labels extends Handler_Protected {
}
function colorreset() {
$ids = split(',', db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(',', $this->dbh->escape_string($_REQUEST["ids"]));
foreach ($ids as $id) {
db_query($this->link, "UPDATE ttrss_labels2 SET
$this->dbh->query("UPDATE ttrss_labels2 SET
fg_color = '', bg_color = '' WHERE id = '$id'
AND owner_uid = " . $_SESSION["uid"]);
$caption = db_escape_string($this->link, label_find_caption($this->link, $id, $_SESSION["uid"]));
$caption = $this->dbh->escape_string(label_find_caption($id, $_SESSION["uid"]));
/* Remove cached data */
db_query($this->link, "UPDATE ttrss_user_entries SET label_cache = ''
$this->dbh->query("UPDATE ttrss_user_entries SET label_cache = ''
WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $_SESSION["uid"]);
}
@@ -168,31 +168,31 @@ class Pref_Labels extends Handler_Protected {
function save() {
$id = db_escape_string($this->link, $_REQUEST["id"]);
$caption = db_escape_string($this->link, trim($_REQUEST["caption"]));
$id = $this->dbh->escape_string($_REQUEST["id"]);
$caption = $this->dbh->escape_string(trim($_REQUEST["caption"]));
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
$result = db_query($this->link, "SELECT caption FROM ttrss_labels2
$result = $this->dbh->query("SELECT caption FROM ttrss_labels2
WHERE id = '$id' AND owner_uid = ". $_SESSION["uid"]);
if (db_num_rows($result) != 0) {
$old_caption = db_fetch_result($result, 0, "caption");
if ($this->dbh->num_rows($result) != 0) {
$old_caption = $this->dbh->fetch_result($result, 0, "caption");
$result = db_query($this->link, "SELECT id FROM ttrss_labels2
$result = $this->dbh->query("SELECT id FROM ttrss_labels2
WHERE caption = '$caption' AND owner_uid = ". $_SESSION["uid"]);
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
if ($caption) {
$result = db_query($this->link, "UPDATE ttrss_labels2 SET
$result = $this->dbh->query("UPDATE ttrss_labels2 SET
caption = '$caption' WHERE id = '$id' AND
owner_uid = " . $_SESSION["uid"]);
/* Update filters that reference label being renamed */
$old_caption = db_escape_string($this->link, $old_caption);
$old_caption = $this->dbh->escape_string($old_caption);
db_query($this->link, "UPDATE ttrss_filters2_actions SET
$this->dbh->query("UPDATE ttrss_filters2_actions SET
action_param = '$caption' WHERE action_param = '$old_caption'
AND action_id = 7
AND filter_id IN (SELECT id FROM ttrss_filters2 WHERE owner_uid = ".$_SESSION["uid"].")");
@@ -206,28 +206,28 @@ class Pref_Labels extends Handler_Protected {
}
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
return;
}
function remove() {
$ids = split(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
foreach ($ids as $id) {
label_remove($this->link, $id, $_SESSION["uid"]);
label_remove($id, $_SESSION["uid"]);
}
}
function add() {
$caption = db_escape_string($this->link, $_REQUEST["caption"]);
$output = db_escape_string($this->link, $_REQUEST["output"]);
$caption = $this->dbh->escape_string($_REQUEST["caption"]);
$output = $this->dbh->escape_string($_REQUEST["output"]);
if ($caption) {
if (label_create($this->link, $caption)) {
if (label_create($caption)) {
if (!$output) {
print T_sprintf("Created label <b>%s</b>", htmlspecialchars($caption));
}
@@ -238,7 +238,7 @@ class Pref_Labels extends Handler_Protected {
print "<rpc-reply><payload>";
print_label_select($this->link, "select_label",
print_label_select("select_label",
$caption, "");
print "</payload></rpc-reply>";
@@ -250,13 +250,13 @@ class Pref_Labels extends Handler_Protected {
function index() {
$sort = db_escape_string($this->link, $_REQUEST["sort"]);
$sort = $this->dbh->escape_string($_REQUEST["sort"]);
if (!$sort || $sort == "undefined") {
$sort = "caption";
}
$label_search = db_escape_string($this->link, $_REQUEST["search"]);
$label_search = $this->dbh->escape_string($_REQUEST["search"]);
if (array_key_exists("search", $_REQUEST)) {
$_SESSION["prefs_label_search"] = $label_search;
@@ -319,8 +319,7 @@ class Pref_Labels extends Handler_Protected {
print "</div>"; #pane
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB,
"hook_prefs_tab", "prefLabels");
print "</div>"; #container

View File

@@ -11,8 +11,8 @@ class Pref_Prefs extends Handler_Protected {
return array_search($method, $csrf_ignored) !== false;
}
function __construct($link, $args) {
parent::__construct($link, $args);
function __construct($args) {
parent::__construct($args);
$this->pref_sections = array(
1 => __('General'),
@@ -52,9 +52,10 @@ class Pref_Prefs extends Handler_Protected {
"STRIP_IMAGES" => array(__("Do not embed images in articles"), ""),
"STRIP_UNSAFE_TAGS" => array(__("Strip unsafe tags from articles"), __("Strip all but most common HTML tags when reading articles.")),
"USER_STYLESHEET" => array(__("Customize stylesheet"), __("Customize CSS stylesheet to your liking")),
"USER_TIMEZONE" => array(__("User timezone"), ""),
"USER_TIMEZONE" => array(__("Time zone"), ""),
"VFEED_GROUP_BY_FEED" => array(__("Group headlines in virtual feeds"), __("Special feeds, labels, and categories are grouped by originating feeds")),
"USER_CSS_THEME" => array(__("Select theme"), __("Select one of the available CSS themes"))
"USER_LANGUAGE" => array(__("Language")),
"USER_CSS_THEME" => array(__("Theme"), __("Select one of the available CSS themes"))
);
}
@@ -79,8 +80,7 @@ class Pref_Prefs extends Handler_Protected {
return;
}
global $pluginhost;
$authenticator = $pluginhost->get_plugin($_SESSION["auth_module"]);
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
if (method_exists($authenticator, "change_password")) {
print $authenticator->change_password($_SESSION["uid"], $old_pw, $new_pw);
@@ -90,9 +90,6 @@ class Pref_Prefs extends Handler_Protected {
}
function saveconfig() {
$_SESSION["prefs_cache"] = false;
$boolean_prefs = explode(",", $_POST["boolean_prefs"]);
foreach ($boolean_prefs as $pref) {
@@ -103,30 +100,25 @@ class Pref_Prefs extends Handler_Protected {
foreach (array_keys($_POST) as $pref_name) {
$pref_name = db_escape_string($this->link, $pref_name);
$value = db_escape_string($this->link, $_POST[$pref_name]);
$pref_name = $this->dbh->escape_string($pref_name);
$value = $this->dbh->escape_string($_POST[$pref_name]);
if ($pref_name == 'DIGEST_PREFERRED_TIME') {
if (get_pref($this->link, 'DIGEST_PREFERRED_TIME') != $value) {
if (get_pref('DIGEST_PREFERRED_TIME') != $value) {
db_query($this->link, "UPDATE ttrss_users SET
$this->dbh->query("UPDATE ttrss_users SET
last_digest_sent = NULL WHERE id = " . $_SESSION['uid']);
}
}
if ($pref_name == "language") {
if ($pref_name == "USER_LANGUAGE") {
if ($_SESSION["language"] != $value) {
setcookie("ttrss_lang", $value,
time() + SESSION_COOKIE_LIFETIME);
$_SESSION["language"] = $value;
$need_reload = true;
}
} else {
set_pref($this->link, $pref_name, $value);
}
set_pref($pref_name, $value);
}
if ($need_reload) {
@@ -138,13 +130,13 @@ class Pref_Prefs extends Handler_Protected {
function getHelp() {
$pref_name = db_escape_string($this->link, $_REQUEST["pn"]);
$pref_name = $this->dbh->escape_string($_REQUEST["pn"]);
$result = db_query($this->link, "SELECT help_text FROM ttrss_prefs
$result = $this->dbh->query("SELECT help_text FROM ttrss_prefs
WHERE pref_name = '$pref_name'");
if (db_num_rows($result) > 0) {
$help_text = db_fetch_result($result, 0, "help_text");
if ($this->dbh->num_rows($result) > 0) {
$help_text = $this->dbh->fetch_result($result, 0, "help_text");
print $help_text;
} else {
printf(__("Unknown option: %s"), $pref_name);
@@ -153,12 +145,12 @@ class Pref_Prefs extends Handler_Protected {
function changeemail() {
$email = db_escape_string($this->link, $_POST["email"]);
$full_name = db_escape_string($this->link, $_POST["full_name"]);
$email = $this->dbh->escape_string($_POST["email"]);
$full_name = $this->dbh->escape_string($_POST["full_name"]);
$active_uid = $_SESSION["uid"];
db_query($this->link, "UPDATE ttrss_users SET email = '$email',
$this->dbh->query("UPDATE ttrss_users SET email = '$email',
full_name = '$full_name' WHERE id = '$active_uid'");
print __("Your personal data has been saved.");
@@ -176,10 +168,10 @@ class Pref_Prefs extends Handler_Protected {
$profile_qpart = "profile IS NULL";
}
db_query($this->link, "DELETE FROM ttrss_user_prefs
$this->dbh->query("DELETE FROM ttrss_user_prefs
WHERE $profile_qpart AND owner_uid = ".$_SESSION["uid"]);
initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]);
initialize_user_prefs($_SESSION["uid"], $_SESSION["profile"]);
echo __("Your preferences are now set to default values.");
}
@@ -225,13 +217,13 @@ class Pref_Prefs extends Handler_Protected {
print "<h2>" . __("Personal data") . "</h2>";
$result = db_query($this->link, "SELECT email,full_name,otp_enabled,
$result = $this->dbh->query("SELECT email,full_name,otp_enabled,
access_level FROM ttrss_users
WHERE id = ".$_SESSION["uid"]);
$email = htmlspecialchars(db_fetch_result($result, 0, "email"));
$full_name = htmlspecialchars(db_fetch_result($result, 0, "full_name"));
$otp_enabled = sql_bool_to_bool(db_fetch_result($result, 0, "otp_enabled"));
$email = htmlspecialchars($this->dbh->fetch_result($result, 0, "email"));
$full_name = htmlspecialchars($this->dbh->fetch_result($result, 0, "full_name"));
$otp_enabled = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "otp_enabled"));
print "<tr><td width=\"40%\">".__('Full name')."</td>";
print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" name=\"full_name\" required=\"1\"
@@ -242,7 +234,7 @@ class Pref_Prefs extends Handler_Protected {
if (!SINGLE_USER_MODE && !$_SESSION["hide_hello"]) {
$access_level = db_fetch_result($result, 0, "access_level");
$access_level = $this->dbh->fetch_result($result, 0, "access_level");
print "<tr><td width=\"40%\">".__('Access level')."</td>";
print "<td>" . $access_level_names[$access_level] . "</td></tr>";
}
@@ -258,10 +250,7 @@ class Pref_Prefs extends Handler_Protected {
print "</form>";
if ($_SESSION["auth_module"]) {
global $pluginhost;
$authenticator = $pluginhost->get_plugin($_SESSION["auth_module"]);
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
} else {
$authenticator = false;
}
@@ -270,11 +259,11 @@ class Pref_Prefs extends Handler_Protected {
print "<h2>" . __("Password") . "</h2>";
$result = db_query($this->link, "SELECT id FROM ttrss_users
$result = $this->dbh->query("SELECT id FROM ttrss_users
WHERE id = ".$_SESSION["uid"]." AND pwd_hash
= 'SHA1:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'");
if (db_num_rows($result) != 0) {
if ($this->dbh->num_rows($result) != 0) {
print format_warning(__("Your password is at default value, please change it."), "default_pass_warning");
}
@@ -375,7 +364,7 @@ class Pref_Prefs extends Handler_Protected {
print "</form>";
} else {
} else if (function_exists("imagecreatefromstring")) {
print "<p>".__("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP.") . "</p>";
@@ -399,8 +388,8 @@ class Pref_Prefs extends Handler_Protected {
parameters: dojo.objectToQuery(this.getValues()),
onComplete: function(transport) {
notify('');
if (transport.responseText.indexOf('ERROR: ') == 0) {
notify_error(transport.responseText.replace('ERROR: ', ''));
if (transport.responseText.indexOf('ERROR:') == 0) {
notify_error(transport.responseText.replace('ERROR:', ''));
} else {
window.location.reload();
}
@@ -416,11 +405,13 @@ class Pref_Prefs extends Handler_Protected {
print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" type=\"password\" required=\"1\"
name=\"password\"></td></tr>";
print "<tr><td colspan=\"2\">";
print "<tr><td width=\"40%\">".__("Enter the generated one time password")."</td>";
print "<input dojoType=\"dijit.form.CheckBox\" required=\"1\"
type=\"checkbox\" id=\"enable_otp\" name=\"enable_otp\"/> ";
print "<label for=\"enable_otp\">".__("I have scanned the code and would like to enable OTP")."</label>";
print "<td class=\"prefValue\"><input dojoType=\"dijit.form.ValidationTextBox\" autocomplete=\"off\"
required=\"1\"
name=\"otp\"></td></tr>";
print "<tr><td colspan=\"2\">";
print "</td></tr><tr><td colspan=\"2\">";
@@ -432,13 +423,16 @@ class Pref_Prefs extends Handler_Protected {
print "</form>";
} else {
print_notice(__("PHP GD functions are required for OTP support."));
}
}
}
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB_SECTION,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION,
"hook_prefs_tab_section", "prefPrefsAuth");
print "</div>"; #pane
@@ -478,10 +472,10 @@ class Pref_Prefs extends Handler_Protected {
}
if ($_SESSION["profile"]) {
initialize_user_prefs($this->link, $_SESSION["uid"], $_SESSION["profile"]);
initialize_user_prefs($_SESSION["uid"], $_SESSION["profile"]);
$profile_qpart = "profile = '" . $_SESSION["profile"] . "'";
} else {
initialize_user_prefs($this->link, $_SESSION["uid"]);
initialize_user_prefs($_SESSION["uid"]);
$profile_qpart = "profile IS NULL";
}
@@ -492,7 +486,7 @@ class Pref_Prefs extends Handler_Protected {
$access_query = 'true';
$result = db_query($this->link, "SELECT DISTINCT
$result = $this->dbh->query("SELECT DISTINCT
ttrss_user_prefs.pref_name,value,type_name,
ttrss_prefs_sections.order_id,
def_value,section_id
@@ -511,7 +505,7 @@ class Pref_Prefs extends Handler_Protected {
$listed_boolean_prefs = array();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
if (in_array($line["pref_name"], $prefs_blacklist)) {
continue;
@@ -545,22 +539,6 @@ class Pref_Prefs extends Handler_Protected {
print "<tr><td colspan=\"3\"><h3>".$section_name."</h3></td></tr>";
$lnum = 0;
if ($active_section == 2) {
print "<tr>";
print "<td width=\"40%\" class=\"prefName\">";
print "<label>";
print __("Language:");
print "</label>";
print "<td>";
print_select_hash("language", $_COOKIE["ttrss_lang"], get_translations(),
"style='width : 220px; margin : 0px' dojoType='dijit.form.Select'");
print "</td>";
print "</tr>";
}
}
print "<tr>";
@@ -576,7 +554,11 @@ class Pref_Prefs extends Handler_Protected {
print "<td class=\"prefValue\">";
if ($pref_name == "USER_TIMEZONE") {
if ($pref_name == "USER_LANGUAGE") {
print_select_hash($pref_name, $value, get_translations(),
"style='width : 220px; margin : 0px' dojoType='dijit.form.Select'");
} else if ($pref_name == "USER_TIMEZONE") {
$timezones = explode("\n", file_get_contents("lib/timezones.txt"));
@@ -676,8 +658,7 @@ class Pref_Prefs extends Handler_Protected {
print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"boolean_prefs\" value=\"$listed_boolean_prefs\">";
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB_SECTION,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION,
"hook_prefs_tab_section", "prefPrefsPrefsInside");
print '</div>'; # inside pane
@@ -713,8 +694,7 @@ class Pref_Prefs extends Handler_Protected {
<label for='prefs_show_advanced'>" .
__("Show additional preferences") . "</label>"; */
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB_SECTION,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION,
"hook_prefs_tab_section", "prefPrefsPrefsOutside");
print "</form>";
@@ -765,9 +745,9 @@ class Pref_Prefs extends Handler_Protected {
<td width='10%'>".__('Author')."</td></tr>";
$system_enabled = array_map("trim", explode(",", PLUGINS));
$user_enabled = array_map("trim", explode(",", get_pref($this->link, "_ENABLED_PLUGINS")));
$user_enabled = array_map("trim", explode(",", get_pref("_ENABLED_PLUGINS")));
$tmppluginhost = new PluginHost($this->link);
$tmppluginhost = new PluginHost();
$tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"]);
$tmppluginhost->load_data(true);
@@ -878,8 +858,7 @@ class Pref_Prefs extends Handler_Protected {
print "</div>"; #pane
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB,
"hook_prefs_tab", "prefPrefs");
print "</div>"; #container
@@ -895,52 +874,67 @@ class Pref_Prefs extends Handler_Protected {
require_once "lib/otphp/lib/totp.php";
require_once "lib/phpqrcode/phpqrcode.php";
$result = db_query($this->link, "SELECT login,salt,otp_enabled
$result = $this->dbh->query("SELECT login,salt,otp_enabled
FROM ttrss_users
WHERE id = ".$_SESSION["uid"]);
$base32 = new Base32();
$login = db_fetch_result($result, 0, "login");
$otp_enabled = sql_bool_to_bool(db_fetch_result($result, 0, "otp_enabled"));
$login = $this->dbh->fetch_result($result, 0, "login");
$otp_enabled = sql_bool_to_bool($this->dbh->fetch_result($result, 0, "otp_enabled"));
if (!$otp_enabled) {
$secret = $base32->encode(sha1(db_fetch_result($result, 0, "salt")));
$secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt")));
$topt = new \OTPHP\TOTP($secret);
print QRcode::png($topt->provisioning_uri($login));
}
}
function otpenable() {
$password = db_escape_string($this->link, $_REQUEST["password"]);
$enable_otp = $_REQUEST["enable_otp"] == "on";
require_once "lib/otphp/vendor/base32.php";
require_once "lib/otphp/lib/otp.php";
require_once "lib/otphp/lib/totp.php";
global $pluginhost;
$authenticator = $pluginhost->get_plugin($_SESSION["auth_module"]);
$password = $_REQUEST["password"];
$otp = $_REQUEST["otp"];
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
if ($authenticator->check_password($_SESSION["uid"], $password)) {
if ($enable_otp) {
db_query($this->link, "UPDATE ttrss_users SET otp_enabled = true WHERE
$result = $this->dbh->query("SELECT salt
FROM ttrss_users
WHERE id = ".$_SESSION["uid"]);
$base32 = new Base32();
$secret = $base32->encode(sha1($this->dbh->fetch_result($result, 0, "salt")));
$topt = new \OTPHP\TOTP($secret);
$otp_check = $topt->now();
if ($otp == $otp_check) {
$this->dbh->query("UPDATE ttrss_users SET otp_enabled = true WHERE
id = " . $_SESSION["uid"]);
print "OK";
} else {
print "ERROR:".__("Incorrect one time password");
}
} else {
print "ERROR: ".__("Incorrect password");
print "ERROR:".__("Incorrect password");
}
}
function otpdisable() {
$password = db_escape_string($this->link, $_REQUEST["password"]);
$password = $this->dbh->escape_string($_REQUEST["password"]);
global $pluginhost;
$authenticator = $pluginhost->get_plugin($_SESSION["auth_module"]);
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
if ($authenticator->check_password($_SESSION["uid"], $password)) {
db_query($this->link, "UPDATE ttrss_users SET otp_enabled = false WHERE
$this->dbh->query("UPDATE ttrss_users SET otp_enabled = false WHERE
id = " . $_SESSION["uid"]);
print "OK";
@@ -956,18 +950,17 @@ class Pref_Prefs extends Handler_Protected {
else
$plugins = "";
set_pref($this->link, "_ENABLED_PLUGINS", $plugins);
set_pref("_ENABLED_PLUGINS", $plugins);
}
function clearplugindata() {
$name = db_escape_string($this->link, $_REQUEST["name"]);
$name = $this->dbh->escape_string($_REQUEST["name"]);
global $pluginhost;
$pluginhost->clear_data($pluginhost->get_plugin($name));
PluginHost::getInstance()->clear_data(PluginHost::getInstance()->get_plugin($name));
}
function customizeCSS() {
$value = get_pref($this->link, "USER_STYLESHEET");
$value = get_pref("USER_STYLESHEET");
$value = str_replace("<br/>", "\n", $value);
@@ -1015,7 +1008,7 @@ class Pref_Prefs extends Handler_Protected {
print "</div>";
$result = db_query($this->link, "SELECT title,id FROM ttrss_settings_profiles
$result = $this->dbh->query("SELECT title,id FROM ttrss_settings_profiles
WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
print "<div class=\"prefProfileHolder\">";
@@ -1046,9 +1039,7 @@ class Pref_Prefs extends Handler_Protected {
$lnum = 1;
while ($line = db_fetch_assoc($result)) {
$class = ($lnum % 2) ? "even" : "odd";
while ($line = $this->dbh->fetch_assoc($result)) {
$profile_id = $line["id"];
$this_row_id = "id=\"FCATR-$profile_id\"";

90
classes/pref/system.php Normal file
View File

@@ -0,0 +1,90 @@
<?php
class Pref_System extends Handler_Protected {
function before($method) {
if (parent::before($method)) {
if ($_SESSION["access_level"] < 10) {
print __("Your access level is insufficient to open this tab.");
return false;
}
return true;
}
return false;
}
function csrf_ignore($method) {
$csrf_ignored = array("index");
return array_search($method, $csrf_ignored) !== false;
}
function clearLog() {
$this->dbh->query("DELETE FROM ttrss_error_log");
}
function index() {
print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Error Log')."\">";
if (LOG_DESTINATION == "sql") {
$result = $this->dbh->query("SELECT errno, errstr, filename, lineno,
created_at, login FROM ttrss_error_log
LEFT JOIN ttrss_users ON (owner_uid = ttrss_users.id)
ORDER BY ttrss_error_log.id DESC
LIMIT 100");
print "<button dojoType=\"dijit.form.Button\"
onclick=\"updateSystemList()\">".__('Refresh')."</button> ";
print "&nbsp;<button dojoType=\"dijit.form.Button\"
onclick=\"clearSqlLog()\">".__('Clear log')."</button> ";
print "<p><table width=\"100%\" cellspacing=\"10\" class=\"prefErrorLog\">";
print "<tr class=\"title\">
<td width='5%'>".__("Error")."</td>
<td>".__("Filename")."</td>
<td>".__("Message")."</td>
<td width='5%'>".__("User")."</td>
<td width='5%'>".__("Date")."</td>
</tr>";
while ($line = $this->dbh->fetch_assoc($result)) {
print "<tr class=\"errrow\">";
foreach ($line as $k => $v) {
$line[$k] = htmlspecialchars($v);
}
print "<td class='errno'>" . Logger::$errornames[$line["errno"]] . " (" . $line["errno"] . ")</td>";
print "<td class='filename'>" . $line["filename"] . ":" . $line["lineno"] . "</td>";
print "<td class='errstr'>" . $line["errstr"] . "</td>";
print "<td class='login'>" . $line["login"] . "</td>";
print "<td class='timestamp'>" .
make_local_datetime(
$line["created_at"], false) . "</td>";
print "</tr>";
}
print "</table>";
} else {
print_notice("Please set LOG_DESTINATION to 'sql' in config.php to enable database logging.");
}
print "</div>";
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB,
"hook_prefs_tab", "prefSystem");
print "</div>"; #container
}
}
?>

View File

@@ -21,7 +21,7 @@ class Pref_Users extends Handler_Protected {
$uid = sprintf("%d", $_REQUEST["id"]);
$result = db_query($this->link, "SELECT login,
$result = $this->dbh->query("SELECT login,
".SUBSTRING_FOR_DATE."(last_login,1,16) AS last_login,
access_level,
(SELECT COUNT(int_id) FROM ttrss_user_entries
@@ -30,33 +30,33 @@ class Pref_Users extends Handler_Protected {
FROM ttrss_users
WHERE id = '$uid'");
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
print "<h1>".__('User not found')."</h1>";
return;
}
// print "<h1>User Details</h1>";
$login = db_fetch_result($result, 0, "login");
$login = $this->dbh->fetch_result($result, 0, "login");
print "<table width='100%'>";
$last_login = make_local_datetime($this->link,
db_fetch_result($result, 0, "last_login"), true);
$last_login = make_local_datetime(
$this->dbh->fetch_result($result, 0, "last_login"), true);
$created = make_local_datetime($this->link,
db_fetch_result($result, 0, "created"), true);
$created = make_local_datetime(
$this->dbh->fetch_result($result, 0, "created"), true);
$access_level = db_fetch_result($result, 0, "access_level");
$stored_articles = db_fetch_result($result, 0, "stored_articles");
$access_level = $this->dbh->fetch_result($result, 0, "access_level");
$stored_articles = $this->dbh->fetch_result($result, 0, "stored_articles");
print "<tr><td>".__('Registered')."</td><td>$created</td></tr>";
print "<tr><td>".__('Last logged in')."</td><td>$last_login</td></tr>";
$result = db_query($this->link, "SELECT COUNT(id) as num_feeds FROM ttrss_feeds
$result = $this->dbh->query("SELECT COUNT(id) as num_feeds FROM ttrss_feeds
WHERE owner_uid = '$uid'");
$num_feeds = db_fetch_result($result, 0, "num_feeds");
$num_feeds = $this->dbh->fetch_result($result, 0, "num_feeds");
print "<tr><td>".__('Subscribed feeds count')."</td><td>$num_feeds</td></tr>";
@@ -64,14 +64,12 @@ class Pref_Users extends Handler_Protected {
print "<h1>".__('Subscribed feeds')."</h1>";
$result = db_query($this->link, "SELECT id,title,site_url FROM ttrss_feeds
$result = $this->dbh->query("SELECT id,title,site_url FROM ttrss_feeds
WHERE owner_uid = '$uid' ORDER BY title");
print "<ul class=\"userFeedList\">";
$row_class = "odd";
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$icon_file = ICONS_URL."/".$line["id"].".ico";
@@ -81,13 +79,11 @@ class Pref_Users extends Handler_Protected {
$feed_icon = "<img class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">";
}
print "<li class=\"$row_class\">$feed_icon&nbsp;<a href=\"".$line["site_url"]."\">".$line["title"]."</a></li>";
$row_class = $row_class == "even" ? "odd" : "even";
print "<li>$feed_icon&nbsp;<a href=\"".$line["site_url"]."\">".$line["title"]."</a></li>";
}
if (db_num_rows($result) < $num_feeds) {
if ($this->dbh->num_rows($result) < $num_feeds) {
// FIXME - add link to show ALL subscribed feeds here somewhere
print "<li><img
class=\"tinyFeedIcon\" src=\"images/blank_icon.gif\">&nbsp;...</li>";
@@ -105,18 +101,18 @@ class Pref_Users extends Handler_Protected {
function edit() {
global $access_level_names;
$id = db_escape_string($this->link, $_REQUEST["id"]);
$id = $this->dbh->escape_string($_REQUEST["id"]);
print "<form id=\"user_edit_form\" onsubmit='return false'>";
print "<input type=\"hidden\" name=\"id\" value=\"$id\">";
print "<input type=\"hidden\" name=\"op\" value=\"pref-users\">";
print "<input type=\"hidden\" name=\"method\" value=\"editSave\">";
$result = db_query($this->link, "SELECT * FROM ttrss_users WHERE id = '$id'");
$result = $this->dbh->query("SELECT * FROM ttrss_users WHERE id = '$id'");
$login = db_fetch_result($result, 0, "login");
$access_level = db_fetch_result($result, 0, "access_level");
$email = db_fetch_result($result, 0, "email");
$login = $this->dbh->fetch_result($result, 0, "login");
$access_level = $this->dbh->fetch_result($result, 0, "access_level");
$email = $this->dbh->fetch_result($result, 0, "email");
$sel_disabled = ($id == $_SESSION["uid"]) ? "disabled" : "";
@@ -181,10 +177,10 @@ class Pref_Users extends Handler_Protected {
}
function editSave() {
$login = db_escape_string($this->link, trim($_REQUEST["login"]));
$uid = db_escape_string($this->link, $_REQUEST["id"]);
$login = $this->dbh->escape_string(trim($_REQUEST["login"]));
$uid = $this->dbh->escape_string($_REQUEST["id"]);
$access_level = (int) $_REQUEST["access_level"];
$email = db_escape_string($this->link, trim($_REQUEST["email"]));
$email = $this->dbh->escape_string(trim($_REQUEST["email"]));
$password = $_REQUEST["password"];
if ($password) {
@@ -195,52 +191,52 @@ class Pref_Users extends Handler_Protected {
$pass_query_part = "";
}
db_query($this->link, "UPDATE ttrss_users SET $pass_query_part login = '$login',
$this->dbh->query("UPDATE ttrss_users SET $pass_query_part login = '$login',
access_level = '$access_level', email = '$email', otp_enabled = false
WHERE id = '$uid'");
}
function remove() {
$ids = split(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
foreach ($ids as $id) {
if ($id != $_SESSION["uid"] && $id != 1) {
db_query($this->link, "DELETE FROM ttrss_tags WHERE owner_uid = '$id'");
db_query($this->link, "DELETE FROM ttrss_feeds WHERE owner_uid = '$id'");
db_query($this->link, "DELETE FROM ttrss_users WHERE id = '$id'");
$this->dbh->query("DELETE FROM ttrss_tags WHERE owner_uid = '$id'");
$this->dbh->query("DELETE FROM ttrss_feeds WHERE owner_uid = '$id'");
$this->dbh->query("DELETE FROM ttrss_users WHERE id = '$id'");
}
}
}
function add() {
$login = db_escape_string($this->link, trim($_REQUEST["login"]));
$login = $this->dbh->escape_string(trim($_REQUEST["login"]));
$tmp_user_pwd = make_password(8);
$salt = substr(bin2hex(get_random_bytes(125)), 0, 250);
$pwd_hash = encrypt_password($tmp_user_pwd, $salt, true);
$result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_users WHERE
login = '$login'");
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
db_query($this->link, "INSERT INTO ttrss_users
$this->dbh->query("INSERT INTO ttrss_users
(login,pwd_hash,access_level,last_login,created, salt)
VALUES ('$login', '$pwd_hash', 0, null, NOW(), '$salt')");
$result = db_query($this->link, "SELECT id FROM ttrss_users WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_users WHERE
login = '$login' AND pwd_hash = '$pwd_hash'");
if (db_num_rows($result) == 1) {
if ($this->dbh->num_rows($result) == 1) {
$new_uid = db_fetch_result($result, 0, "id");
$new_uid = $this->dbh->fetch_result($result, 0, "id");
print format_notice(T_sprintf("Added user <b>%s</b> with password <b>%s</b>",
$login, $tmp_user_pwd));
initialize_user($this->link, $new_uid);
initialize_user($new_uid);
} else {
@@ -252,9 +248,9 @@ class Pref_Users extends Handler_Protected {
}
}
static function resetUserPassword($link, $uid, $show_password) {
static function resetUserPassword($uid, $show_password) {
$result = db_query($link, "SELECT login,email
$result = db_query("SELECT login,email
FROM ttrss_users WHERE id = '$uid'");
$login = db_fetch_result($result, 0, "login");
@@ -266,7 +262,7 @@ class Pref_Users extends Handler_Protected {
$pwd_hash = encrypt_password($tmp_user_pwd, $new_salt, true);
db_query($link, "UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt'
db_query("UPDATE ttrss_users SET pwd_hash = '$pwd_hash', salt = '$new_salt'
WHERE id = '$uid'");
if ($show_password) {
@@ -304,8 +300,8 @@ class Pref_Users extends Handler_Protected {
}
function resetPass() {
$uid = db_escape_string($this->link, $_REQUEST["id"]);
Pref_Users::resetUserPassword($this->link, $uid, true);
$uid = $this->dbh->escape_string($_REQUEST["id"]);
Pref_Users::resetUserPassword($uid, true);
}
function index() {
@@ -317,7 +313,7 @@ class Pref_Users extends Handler_Protected {
print "<div id=\"pref-user-toolbar\" dojoType=\"dijit.Toolbar\">";
$user_search = db_escape_string($this->link, $_REQUEST["search"]);
$user_search = $this->dbh->escape_string($_REQUEST["search"]);
if (array_key_exists("search", $_REQUEST)) {
$_SESSION["prefs_user_search"] = $user_search;
@@ -332,7 +328,7 @@ class Pref_Users extends Handler_Protected {
__('Search')."</button>
</div>";
$sort = db_escape_string($this->link, $_REQUEST["sort"]);
$sort = $this->dbh->escape_string($_REQUEST["sort"]);
if (!$sort || $sort == "undefined") {
$sort = "login";
@@ -367,7 +363,7 @@ class Pref_Users extends Handler_Protected {
if ($user_search) {
$user_search = split(" ", $user_search);
$user_search = explode(" ", $user_search);
$tokens = array();
foreach ($user_search as $token) {
@@ -381,7 +377,7 @@ class Pref_Users extends Handler_Protected {
$user_search_query = "";
}
$result = db_query($this->link, "SELECT
$result = $this->dbh->query("SELECT
id,login,access_level,email,
".SUBSTRING_FOR_DATE."(last_login,1,16) as last_login,
".SUBSTRING_FOR_DATE."(created,1,16) as created
@@ -392,7 +388,7 @@ class Pref_Users extends Handler_Protected {
id > 0
ORDER BY $sort");
if (db_num_rows($result) > 0) {
if ($this->dbh->num_rows($result) > 0) {
print "<p><table width=\"100%\" cellspacing=\"0\"
class=\"prefUserList\" id=\"prefUserList\">";
@@ -406,9 +402,7 @@ class Pref_Users extends Handler_Protected {
$lnum = 0;
while ($line = db_fetch_assoc($result)) {
$class = ($lnum % 2) ? "even" : "odd";
while ($line = $this->dbh->fetch_assoc($result)) {
$uid = $line["id"];
@@ -416,8 +410,8 @@ class Pref_Users extends Handler_Protected {
$line["login"] = htmlspecialchars($line["login"]);
$line["created"] = make_local_datetime($this->link, $line["created"], false);
$line["last_login"] = make_local_datetime($this->link, $line["last_login"], false);
$line["created"] = make_local_datetime($line["created"], false);
$line["last_login"] = make_local_datetime($line["last_login"], false);
print "<td align='center'><input onclick='toggleSelectRow2(this);'
dojoType=\"dijit.form.CheckBox\" type=\"checkbox\"
@@ -453,8 +447,7 @@ class Pref_Users extends Handler_Protected {
print "</div>"; #pane
global $pluginhost;
$pluginhost->run_hooks($pluginhost::HOOK_PREFS_TAB,
PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB,
"hook_prefs_tab", "prefUsers");
print "</div>"; #container

View File

@@ -8,18 +8,17 @@ class RPC extends Handler_Protected {
}
function setprofile() {
$id = db_escape_string($this->link, $_REQUEST["id"]);
$id = $this->dbh->escape_string($_REQUEST["id"]);
$_SESSION["profile"] = $id;
$_SESSION["prefs_cache"] = array();
}
function remprofiles() {
$ids = explode(",", db_escape_string($this->link, trim($_REQUEST["ids"])));
$ids = explode(",", $this->dbh->escape_string(trim($_REQUEST["ids"])));
foreach ($ids as $id) {
if ($_SESSION["profile"] != $id) {
db_query($this->link, "DELETE FROM ttrss_settings_profiles WHERE id = '$id' AND
$this->dbh->query("DELETE FROM ttrss_settings_profiles WHERE id = '$id' AND
owner_uid = " . $_SESSION["uid"]);
}
}
@@ -27,38 +26,38 @@ class RPC extends Handler_Protected {
// Silent
function addprofile() {
$title = db_escape_string($this->link, trim($_REQUEST["title"]));
$title = $this->dbh->escape_string(trim($_REQUEST["title"]));
if ($title) {
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
$result = db_query($this->link, "SELECT id FROM ttrss_settings_profiles
$result = $this->dbh->query("SELECT id FROM ttrss_settings_profiles
WHERE title = '$title' AND owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
db_query($this->link, "INSERT INTO ttrss_settings_profiles (title, owner_uid)
$this->dbh->query("INSERT INTO ttrss_settings_profiles (title, owner_uid)
VALUES ('$title', ".$_SESSION["uid"] .")");
$result = db_query($this->link, "SELECT id FROM ttrss_settings_profiles WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_settings_profiles WHERE
title = '$title'");
if (db_num_rows($result) != 0) {
$profile_id = db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) != 0) {
$profile_id = $this->dbh->fetch_result($result, 0, "id");
if ($profile_id) {
initialize_user_prefs($this->link, $_SESSION["uid"], $profile_id);
initialize_user_prefs($_SESSION["uid"], $profile_id);
}
}
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
}
// Silent
function saveprofile() {
$id = db_escape_string($this->link, $_REQUEST["id"]);
$title = db_escape_string($this->link, trim($_REQUEST["value"]));
$id = $this->dbh->escape_string($_REQUEST["id"]);
$title = $this->dbh->escape_string(trim($_REQUEST["value"]));
if ($id == 0) {
print __("Default profile");
@@ -66,55 +65,55 @@ class RPC extends Handler_Protected {
}
if ($title) {
db_query($this->link, "BEGIN");
$this->dbh->query("BEGIN");
$result = db_query($this->link, "SELECT id FROM ttrss_settings_profiles
$result = $this->dbh->query("SELECT id FROM ttrss_settings_profiles
WHERE title = '$title' AND owner_uid =" . $_SESSION["uid"]);
if (db_num_rows($result) == 0) {
db_query($this->link, "UPDATE ttrss_settings_profiles
if ($this->dbh->num_rows($result) == 0) {
$this->dbh->query("UPDATE ttrss_settings_profiles
SET title = '$title' WHERE id = '$id' AND
owner_uid = " . $_SESSION["uid"]);
print $title;
} else {
$result = db_query($this->link, "SELECT title FROM ttrss_settings_profiles
$result = $this->dbh->query("SELECT title FROM ttrss_settings_profiles
WHERE id = '$id' AND owner_uid =" . $_SESSION["uid"]);
print db_fetch_result($result, 0, "title");
print $this->dbh->fetch_result($result, 0, "title");
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
}
// Silent
function remarchive() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
foreach ($ids as $id) {
$result = db_query($this->link, "DELETE FROM ttrss_archived_feeds WHERE
$result = $this->dbh->query("DELETE FROM ttrss_archived_feeds WHERE
(SELECT COUNT(*) FROM ttrss_user_entries
WHERE orig_feed_id = '$id') = 0 AND
id = '$id' AND owner_uid = ".$_SESSION["uid"]);
$rc = db_affected_rows($this->link, $result);
$rc = $this->dbh->affected_rows($result);
}
}
function addfeed() {
$feed = db_escape_string($this->link, $_REQUEST['feed']);
$cat = db_escape_string($this->link, $_REQUEST['cat']);
$login = db_escape_string($this->link, $_REQUEST['login']);
$pass = db_escape_string($this->link, $_REQUEST['pass']);
$feed = $this->dbh->escape_string($_REQUEST['feed']);
$cat = $this->dbh->escape_string($_REQUEST['cat']);
$login = $this->dbh->escape_string($_REQUEST['login']);
$pass = trim($_REQUEST['pass']); // escaped later
$rc = subscribe_to_feed($this->link, $feed, $cat, $login, $pass);
$rc = subscribe_to_feed($feed, $cat, $login, $pass);
print json_encode(array("result" => $rc));
}
function togglepref() {
$key = db_escape_string($this->link, $_REQUEST["key"]);
set_pref($this->link, $key, !get_pref($this->link, $key));
$value = get_pref($this->link, $key);
$key = $this->dbh->escape_string($_REQUEST["key"]);
set_pref($key, !get_pref($key));
$value = get_pref($key);
print json_encode(array("param" =>$key, "value" => $value));
}
@@ -124,14 +123,14 @@ class RPC extends Handler_Protected {
$key = $_REQUEST['key'];
$value = str_replace("\n", "<br/>", $_REQUEST['value']);
set_pref($this->link, $key, $value, $_SESSION['uid'], $key != 'USER_STYLESHEET');
set_pref($key, $value, $_SESSION['uid'], $key != 'USER_STYLESHEET');
print json_encode(array("param" =>$key, "value" => $value));
}
function mark() {
$mark = $_REQUEST["mark"];
$id = db_escape_string($this->link, $_REQUEST["id"]);
$id = $this->dbh->escape_string($_REQUEST["id"]);
if ($mark == "1") {
$mark = "true";
@@ -139,7 +138,7 @@ class RPC extends Handler_Protected {
$mark = "false";
}
$result = db_query($this->link, "UPDATE ttrss_user_entries SET marked = $mark,
$result = $this->dbh->query("UPDATE ttrss_user_entries SET marked = $mark,
last_marked = NOW()
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
@@ -147,12 +146,12 @@ class RPC extends Handler_Protected {
}
function delete() {
$ids = db_escape_string($this->link, $_REQUEST["ids"]);
$ids = $this->dbh->escape_string($_REQUEST["ids"]);
$result = db_query($this->link, "DELETE FROM ttrss_user_entries
$result = $this->dbh->query("DELETE FROM ttrss_user_entries
WHERE ref_id IN ($ids) AND owner_uid = " . $_SESSION["uid"]);
purge_orphans($this->link);
purge_orphans();
print json_encode(array("message" => "UPDATE_COUNTERS"));
}
@@ -161,26 +160,26 @@ class RPC extends Handler_Protected {
$ids = explode(",", $_REQUEST["ids"]);
foreach ($ids as $id) {
$id = db_escape_string($this->link, trim($id));
db_query($this->link, "BEGIN");
$id = $this->dbh->escape_string(trim($id));
$this->dbh->query("BEGIN");
$result = db_query($this->link, "SELECT feed_url,site_url,title FROM ttrss_archived_feeds
$result = $this->dbh->query("SELECT feed_url,site_url,title FROM ttrss_archived_feeds
WHERE id = (SELECT orig_feed_id FROM ttrss_user_entries WHERE ref_id = $id
AND owner_uid = ".$_SESSION["uid"].")");
if (db_num_rows($result) != 0) {
$feed_url = db_escape_string($this->link, db_fetch_result($result, 0, "feed_url"));
$site_url = db_escape_string($this->link, db_fetch_result($result, 0, "site_url"));
$title = db_escape_string($this->link, db_fetch_result($result, 0, "title"));
if ($this->dbh->num_rows($result) != 0) {
$feed_url = $this->dbh->escape_string(db_fetch_result($result, 0, "feed_url"));
$site_url = $this->dbh->escape_string(db_fetch_result($result, 0, "site_url"));
$title = $this->dbh->escape_string(db_fetch_result($result, 0, "title"));
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_url'
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_url'
AND owner_uid = " .$_SESSION["uid"]);
if (db_num_rows($result) == 0) {
if ($this->dbh->num_rows($result) == 0) {
if (!$title) $title = '[Unknown]';
$result = db_query($this->link,
$result = $this->dbh->query(
"INSERT INTO ttrss_feeds
(owner_uid,feed_url,site_url,title,cat_id,auth_login,auth_pass,update_method)
VALUES (".$_SESSION["uid"].",
@@ -189,77 +188,77 @@ class RPC extends Handler_Protected {
'$title',
NULL, '', '', 0)");
$result = db_query($this->link,
$result = $this->dbh->query(
"SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_url'
AND owner_uid = ".$_SESSION["uid"]);
if (db_num_rows($result) != 0) {
$feed_id = db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) != 0) {
$feed_id = $this->dbh->fetch_result($result, 0, "id");
}
} else {
$feed_id = db_fetch_result($result, 0, "id");
$feed_id = $this->dbh->fetch_result($result, 0, "id");
}
if ($feed_id) {
$result = db_query($this->link, "UPDATE ttrss_user_entries
$result = $this->dbh->query("UPDATE ttrss_user_entries
SET feed_id = '$feed_id', orig_feed_id = NULL
WHERE ref_id = $id AND owner_uid = " . $_SESSION["uid"]);
}
}
db_query($this->link, "COMMIT");
$this->dbh->query("COMMIT");
}
print json_encode(array("message" => "UPDATE_COUNTERS"));
}
function archive() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
foreach ($ids as $id) {
$this->archive_article($this->link, $id, $_SESSION["uid"]);
$this->archive_article($id, $_SESSION["uid"]);
}
print json_encode(array("message" => "UPDATE_COUNTERS"));
}
private function archive_article($link, $id, $owner_uid) {
db_query($link, "BEGIN");
private function archive_article($id, $owner_uid) {
$this->dbh->query("BEGIN");
$result = db_query($link, "SELECT feed_id FROM ttrss_user_entries
$result = $this->dbh->query("SELECT feed_id FROM ttrss_user_entries
WHERE ref_id = '$id' AND owner_uid = $owner_uid");
if (db_num_rows($result) != 0) {
if ($this->dbh->num_rows($result) != 0) {
/* prepare the archived table */
$feed_id = (int) db_fetch_result($result, 0, "feed_id");
$feed_id = (int) $this->dbh->fetch_result($result, 0, "feed_id");
if ($feed_id) {
$result = db_query($link, "SELECT id FROM ttrss_archived_feeds
$result = $this->dbh->query("SELECT id FROM ttrss_archived_feeds
WHERE id = '$feed_id'");
if (db_num_rows($result) == 0) {
db_query($link, "INSERT INTO ttrss_archived_feeds
if ($this->dbh->num_rows($result) == 0) {
$this->dbh->query("INSERT INTO ttrss_archived_feeds
(id, owner_uid, title, feed_url, site_url)
SELECT id, owner_uid, title, feed_url, site_url from ttrss_feeds
WHERE id = '$feed_id'");
}
db_query($link, "UPDATE ttrss_user_entries
$this->dbh->query("UPDATE ttrss_user_entries
SET orig_feed_id = feed_id, feed_id = NULL
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
}
}
db_query($link, "COMMIT");
$this->dbh->query("COMMIT");
}
function publ() {
$pub = $_REQUEST["pub"];
$id = db_escape_string($this->link, $_REQUEST["id"]);
$note = trim(strip_tags(db_escape_string($this->link, $_REQUEST["note"])));
$id = $this->dbh->escape_string($_REQUEST["id"]);
$note = trim(strip_tags($this->dbh->escape_string($_REQUEST["note"])));
if ($pub == "1") {
$pub = "true";
@@ -267,7 +266,7 @@ class RPC extends Handler_Protected {
$pub = "false";
}
$result = db_query($this->link, "UPDATE ttrss_user_entries SET
$result = $this->dbh->query("UPDATE ttrss_user_entries SET
published = $pub, last_published = NOW()
WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
@@ -276,7 +275,7 @@ class RPC extends Handler_Protected {
if (PUBSUBHUBBUB_HUB) {
$rss_link = get_self_url_prefix() .
"/public.php?op=rss&id=-2&key=" .
get_feed_access_key($this->link, -2, false);
get_feed_access_key(-2, false);
$p = new Publisher(PUBSUBHUBBUB_HUB);
@@ -292,41 +291,41 @@ class RPC extends Handler_Protected {
$reply = array();
if ($seq) $reply['seq'] = $seq;
if (!empty($_REQUEST['seq'])) $reply['seq'] = (int) $_REQUEST['seq'];
if ($last_article_id != getLastArticleId($this->link)) {
$reply['counters'] = getAllCounters($this->link);
if ($last_article_id != getLastArticleId()) {
$reply['counters'] = getAllCounters();
}
$reply['runtime-info'] = make_runtime_info($this->link);
$reply['runtime-info'] = make_runtime_info();
print json_encode($reply);
}
/* GET["cmode"] = 0 - mark as read, 1 - as unread, 2 - toggle */
function catchupSelected() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
$cmode = sprintf("%d", $_REQUEST["cmode"]);
catchupArticlesById($this->link, $ids, $cmode);
catchupArticlesById($ids, $cmode);
print json_encode(array("message" => "UPDATE_COUNTERS", "ids" => $ids));
}
function markSelected() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
$cmode = sprintf("%d", $_REQUEST["cmode"]);
$this->markArticlesById($this->link, $ids, $cmode);
$this->markArticlesById($ids, $cmode);
print json_encode(array("message" => "UPDATE_COUNTERS"));
}
function publishSelected() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
$cmode = sprintf("%d", $_REQUEST["cmode"]);
$this->publishArticlesById($this->link, $ids, $cmode);
$this->publishArticlesById($ids, $cmode);
print json_encode(array("message" => "UPDATE_COUNTERS"));
}
@@ -334,59 +333,61 @@ class RPC extends Handler_Protected {
function sanityCheck() {
$_SESSION["hasAudio"] = $_REQUEST["hasAudio"] === "true";
$_SESSION["hasSandbox"] = $_REQUEST["hasSandbox"] === "true";
$_SESSION["hasMp3"] = $_REQUEST["hasMp3"] === "true";
$_SESSION["clientTzOffset"] = $_REQUEST["clientTzOffset"];
$reply = array();
$reply['error'] = sanity_check($this->link);
$reply['error'] = sanity_check();
if ($reply['error']['code'] == 0) {
$reply['init-params'] = make_init_params($this->link);
$reply['runtime-info'] = make_runtime_info($this->link);
$reply['init-params'] = make_init_params();
$reply['runtime-info'] = make_runtime_info();
}
print json_encode($reply);
}
function completeLabels() {
$search = db_escape_string($this->link, $_REQUEST["search"]);
$search = $this->dbh->escape_string($_REQUEST["search"]);
$result = db_query($this->link, "SELECT DISTINCT caption FROM
$result = $this->dbh->query("SELECT DISTINCT caption FROM
ttrss_labels2
WHERE owner_uid = '".$_SESSION["uid"]."' AND
LOWER(caption) LIKE LOWER('$search%') ORDER BY caption
LIMIT 5");
print "<ul>";
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
print "<li>" . $line["caption"] . "</li>";
}
print "</ul>";
}
function purge() {
$ids = explode(",", db_escape_string($this->link, $_REQUEST["ids"]));
$ids = explode(",", $this->dbh->escape_string($_REQUEST["ids"]));
$days = sprintf("%d", $_REQUEST["days"]);
foreach ($ids as $id) {
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
id = '$id' AND owner_uid = ".$_SESSION["uid"]);
if (db_num_rows($result) == 1) {
purge_feed($this->link, $id, $days);
if ($this->dbh->num_rows($result) == 1) {
purge_feed($id, $days);
}
}
}
function updateFeedBrowser() {
$search = db_escape_string($this->link, $_REQUEST["search"]);
$limit = db_escape_string($this->link, $_REQUEST["limit"]);
$mode = (int) db_escape_string($this->link, $_REQUEST["mode"]);
$search = $this->dbh->escape_string($_REQUEST["search"]);
$limit = $this->dbh->escape_string($_REQUEST["limit"]);
$mode = (int) $this->dbh->escape_string($_REQUEST["mode"]);
require_once "feedbrowser.php";
print json_encode(array("content" =>
make_feed_browser($this->link, $search, $limit, $mode),
make_feed_browser($search, $limit, $mode),
"mode" => $mode));
}
@@ -401,14 +402,14 @@ class RPC extends Handler_Protected {
if ($mode == 1) {
foreach ($payload as $feed) {
$title = db_escape_string($this->link, $feed[0]);
$feed_url = db_escape_string($this->link, $feed[1]);
$title = $this->dbh->escape_string($feed[0]);
$feed_url = $this->dbh->escape_string($feed[1]);
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($result) == 0) {
$result = db_query($this->link, "INSERT INTO ttrss_feeds
if ($this->dbh->num_rows($result) == 0) {
$result = $this->dbh->query("INSERT INTO ttrss_feeds
(owner_uid,feed_url,title,cat_id,site_url)
VALUES ('".$_SESSION["uid"]."',
'$feed_url', '$title', NULL, '')");
@@ -417,19 +418,19 @@ class RPC extends Handler_Protected {
} else if ($mode == 2) {
// feed archive
foreach ($payload as $id) {
$result = db_query($this->link, "SELECT * FROM ttrss_archived_feeds
$result = $this->dbh->query("SELECT * FROM ttrss_archived_feeds
WHERE id = '$id' AND owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($result) != 0) {
$site_url = db_escape_string($this->link, db_fetch_result($result, 0, "site_url"));
$feed_url = db_escape_string($this->link, db_fetch_result($result, 0, "feed_url"));
$title = db_escape_string($this->link, db_fetch_result($result, 0, "title"));
if ($this->dbh->num_rows($result) != 0) {
$site_url = $this->dbh->escape_string(db_fetch_result($result, 0, "site_url"));
$feed_url = $this->dbh->escape_string(db_fetch_result($result, 0, "feed_url"));
$title = $this->dbh->escape_string(db_fetch_result($result, 0, "title"));
$result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($result) == 0) {
$result = db_query($this->link, "INSERT INTO ttrss_feeds
if ($this->dbh->num_rows($result) == 0) {
$result = $this->dbh->query("INSERT INTO ttrss_feeds
(owner_uid,feed_url,title,cat_id,site_url)
VALUES ('$id','".$_SESSION["uid"]."',
'$feed_url', '$title', NULL, '$site_url')");
@@ -440,35 +441,35 @@ class RPC extends Handler_Protected {
}
function catchupFeed() {
$feed_id = db_escape_string($this->link, $_REQUEST['feed_id']);
$is_cat = db_escape_string($this->link, $_REQUEST['is_cat']) == "true";
$mode = db_escape_string($this->link, $_REQUEST['mode']);
$feed_id = $this->dbh->escape_string($_REQUEST['feed_id']);
$is_cat = $this->dbh->escape_string($_REQUEST['is_cat']) == "true";
$mode = $this->dbh->escape_string($_REQUEST['mode']);
catchup_feed($this->link, $feed_id, $is_cat, false, false, $mode);
catchup_feed($feed_id, $is_cat, false, false, $mode);
print json_encode(array("message" => "UPDATE_COUNTERS"));
}
function quickAddCat() {
$cat = db_escape_string($this->link, $_REQUEST["cat"]);
$cat = $this->dbh->escape_string($_REQUEST["cat"]);
add_feed_category($this->link, $cat);
add_feed_category($cat);
$result = db_query($this->link, "SELECT id FROM ttrss_feed_categories WHERE
$result = $this->dbh->query("SELECT id FROM ttrss_feed_categories WHERE
title = '$cat' AND owner_uid = " . $_SESSION["uid"]);
if (db_num_rows($result) == 1) {
$id = db_fetch_result($result, 0, "id");
if ($this->dbh->num_rows($result) == 1) {
$id = $this->dbh->fetch_result($result, 0, "id");
} else {
$id = 0;
}
print_feed_cat_select($this->link, "cat_id", $id);
print_feed_cat_select("cat_id", $id, '');
}
// Silent
function clearArticleKeys() {
db_query($this->link, "UPDATE ttrss_user_entries SET uuid = '' WHERE
$this->dbh->query("UPDATE ttrss_user_entries SET uuid = '' WHERE
owner_uid = " . $_SESSION["uid"]);
return;
@@ -478,7 +479,7 @@ class RPC extends Handler_Protected {
$wide = (int) $_REQUEST["wide"];
setcookie("ttrss_widescreen", $wide,
time() + SESSION_COOKIE_LIFETIME);
time() + COOKIE_LIFETIME_LONG);
print json_encode(array("wide" => $wide));
}
@@ -515,7 +516,7 @@ class RPC extends Handler_Protected {
$random_qpart = sql_random_function();
// We search for feed needing update.
$result = db_query($this->link, "SELECT ttrss_feeds.feed_url,ttrss_feeds.id
$result = $this->dbh->query("SELECT ttrss_feeds.feed_url,ttrss_feeds.id
FROM
ttrss_feeds, ttrss_users, ttrss_user_prefs
WHERE
@@ -534,11 +535,11 @@ class RPC extends Handler_Protected {
$tstart = time();
while ($line = db_fetch_assoc($result)) {
while ($line = $this->dbh->fetch_assoc($result)) {
$feed_id = $line["id"];
if (time() - $tstart < ini_get("max_execution_time") * 0.7) {
update_rss_feed($this->link, $feed_id, true);
update_rss_feed($feed_id, true);
++$num_updated;
} else {
break;
@@ -546,8 +547,8 @@ class RPC extends Handler_Protected {
}
// Purge orphans and cleanup tags
purge_orphans($this->link);
cleanup_tags($this->link, 14, 50000);
purge_orphans();
cleanup_tags(14, 50000);
if ($num_updated > 0) {
print json_encode(array("message" => "UPDATE_COUNTERS",
@@ -558,7 +559,7 @@ class RPC extends Handler_Protected {
}
private function markArticlesById($link, $ids, $cmode) {
private function markArticlesById($ids, $cmode) {
$tmp_ids = array();
@@ -569,21 +570,21 @@ class RPC extends Handler_Protected {
$ids_qpart = join(" OR ", $tmp_ids);
if ($cmode == 0) {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
marked = false, last_marked = NOW()
WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
} else if ($cmode == 1) {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
marked = true, last_marked = NOW()
WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
} else {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
marked = NOT marked,last_marked = NOW()
WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
}
}
private function publishArticlesById($link, $ids, $cmode) {
private function publishArticlesById($ids, $cmode) {
$tmp_ids = array();
@@ -594,15 +595,15 @@ class RPC extends Handler_Protected {
$ids_qpart = join(" OR ", $tmp_ids);
if ($cmode == 0) {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
published = false,last_published = NOW()
WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
} else if ($cmode == 1) {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
published = true,last_published = NOW()
WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
} else {
db_query($link, "UPDATE ttrss_user_entries SET
$this->dbh->query("UPDATE ttrss_user_entries SET
published = NOT published,last_published = NOW()
WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
}
@@ -610,7 +611,7 @@ class RPC extends Handler_Protected {
if (PUBSUBHUBBUB_HUB) {
$rss_link = get_self_url_prefix() .
"/public.php?op=rss&id=-2&key=" .
get_feed_access_key($link, -2, false);
get_feed_access_key(-2, false);
$p = new Publisher(PUBSUBHUBBUB_HUB);
@@ -619,14 +620,14 @@ class RPC extends Handler_Protected {
}
function getlinktitlebyid() {
$id = db_escape_string($this->link, $_REQUEST['id']);
$id = $this->dbh->escape_string($_REQUEST['id']);
$result = db_query($this->link, "SELECT link, title FROM ttrss_entries, ttrss_user_entries
$result = $this->dbh->query("SELECT link, title FROM ttrss_entries, ttrss_user_entries
WHERE ref_id = '$id' AND ref_id = id AND owner_uid = ". $_SESSION["uid"]);
if (db_num_rows($result) != 0) {
$link = db_fetch_result($result, 0, "link");
$title = db_fetch_result($result, 0, "title");
if ($this->dbh->num_rows($result) != 0) {
$link = $this->dbh->fetch_result($result, 0, "link");
$title = $this->dbh->fetch_result($result, 0, "title");
echo json_encode(array("link" => $link, "title" => $title));
} else {
@@ -634,5 +635,16 @@ class RPC extends Handler_Protected {
}
}
function log() {
$logmsg = $this->dbh->escape_string($_REQUEST['logmsg']);
if ($logmsg) {
Logger::get()->log_error(E_USER_WARNING,
$logmsg, '[client-js]', 0, false);
}
echo json_encode(array("message" => "HOST_ERROR_LOGGED"));
}
}
?>

View File

@@ -1,7 +0,0 @@
<?php
class SanitizeDummy extends SimplePie_Sanitize {
function sanitize($data, $type, $base = '') {
return $data;
}
}
?>

View File

@@ -17,31 +17,29 @@ class ttrssMailer extends PHPMailer {
public $CharSet = "UTF-8";
public $PluginDir = "lib/phpmailer/";
public $ContentType = "text/html"; //default email type is HTML
public $Host;
public $Port;
public $SMTPAuth=False;
public $Username;
public $Password;
function __construct() {
$this->SetLanguage("en", "lib/phpmailer/language/");
//if SMTP_HOST is specified, use SMTP to send mail directly
if (SMTP_HOST) {
$Host = SMTP_HOST;
$Mailer = "smtp";
}
//if SMTP_PORT is specified, assign it. Otherwise default to port 25
if(SMTP_PORT){
$Port = SMTP_PORT;
}else{
$Port = "25";
if (SMTP_SERVER) {
$pair = explode(":", SMTP_SERVER, 2);
$this->Mailer = "smtp";
$this->Host = $pair[0];
$this->Port = $pair[1];
if (!$this->Port) $this->Port = 25;
} else {
$this->Host = '';
$this->Port = '';
}
//if SMTP_LOGIN is specified, set credentials and enable auth
if(SMTP_LOGIN){
$SMTPAuth = true;
$Username = SMTP_LOGIN;
$Password = SMTP_PASSWORD;
$this->SMTPAuth = true;
$this->Username = SMTP_LOGIN;
$this->Password = SMTP_PASSWORD;
}
}
/* @brief a simple mail function to send email using the defaults

View File

@@ -8,7 +8,7 @@
define('DB_USER', "fox");
define('DB_NAME', "fox");
define('DB_PASS', "XXXXXX");
//define('DB_PORT', '5432'); // when neeeded, PG-only
define('DB_PORT', ''); // usually 5432 for PostgreSQL, 3306 for MySQL
define('MYSQL_CHARSET', 'UTF8');
// Connection charset for MySQL. If you have a legacy database and/or experience
@@ -24,6 +24,13 @@
// You need to set this option correctly otherwise several features
// including PUSH, bookmarklets and browser integration will not work properly.
define('FEED_CRYPT_KEY', '');
// Key used for encryption of passwords for password-protected feeds
// in the database. A string of 24 random characters. If left blank, encryption
// is not used. Requires mcrypt functions.
// Warning: changing this key will make your stored feed passwords impossible
// to decrypt.
define('SINGLE_USER_MODE', false);
// Operate in single user mode, disables all functionality related to
// multiple users and authentication. Enabling this assumes you have
@@ -101,6 +108,9 @@
// 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');
// Hostname:port combination for the Sphinx server.
define('SPHINX_INDEX', 'ttrss');
// Index name in Sphinx configuration. You can specify multiple indexes
// as a comma-separated string.
@@ -129,10 +139,6 @@
define('SESSION_COOKIE_LIFETIME', 86400);
// Default lifetime of a session (e.g. login) cookie. In seconds,
// 0 means cookie will be deleted when browser closes.
// Setting this to zero will affect several user preferences
// like widescreen mode not saving and disable "remember me".
// Note that if remember me is not checked, session cookie
// will always expire with browser session.
define('SESSION_CHECK_ADDRESS', 1);
// Check client IP address when validating session:
@@ -153,16 +159,14 @@
define('DIGEST_SUBJECT', '[tt-rss] New headlines for last 24 hours');
// Subject line for email digests
define('SMTP_HOST', '');
// SMTP Host to send outgoing mail. Blank - use system MTA.
define('SMTP_PORT','');
// SMTP port to sent outgoing mail. Default is 25.
define('SMTP_SERVER', '');
// Hostname:port combination to send outgoing mail (i.e. localhost:25).
// Blank - use system MTA.
define('SMTP_LOGIN', '');
define('SMTP_PASSWORD', '');
// These two options enable SMTP authentication when sending
// outgoing mail. Only used with SMTP_HOST
// outgoing mail. Only used with SMTP_SERVER.
// ***************************************
// *** Other settings (less important) ***
@@ -184,6 +188,14 @@
// authentication plugin here (auth_*).
// Users may enable other user plugins from Preferences/Plugins but may not
// disable plugins specified in this list.
// Disabling auth_internal in this list would automatically disable
// reset password link on the login form.
define('LOG_DESTINATION', 'sql');
// Log destination to use. Possible values: sql (uses internal logging
// you can read in Preferences -> System), syslog - logs to system log.
// Setting this to blank uses PHP logging (usually to http server
// error.log).
define('CONFIG_VERSION', 26);
// Expected config version. Please update this option in config.php

0
feed-icons/index.html Normal file
View File

76
images/close_notify.svg Normal file
View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
id="svg2985"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="close_notify.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#88b0f0"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.197802"
inkscape:cx="0.97227717"
inkscape:cy="8"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1920"
inkscape:window-height="1138"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#454545;stroke-width:0.73948608000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path2997"
sodipodi:cx="6.6673269"
sodipodi:cy="7.1702971"
sodipodi:rx="5.270792"
sodipodi:ry="5.270792"
d="m 11.938119,7.1702971 a 5.270792,5.270792 0 1 1 -10.5415841,0 5.270792,5.270792 0 1 1 10.5415841,0 z"
transform="matrix(1.3522905,0,0,1.3522905,-1.0161629,-1.6963247)" />
<path
style="fill:none;stroke:#454545;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;opacity:1"
d="M 4.4322613,4.4322611 11.567739,11.567739"
id="path3771"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#454545;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;opacity:1"
d="M 11.567739,4.432261 4.432261,11.567739"
id="path3771-1"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

14
include/autoload.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
require_once "functions.php";
function __autoload($class) {
$class_file = str_replace("_", "/", strtolower(basename($class)));
$file = dirname(__FILE__)."/../classes/$class_file.php";
if (file_exists($file)) {
require $file;
}
}
?>

View File

@@ -1,19 +1,19 @@
<?php
/* function ccache_zero($link, $feed_id, $owner_uid) {
db_query($link, "UPDATE ttrss_counters_cache SET
/* function ccache_zero($feed_id, $owner_uid) {
db_query("UPDATE ttrss_counters_cache SET
value = 0, updated = NOW() WHERE
feed_id = '$feed_id' AND owner_uid = '$owner_uid'");
} */
function ccache_zero_all($link, $owner_uid) {
db_query($link, "UPDATE ttrss_counters_cache SET
function ccache_zero_all($owner_uid) {
db_query("UPDATE ttrss_counters_cache SET
value = 0 WHERE owner_uid = '$owner_uid'");
db_query($link, "UPDATE ttrss_cat_counters_cache SET
db_query("UPDATE ttrss_cat_counters_cache SET
value = 0 WHERE owner_uid = '$owner_uid'");
}
function ccache_remove($link, $feed_id, $owner_uid, $is_cat = false) {
function ccache_remove($feed_id, $owner_uid, $is_cat = false) {
if (!$is_cat) {
$table = "ttrss_counters_cache";
@@ -21,39 +21,39 @@
$table = "ttrss_cat_counters_cache";
}
db_query($link, "DELETE FROM $table WHERE
db_query("DELETE FROM $table WHERE
feed_id = '$feed_id' AND owner_uid = '$owner_uid'");
}
function ccache_update_all($link, $owner_uid) {
function ccache_update_all($owner_uid) {
if (get_pref($link, 'ENABLE_FEED_CATS', $owner_uid)) {
if (get_pref('ENABLE_FEED_CATS', $owner_uid)) {
$result = db_query($link, "SELECT feed_id FROM ttrss_cat_counters_cache
$result = db_query("SELECT feed_id FROM ttrss_cat_counters_cache
WHERE feed_id > 0 AND owner_uid = '$owner_uid'");
while ($line = db_fetch_assoc($result)) {
ccache_update($link, $line["feed_id"], $owner_uid, true);
ccache_update($line["feed_id"], $owner_uid, true);
}
/* We have to manually include category 0 */
ccache_update($link, 0, $owner_uid, true);
ccache_update(0, $owner_uid, true);
} else {
$result = db_query($link, "SELECT feed_id FROM ttrss_counters_cache
$result = db_query("SELECT feed_id FROM ttrss_counters_cache
WHERE feed_id > 0 AND owner_uid = '$owner_uid'");
while ($line = db_fetch_assoc($result)) {
print ccache_update($link, $line["feed_id"], $owner_uid);
print ccache_update($line["feed_id"], $owner_uid);
}
}
}
function ccache_find($link, $feed_id, $owner_uid, $is_cat = false,
function ccache_find($feed_id, $owner_uid, $is_cat = false,
$no_update = false) {
if (!is_numeric($feed_id)) return;
@@ -61,7 +61,7 @@
if (!$is_cat) {
$table = "ttrss_counters_cache";
/* if ($feed_id > 0) {
$tmp_result = db_query($link, "SELECT owner_uid FROM ttrss_feeds
$tmp_result = db_query("SELECT owner_uid FROM ttrss_feeds
WHERE id = '$feed_id'");
$owner_uid = db_fetch_result($tmp_result, 0, "owner_uid");
} */
@@ -75,7 +75,7 @@
$date_qpart = "updated > DATE_SUB(NOW(), INTERVAL 15 MINUTE)";
}
$result = db_query($link, "SELECT value FROM $table
$result = db_query("SELECT value FROM $table
WHERE owner_uid = '$owner_uid' AND feed_id = '$feed_id'
LIMIT 1");
@@ -85,30 +85,30 @@
if ($no_update) {
return -1;
} else {
return ccache_update($link, $feed_id, $owner_uid, $is_cat);
return ccache_update($feed_id, $owner_uid, $is_cat);
}
}
}
function ccache_update($link, $feed_id, $owner_uid, $is_cat = false,
function ccache_update($feed_id, $owner_uid, $is_cat = false,
$update_pcat = true) {
if (!is_numeric($feed_id)) return;
/* if (!$is_cat && $feed_id > 0) {
$tmp_result = db_query($link, "SELECT owner_uid FROM ttrss_feeds
$tmp_result = db_query("SELECT owner_uid FROM ttrss_feeds
WHERE id = '$feed_id'");
$owner_uid = db_fetch_result($tmp_result, 0, "owner_uid");
} */
$prev_unread = ccache_find($link, $feed_id, $owner_uid, $is_cat, true);
$prev_unread = ccache_find($feed_id, $owner_uid, $is_cat, true);
/* When updating a label, all we need to do is recalculate feed counters
* because labels are not cached */
if ($feed_id < 0) {
ccache_update_all($link, $owner_uid);
ccache_update_all($owner_uid);
return;
}
@@ -127,14 +127,14 @@
/* Recalculate counters for child feeds */
$result = db_query($link, "SELECT id FROM ttrss_feeds
$result = db_query("SELECT id FROM ttrss_feeds
WHERE owner_uid = '$owner_uid' AND $cat_qpart");
while ($line = db_fetch_assoc($result)) {
ccache_update($link, $line["id"], $owner_uid, false, false);
ccache_update($line["id"], $owner_uid, false, false);
}
$result = db_query($link, "SELECT SUM(value) AS sv
$result = db_query("SELECT SUM(value) AS sv
FROM ttrss_counters_cache, ttrss_feeds
WHERE id = feed_id AND $cat_qpart AND
ttrss_feeds.owner_uid = '$owner_uid'");
@@ -142,27 +142,27 @@
$unread = (int) db_fetch_result($result, 0, "sv");
} else {
$unread = (int) getFeedArticles($link, $feed_id, $is_cat, true, $owner_uid);
$unread = (int) getFeedArticles($feed_id, $is_cat, true, $owner_uid);
}
db_query($link, "BEGIN");
db_query("BEGIN");
$result = db_query($link, "SELECT feed_id FROM $table
$result = db_query("SELECT feed_id FROM $table
WHERE owner_uid = '$owner_uid' AND feed_id = '$feed_id' LIMIT 1");
if (db_num_rows($result) == 1) {
db_query($link, "UPDATE $table SET
db_query("UPDATE $table SET
value = '$unread', updated = NOW() WHERE
feed_id = '$feed_id' AND owner_uid = '$owner_uid'");
} else {
db_query($link, "INSERT INTO $table
db_query("INSERT INTO $table
(feed_id, value, owner_uid, updated)
VALUES
($feed_id, $unread, $owner_uid, NOW())");
}
db_query($link, "COMMIT");
db_query("COMMIT");
if ($feed_id > 0 && $prev_unread != $unread) {
@@ -172,36 +172,36 @@
if ($update_pcat) {
$result = db_query($link, "SELECT cat_id FROM ttrss_feeds
$result = db_query("SELECT cat_id FROM ttrss_feeds
WHERE owner_uid = '$owner_uid' AND id = '$feed_id'");
$cat_id = (int) db_fetch_result($result, 0, "cat_id");
ccache_update($link, $cat_id, $owner_uid, true);
ccache_update($cat_id, $owner_uid, true);
}
}
} else if ($feed_id < 0) {
ccache_update_all($link, $owner_uid);
ccache_update_all($owner_uid);
}
return $unread;
}
/* function ccache_cleanup($link, $owner_uid) {
/* function ccache_cleanup($owner_uid) {
if (DB_TYPE == "pgsql") {
db_query($link, "DELETE FROM ttrss_counters_cache AS c1 WHERE
db_query("DELETE FROM ttrss_counters_cache AS c1 WHERE
(SELECT count(*) FROM ttrss_counters_cache AS c2
WHERE c1.feed_id = c2.feed_id AND c2.owner_uid = c1.owner_uid) > 1
AND owner_uid = '$owner_uid'");
db_query($link, "DELETE FROM ttrss_cat_counters_cache AS c1 WHERE
db_query("DELETE FROM ttrss_cat_counters_cache AS c1 WHERE
(SELECT count(*) FROM ttrss_cat_counters_cache AS c2
WHERE c1.feed_id = c2.feed_id AND c2.owner_uid = c1.owner_uid) > 1
AND owner_uid = '$owner_uid'");
} else {
db_query($link, "DELETE c1 FROM
db_query("DELETE c1 FROM
ttrss_counters_cache AS c1,
ttrss_counters_cache AS c2
WHERE
@@ -209,7 +209,7 @@
c1.owner_uid = c2.owner_uid AND
c1.feed_id = c2.feed_id");
db_query($link, "DELETE c1 FROM
db_query("DELETE c1 FROM
ttrss_cat_counters_cache AS c1,
ttrss_cat_counters_cache AS c2
WHERE

View File

@@ -1,5 +1,7 @@
<?php
require_once "lib/floIcon.php";
function _resolve_htmlcolor($color) {
$htmlcolors = array ("aliceblue" => "#f0f8ff",
"antiquewhite" => "#faebd7",
@@ -235,16 +237,16 @@ function rgb2hsl($arr) {
} else {
$s = $del_Max / $var_Max;
$del_R = ( ( ( $max - $var_R ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_G = ( ( ( $max - $var_G ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_B = ( ( ( $max - $var_B ) / 6 ) + ( $del_Max / 2 ) ) / $del_Max;
$del_R = ((($var_Max - $var_R ) / 6 ) + ($del_Max / 2 ) ) / $del_Max;
$del_G = ((($var_Max - $var_G ) / 6 ) + ($del_Max / 2 ) ) / $del_Max;
$del_B = ((($var_Max - $var_B ) / 6 ) + ($del_Max / 2 ) ) / $del_Max;
if ($var_R == $var_Max) $h = $del_B - $del_G;
else if ($var_G == $var_Max) $h = ( 1 / 3 ) + $del_R - $del_B;
else if ($var_B == $var_Max) $h = ( 2 / 3 ) + $del_G - $del_R;
else if ($var_G == $var_Max) $h = (1 / 3 ) + $del_R - $del_B;
else if ($var_B == $var_Max) $h = (2 / 3 ) + $del_G - $del_R;
if ($H < 0) $h++;
if ($H > 1) $h--;
if ($h < 0) $h++;
if ($h > 1) $h--;
}
return array($h, $s, $v);
@@ -259,10 +261,10 @@ function hsl2rgb($arr) {
$r = $g = $B = $v * 255;
} else {
$var_H = $h * 6;
$var_i = floor( $var_H );
$var_1 = $v * ( 1 - $s );
$var_2 = $v * ( 1 - $s * ( $var_H - $var_i ) );
$var_3 = $v * ( 1 - $s * (1 - ( $var_H - $var_i ) ) );
$var_i = floor($var_H );
$var_1 = $v * (1 - $s );
$var_2 = $v * (1 - $s * ($var_H - $var_i ) );
$var_3 = $v * (1 - $s * (1 - ($var_H - $var_i ) ) );
if ($var_i == 0) { $var_R = $v ; $var_G = $var_3 ; $var_B = $var_1 ; }
else if ($var_i == 1) { $var_R = $var_2 ; $var_G = $v ; $var_B = $var_1 ; }
@@ -278,4 +280,62 @@ function hsl2rgb($arr) {
return array($r, $g, $B);
}
function colorPalette($imageFile, $numColors, $granularity = 5) {
$granularity = max(1, abs((int)$granularity));
$colors = array();
$size = @getimagesize($imageFile);
if (!defined('_DISABLE_FLOICON') && strtolower($size['mime']) == 'image/vnd.microsoft.icon') {
$ico = new floIcon();
@$ico->readICO($imageFile);
if(count($ico->images)==0)
return null;
else
$img = @$ico->images[count($ico->images)-1]->getImageResource();
} else {
$img = @imagecreatefromstring(file_get_contents($imageFile));
}
if (!$img) return false;
for($x = 0; $x < $size[0]; $x += $granularity) {
for($y = 0; $y < $size[1]; $y += $granularity) {
$thisColor = imagecolorat($img, $x, $y);
$rgb = imagecolorsforindex($img, $thisColor);
$red = round(round(($rgb['red'] / 0x33)) * 0x33);
$green = round(round(($rgb['green'] / 0x33)) * 0x33);
$blue = round(round(($rgb['blue'] / 0x33)) * 0x33);
$thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue);
if(array_key_exists($thisRGB, $colors)) {
$colors[$thisRGB]++;
} else{
$colors[$thisRGB] = 1;
}
}
}
arsort($colors);
return array_slice(array_keys($colors), 0, $numColors);
}
function calculate_avg_color($iconFile) {
$palette = colorPalette($iconFile, 4, 4);
if (is_array($palette)) {
foreach ($palette as $p) {
$hsl = rgb2hsl(_color_unpack("#$p"));
if ($hsl[1] > 0.25 && $hsl[2] > 0.25 &&
!($hsl[0] >= 0 && $hsl[0] < 0.01 && $hsl[1] < 0.01) &&
!($hsl[0] >= 0 && $hsl[0] < 0.01 && $hsl[2] > 0.99)) {
return _color_pack(hsl2rgb($hsl));
}
}
}
return '';
}
?>

36
include/crypt.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
function decrypt_string($str) {
$pair = explode(":", $str);
if (count($pair) == 2) {
@$iv = base64_decode($pair[0]);
@$encstr = base64_decode($pair[1]);
if ($iv && $encstr) {
$key = hash('SHA256', FEED_CRYPT_KEY, true);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encstr,
MCRYPT_MODE_CBC, $iv);
if ($str) return rtrim($str);
}
}
return false;
}
function encrypt_string($str) {
$key = hash('SHA256', FEED_CRYPT_KEY, true);
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,
MCRYPT_MODE_CBC), MCRYPT_RAND);
$encstr = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str,
MCRYPT_MODE_CBC, $iv);
$iv_base64 = base64_encode($iv);
$encstr_base64 = base64_encode($encstr);
return "$iv_base64:$encstr_base64";
}
?>

View File

@@ -1,186 +1,11 @@
<?php
require_once "config.php";
require_once "db.php";
if (!defined('DISABLE_SESSIONS') && !defined('PREFS_NO_CACHE')) {
if (!$_SESSION["prefs_cache"])
$_SESSION["prefs_cache"] = array();
function get_pref($pref_name, $user_id = false, $die_on_error = false) {
return Db_Prefs::get()->read($pref_name, $user_id, $die_on_error);
}
function cache_prefs($link) {
$profile = false;
$user_id = $_SESSION["uid"];
@$profile = $_SESSION["profile"];
if ($profile) {
$profile_qpart = "profile = '$profile' AND";
} else {
$profile_qpart = "profile IS NULL AND";
}
if (get_schema_version($link) < 63) $profile_qpart = "";
$result = db_query($link, "SELECT
value,ttrss_prefs_types.type_name as type_name,ttrss_prefs.pref_name AS pref_name
FROM
ttrss_user_prefs,ttrss_prefs,ttrss_prefs_types
WHERE
$profile_qpart
ttrss_prefs.pref_name NOT LIKE '_MOBILE%' AND
ttrss_prefs_types.id = type_id AND
owner_uid = '$user_id' AND
ttrss_user_prefs.pref_name = ttrss_prefs.pref_name");
while ($line = db_fetch_assoc($result)) {
if ($user_id == $_SESSION["uid"]) {
$pref_name = $line["pref_name"];
$_SESSION["prefs_cache"][$pref_name]["type"] = $line["type_name"];
$_SESSION["prefs_cache"][$pref_name]["value"] = $line["value"];
}
}
}
function get_pref($link, $pref_name, $user_id = false, $die_on_error = false) {
$pref_name = db_escape_string($link, $pref_name);
$prefs_cache = true;
$profile = false;
if (!$user_id) {
$user_id = $_SESSION["uid"];
@$profile = $_SESSION["profile"];
} else {
$user_id = sprintf("%d", $user_id);
//$prefs_cache = false;
}
if ($prefs_cache && !defined('DISABLE_SESSIONS') && !defined('PREFS_NO_CACHE')) {
if ($_SESSION["prefs_cache"] && @$_SESSION["prefs_cache"][$pref_name]) {
$tuple = $_SESSION["prefs_cache"][$pref_name];
return convert_pref_type($tuple["value"], $tuple["type"]);
}
}
if ($profile) {
$profile_qpart = "profile = '$profile' AND";
} else {
$profile_qpart = "profile IS NULL AND";
}
if (get_schema_version($link) < 63) $profile_qpart = "";
$result = db_query($link, "SELECT
value,ttrss_prefs_types.type_name as type_name
FROM
ttrss_user_prefs,ttrss_prefs,ttrss_prefs_types
WHERE
$profile_qpart
ttrss_user_prefs.pref_name = '$pref_name' AND
ttrss_prefs_types.id = type_id AND
owner_uid = '$user_id' AND
ttrss_user_prefs.pref_name = ttrss_prefs.pref_name");
if (db_num_rows($result) > 0) {
$value = db_fetch_result($result, 0, "value");
$type_name = db_fetch_result($result, 0, "type_name");
if (!defined('DISABLE_SESSIONS')) {
if ($user_id == $_SESSION["uid"]) {
$_SESSION["prefs_cache"][$pref_name]["type"] = $type_name;
$_SESSION["prefs_cache"][$pref_name]["value"] = $value;
}
}
return convert_pref_type($value, $type_name);
} else {
if ($die_on_error) {
die("Fatal error, unknown preferences key: $pref_name");
} else {
return null;
}
}
}
function convert_pref_type($value, $type_name) {
if ($type_name == "bool") {
return $value == "true";
} else if ($type_name == "integer") {
return sprintf("%d", $value);
} else {
return $value;
}
}
function set_pref($link, $pref_name, $value, $user_id = false, $strip_tags = true) {
$pref_name = db_escape_string($link, $pref_name);
$value = db_escape_string($link, $value, $strip_tags);
if (!$user_id) {
$user_id = $_SESSION["uid"];
@$profile = $_SESSION["profile"];
} else {
$user_id = sprintf("%d", $user_id);
$prefs_cache = false;
}
if ($profile) {
$profile_qpart = "AND profile = '$profile'";
} else {
$profile_qpart = "AND profile IS NULL";
}
if (get_schema_version($link) < 63) $profile_qpart = "";
$type_name = "";
$current_value = "";
if (!defined('DISABLE_SESSIONS') && !defined('PREFS_NO_CACHE')) {
if ($_SESSION["prefs_cache"] && @$_SESSION["prefs_cache"][$pref_name]) {
$type_name = $_SESSION["prefs_cache"][$pref_name]["type"];
$current_value = $_SESSION["prefs_cache"][$pref_name]["value"];
}
}
if (!$type_name) {
$result = db_query($link, "SELECT type_name
FROM ttrss_prefs,ttrss_prefs_types
WHERE pref_name = '$pref_name' AND type_id = ttrss_prefs_types.id");
if (db_num_rows($result) > 0)
$type_name = db_fetch_result($result, 0, "type_name");
} else if ($current_value == $value) {
return;
}
if ($type_name) {
if ($type_name == "bool") {
if ($value == "1" || $value == "true") {
$value = "true";
} else {
$value = "false";
}
} else if ($type_name == "integer") {
$value = sprintf("%d", $value);
}
if ($pref_name == 'USER_TIMEZONE' && $value == '') {
$value = 'UTC';
}
db_query($link, "UPDATE ttrss_user_prefs SET
value = '$value' WHERE pref_name = '$pref_name'
$profile_qpart
AND owner_uid = " . $_SESSION["uid"]);
if (!defined('DISABLE_SESSIONS')) {
if ($user_id == $_SESSION["uid"]) {
$_SESSION["prefs_cache"][$pref_name]["type"] = $type_name;
$_SESSION["prefs_cache"][$pref_name]["value"] = $value;
}
}
}
function set_pref($pref_name, $value, $user_id = false, $strip_tags = true) {
return Db_Prefs::get()->write($pref_name, $value, $user_id, $strip_tags);
}
?>

View File

@@ -1,138 +1,36 @@
<?php
require_once "config.php";
function db_connect($host, $user, $pass, $db) {
if (DB_TYPE == "pgsql") {
$string = "dbname=$db user=$user";
if ($pass) {
$string .= " password=$pass";
}
if ($host) {
$string .= " host=$host";
}
if (defined('DB_PORT') && DB_PORT) {
$string = "$string port=" . DB_PORT;
}
$link = pg_connect($string);
if (!$link) {
die("Unable to connect to database (as $user to $host, database $db):" . pg_last_error());
}
return $link;
} else if (DB_TYPE == "mysql") {
$link = mysql_connect($host, $user, $pass);
if ($link) {
$result = mysql_select_db($db, $link);
if (!$result) {
die("Can't select DB: " . mysql_error($link));
}
return $link;
} else {
die("Unable to connect to database (as $user to $host, database $db): " . mysql_error());
}
}
function db_escape_string($s, $strip_tags = true) {
return Db::get()->escape_string($s, $strip_tags);
}
function db_escape_string($link, $s, $strip_tags = true) {
if ($strip_tags) $s = strip_tags($s);
if (DB_TYPE == "pgsql") {
return pg_escape_string($link, $s);
} else {
return mysql_real_escape_string($s, $link);
}
}
function db_query($link, $query, $die_on_error = true) {
if (DB_TYPE == "pgsql") {
$result = pg_query($link, $query);
if (!$result) {
$query = htmlspecialchars($query); // just in case
if ($die_on_error) {
die("Query <i>$query</i> failed [$result]: " . ($link ? pg_last_error($link) : "No connection"));
}
}
return $result;
} else if (DB_TYPE == "mysql") {
$result = mysql_query($query, $link);
if (!$result) {
$query = htmlspecialchars($query);
if ($die_on_error) {
die("Query <i>$query</i> failed: " . ($link ? mysql_error($link) : "No connection"));
}
}
return $result;
}
function db_query($query, $die_on_error = true) {
return Db::get()->query($query, $die_on_error);
}
function db_fetch_assoc($result) {
if (DB_TYPE == "pgsql") {
return pg_fetch_assoc($result);
} else if (DB_TYPE == "mysql") {
return mysql_fetch_assoc($result);
}
return Db::get()->fetch_assoc($result);
}
function db_num_rows($result) {
if (DB_TYPE == "pgsql") {
return pg_num_rows($result);
} else if (DB_TYPE == "mysql") {
return mysql_num_rows($result);
}
return Db::get()->num_rows($result);
}
function db_fetch_result($result, $row, $param) {
if (DB_TYPE == "pgsql") {
return pg_fetch_result($result, $row, $param);
} else if (DB_TYPE == "mysql") {
// I hate incoherent naming of PHP functions
return mysql_result($result, $row, $param);
}
return Db::get()->fetch_result($result, $row, $param);
}
function db_unescape_string($str) {
$tmp = str_replace("\\\"", "\"", $str);
$tmp = str_replace("\\'", "'", $tmp);
return $tmp;
function db_affected_rows($result) {
return Db::get()->affected_rows($result);
}
function db_close($link) {
if (DB_TYPE == "pgsql") {
return pg_close($link);
} else if (DB_TYPE == "mysql") {
return mysql_close($link);
}
}
function db_affected_rows($link, $result) {
if (DB_TYPE == "pgsql") {
return pg_affected_rows($result);
} else if (DB_TYPE == "mysql") {
return mysql_affected_rows($link);
}
}
function db_last_error($link) {
if (DB_TYPE == "pgsql") {
return pg_last_error($link);
} else if (DB_TYPE == "mysql") {
return mysql_error($link);
}
function db_last_error() {
return Db::get()->last_error();
}
function db_quote($str){
return("'$str'");
return Db::get()->quote($str);
}
?>

View File

@@ -6,7 +6,7 @@
* @param integer $limit The maximum number of articles by digest.
* @return boolean Return false if digests are not enabled.
*/
function send_headlines_digests($link, $debug = false) {
function send_headlines_digests($debug = false) {
require_once 'classes/ttrssmailer.php';
@@ -21,28 +21,28 @@
$interval_query = "last_digest_sent < DATE_SUB(NOW(), INTERVAL 1 DAY)";
}
$result = db_query($link, "SELECT id,email FROM ttrss_users
$result = db_query("SELECT id,email FROM ttrss_users
WHERE email != '' AND (last_digest_sent IS NULL OR $interval_query)");
while ($line = db_fetch_assoc($result)) {
if (get_pref($link, 'DIGEST_ENABLE', $line['id'], false)) {
$preferred_ts = strtotime(get_pref($link, 'DIGEST_PREFERRED_TIME', $line['id'], '00:00'));
if (get_pref('DIGEST_ENABLE', $line['id'], false)) {
$preferred_ts = strtotime(get_pref('DIGEST_PREFERRED_TIME', $line['id'], '00:00'));
// try to send digests within 2 hours of preferred time
if ($preferred_ts && time() >= $preferred_ts &&
time() - $preferred_ts <= 7200) {
if ($debug) print "Sending digest for UID:" . $line['id'] . " - " . $line["email"] . " ... ";
if ($debug) _debug("Sending digest for UID:" . $line['id'] . " - " . $line["email"]);
$do_catchup = get_pref($link, 'DIGEST_CATCHUP', $line['id'], false);
$do_catchup = get_pref('DIGEST_CATCHUP', $line['id'], false);
global $tz_offset;
// reset tz_offset global to prevent tz cache clash between users
$tz_offset = -1;
$tuple = prepare_headlines_digest($link, $line["id"], 1, $limit);
$tuple = prepare_headlines_digest($line["id"], 1, $limit);
$digest = $tuple[0];
$headlines_count = $tuple[1];
$affected_ids = $tuple[2];
@@ -54,19 +54,19 @@
$rc = $mail->quickMail($line["email"], $line["login"] , DIGEST_SUBJECT, $digest, $digest_text);
if (!$rc && $debug) print "ERROR: " . $mail->ErrorInfo;
if (!$rc && $debug) _debug("ERROR: " . $mail->ErrorInfo);
if ($debug) print "RC=$rc\n";
if ($debug) _debug("RC=$rc");
if ($rc && $do_catchup) {
if ($debug) print "Marking affected articles as read...\n";
catchupArticlesById($link, $affected_ids, 0, $line["id"]);
if ($debug) _debug("Marking affected articles as read...");
catchupArticlesById($affected_ids, 0, $line["id"]);
}
} else {
if ($debug) print "No headlines\n";
if ($debug) _debug("No headlines");
}
db_query($link, "UPDATE ttrss_users SET last_digest_sent = NOW()
db_query("UPDATE ttrss_users SET last_digest_sent = NOW()
WHERE id = " . $line["id"]);
}
@@ -77,7 +77,7 @@
}
function prepare_headlines_digest($link, $user_id, $days = 1, $limit = 1000) {
function prepare_headlines_digest($user_id, $days = 1, $limit = 1000) {
require_once "lib/MiniTemplator.class.php";
@@ -87,7 +87,7 @@
$tpl->readTemplateFromFile("templates/digest_template_html.txt");
$tpl_t->readTemplateFromFile("templates/digest_template.txt");
$user_tz_string = get_pref($link, 'USER_TIMEZONE', $user_id);
$user_tz_string = get_pref('USER_TIMEZONE', $user_id);
$local_ts = convert_timestamp(time(), 'UTC', $user_tz_string);
$tpl->setVariable('CUR_DATE', date('Y/m/d', $local_ts));
@@ -104,7 +104,7 @@
$interval_query = "ttrss_entries.date_updated > DATE_SUB(NOW(), INTERVAL $days DAY)";
}
$result = db_query($link, "SELECT ttrss_entries.title,
$result = db_query("SELECT ttrss_entries.title,
ttrss_feeds.title AS feed_title,
COALESCE(ttrss_feed_categories.title, '".__('Uncategorized')."') AS cat_title,
date_updated,
@@ -143,7 +143,7 @@
array_push($affected_ids, $line["ref_id"]);
$updated = make_local_datetime($link, $line['last_updated'], false,
$updated = make_local_datetime($line['last_updated'], false,
$user_id);
/* if ($line["score"] != 0) {
@@ -152,7 +152,7 @@
$line["title"] .= " (".$line['score'].")";
} */
if (get_pref($link, 'ENABLE_FEED_CATS', $user_id)) {
if (get_pref('ENABLE_FEED_CATS', $user_id)) {
$line['feed_title'] = $line['cat_title'] . " / " . $line['feed_title'];
}

37
include/errorhandler.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
function ttrss_error_handler($errno, $errstr, $file, $line, $context) {
global $logger;
if (error_reporting() == 0 || !$errno) return false;
$file = substr(str_replace(dirname(dirname(__FILE__)), "", $file), 1);
return Logger::get()->log_error($errno, $errstr, $file, $line, $context);
}
function ttrss_fatal_handler() {
global $logger;
$error = error_get_last();
if ($error !== NULL) {
$errno = $error["type"];
$file = $error["file"];
$line = $error["line"];
$errstr = $error["message"];
if (!$errno) return false;
$context = debug_backtrace();
$file = substr(str_replace(dirname(dirname(__FILE__)), "", $file), 1);
return Logger::get()->log_error($errno, $errstr, $file, $line, $context);
}
return false;
}
register_shutdown_function('ttrss_fatal_handler');
set_error_handler('ttrss_error_handler');
?>

View File

@@ -1,5 +1,5 @@
<?php
function make_feed_browser($link, $search, $limit, $mode = 1) {
function make_feed_browser($search, $limit, $mode = 1) {
$owner_uid = $_SESSION["uid"];
$rv = '';
@@ -12,13 +12,13 @@
}
if ($mode == 1) {
/* $result = db_query($link, "SELECT feed_url, subscribers FROM
/* $result = db_query("SELECT feed_url, subscribers FROM
ttrss_feedbrowser_cache WHERE (SELECT COUNT(id) = 0 FROM ttrss_feeds AS tf
WHERE tf.feed_url = ttrss_feedbrowser_cache.feed_url
AND owner_uid = '$owner_uid') $search_qpart
ORDER BY subscribers DESC LIMIT $limit"); */
$result = db_query($link, "SELECT feed_url, site_url, title, SUM(subscribers) AS subscribers FROM
$result = db_query("SELECT feed_url, site_url, title, SUM(subscribers) AS subscribers FROM
(SELECT feed_url, site_url, title, subscribers FROM ttrss_feedbrowser_cache UNION ALL
SELECT feed_url, site_url, title, subscribers FROM ttrss_linked_feeds) AS qqq
WHERE
@@ -28,7 +28,7 @@
GROUP BY feed_url, site_url, title ORDER BY subscribers DESC LIMIT $limit");
} else if ($mode == 2) {
$result = db_query($link, "SELECT *,
$result = db_query("SELECT *,
(SELECT COUNT(*) FROM ttrss_user_entries WHERE
orig_feed_id = ttrss_archived_feeds.id) AS articles_archived
FROM

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
<?php
function label_find_id($link, $label, $owner_uid) {
$result = db_query($link,
function label_find_id($label, $owner_uid) {
$result = db_query(
"SELECT id FROM ttrss_labels2 WHERE caption = '$label'
AND owner_uid = '$owner_uid' LIMIT 1");
@@ -11,12 +11,12 @@
}
}
function get_article_labels($link, $id, $owner_uid = false) {
function get_article_labels($id, $owner_uid = false) {
$rv = array();
if (!$owner_uid) $owner_uid = $_SESSION["uid"];
$result = db_query($link, "SELECT label_cache FROM
$result = db_query("SELECT label_cache FROM
ttrss_user_entries WHERE ref_id = '$id' AND owner_uid = " .
$owner_uid);
@@ -33,7 +33,7 @@
}
}
$result = db_query($link,
$result = db_query(
"SELECT DISTINCT label_id,caption,fg_color,bg_color
FROM ttrss_labels2, ttrss_user_labels2
WHERE id = label_id
@@ -48,16 +48,16 @@
}
if (count($rv) > 0)
label_update_cache($link, $owner_uid, $id, $rv);
label_update_cache($owner_uid, $id, $rv);
else
label_update_cache($link, $owner_uid, $id, array("no-labels" => 1));
label_update_cache($owner_uid, $id, array("no-labels" => 1));
return $rv;
}
function label_find_caption($link, $label, $owner_uid) {
$result = db_query($link,
function label_find_caption($label, $owner_uid) {
$result = db_query(
"SELECT caption FROM ttrss_labels2 WHERE id = '$label'
AND owner_uid = '$owner_uid' LIMIT 1");
@@ -68,10 +68,10 @@
}
}
function get_all_labels($link, $owner_uid) {
function get_all_labels($owner_uid) {
$rv = array();
$result = db_query($link, "SELECT fg_color, bg_color, caption FROM ttrss_labels2 WHERE owner_uid = " . $owner_uid);
$result = db_query("SELECT fg_color, bg_color, caption FROM ttrss_labels2 WHERE owner_uid = " . $owner_uid);
while ($line = db_fetch_assoc($result)) {
array_push($rv, $line);
@@ -80,50 +80,50 @@
return $rv;
}
function label_update_cache($link, $owner_uid, $id, $labels = false, $force = false) {
function label_update_cache($owner_uid, $id, $labels = false, $force = false) {
if ($force)
label_clear_cache($link, $id);
label_clear_cache($id);
if (!$labels)
$labels = get_article_labels($link, $id);
$labels = get_article_labels($id);
$labels = db_escape_string($link, json_encode($labels));
$labels = db_escape_string(json_encode($labels));
db_query($link, "UPDATE ttrss_user_entries SET
db_query("UPDATE ttrss_user_entries SET
label_cache = '$labels' WHERE ref_id = '$id' AND owner_uid = '$owner_uid'");
}
function label_clear_cache($link, $id) {
function label_clear_cache($id) {
db_query($link, "UPDATE ttrss_user_entries SET
db_query("UPDATE ttrss_user_entries SET
label_cache = '' WHERE ref_id = '$id'");
}
function label_remove_article($link, $id, $label, $owner_uid) {
function label_remove_article($id, $label, $owner_uid) {
$label_id = label_find_id($link, $label, $owner_uid);
$label_id = label_find_id($label, $owner_uid);
if (!$label_id) return;
$result = db_query($link,
$result = db_query(
"DELETE FROM ttrss_user_labels2
WHERE
label_id = '$label_id' AND
article_id = '$id'");
label_clear_cache($link, $id);
label_clear_cache($id);
}
function label_add_article($link, $id, $label, $owner_uid) {
function label_add_article($id, $label, $owner_uid) {
$label_id = label_find_id($link, $label, $owner_uid);
$label_id = label_find_id($label, $owner_uid);
if (!$label_id) return;
$result = db_query($link,
$result = db_query(
"SELECT
article_id FROM ttrss_labels2, ttrss_user_labels2
WHERE
@@ -133,66 +133,66 @@
LIMIT 1");
if (db_num_rows($result) == 0) {
db_query($link, "INSERT INTO ttrss_user_labels2
db_query("INSERT INTO ttrss_user_labels2
(label_id, article_id) VALUES ('$label_id', '$id')");
}
label_clear_cache($link, $id);
label_clear_cache($id);
}
function label_remove($link, $id, $owner_uid) {
function label_remove($id, $owner_uid) {
if (!$owner_uid) $owner_uid = $_SESSION["uid"];
db_query($link, "BEGIN");
db_query("BEGIN");
$result = db_query($link, "SELECT caption FROM ttrss_labels2
$result = db_query("SELECT caption FROM ttrss_labels2
WHERE id = '$id'");
$caption = db_fetch_result($result, 0, "caption");
$result = db_query($link, "DELETE FROM ttrss_labels2 WHERE id = '$id'
$result = db_query("DELETE FROM ttrss_labels2 WHERE id = '$id'
AND owner_uid = " . $owner_uid);
if (db_affected_rows($link, $result) != 0 && $caption) {
if (db_affected_rows($result) != 0 && $caption) {
/* Remove access key for the label */
$ext_id = LABEL_BASE_INDEX - 1 - $id;
db_query($link, "DELETE FROM ttrss_access_keys WHERE
db_query("DELETE FROM ttrss_access_keys WHERE
feed_id = '$ext_id' AND owner_uid = $owner_uid");
/* Remove cached data */
db_query($link, "UPDATE ttrss_user_entries SET label_cache = ''
db_query("UPDATE ttrss_user_entries SET label_cache = ''
WHERE label_cache LIKE '%$caption%' AND owner_uid = " . $owner_uid);
}
db_query($link, "COMMIT");
db_query("COMMIT");
}
function label_create($link, $caption, $fg_color = '', $bg_color = '', $owner_uid = false) {
function label_create($caption, $fg_color = '', $bg_color = '', $owner_uid = false) {
if (!$owner_uid) $owner_uid = $_SESSION['uid'];
db_query($link, "BEGIN");
db_query("BEGIN");
$result = false;
$result = db_query($link, "SELECT id FROM ttrss_labels2
$result = db_query("SELECT id FROM ttrss_labels2
WHERE caption = '$caption' AND owner_uid = $owner_uid");
if (db_num_rows($result) == 0) {
$result = db_query($link,
$result = db_query(
"INSERT INTO ttrss_labels2 (caption,owner_uid,fg_color,bg_color)
VALUES ('$caption', '$owner_uid', '$fg_color', '$bg_color')");
$result = db_affected_rows($link, $result) != 0;
$result = db_affected_rows($result) != 0;
}
db_query($link, "COMMIT");
db_query("COMMIT");
return $result;
}

View File

@@ -188,6 +188,8 @@ function bwLimitChange(elem) {
value="<?php echo $_SESSION["fake_login"] ?>" />
</div>
<?php if (strpos(PLUGINS, "auth_internal") !== FALSE) { ?>
<div class="row">
<label><?php echo __("Password:") ?></label>
<input type="password" name="password" required="1"
@@ -197,13 +199,7 @@ function bwLimitChange(elem) {
<a class='forgotpass' href="public.php?op=forgotpass"><?php echo __("I forgot my password") ?></a>
</div>
<div class="row">
<label><?php echo __("Language:") ?></label>
<?php
print_select_hash("language", $_COOKIE["ttrss_lang"], get_translations(),
"style='width : 220px; margin : 0px' dojoType='dijit.form.Select'");
?>
</div>
<?php } ?>
<div class="row">
<label><?php echo __("Profile:") ?></label>
@@ -218,7 +214,11 @@ function bwLimitChange(elem) {
<label>&nbsp;</label>
<input dojoType="dijit.form.CheckBox" name="bw_limit" id="bw_limit" type="checkbox"
onchange="bwLimitChange(this)">
<label style='display : inline' for="bw_limit"><?php echo __("Use less traffic") ?></label>
<label id="bw_limit_label" style='display : inline' for="bw_limit"><?php echo __("Use less traffic") ?></label>
</div>
<div dojoType="dijit.Tooltip" connectId="bw_limit_label" position="below">
<?php echo __("Does not display images in articles, reduces automatic refreshes."); ?>
</div>
<?php if (SESSION_COOKIE_LIFETIME > 0) { ?>

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@
return $url_path;
}
function initial_sanity_check($link) {
function initial_sanity_check() {
$errors = array();
@@ -55,6 +55,10 @@
array_push($errors, "Image cache is not writable (chmod -R 777 ".CACHE_DIR."/images)");
}
if (!is_writable(CACHE_DIR . "/upload")) {
array_push($errors, "Upload cache is not writable (chmod -R 777 ".CACHE_DIR."/upload)");
}
if (!is_writable(CACHE_DIR . "/export")) {
array_push($errors, "Data export cache is not writable (chmod -R 777 ".CACHE_DIR."/export)");
}
@@ -63,6 +67,14 @@
array_push($errors, "Javascript cache is not writable (chmod -R 777 ".CACHE_DIR."/js)");
}
if (strlen(FEED_CRYPT_KEY) > 0 && strlen(FEED_CRYPT_KEY) != 24) {
array_push($errors, "FEED_CRYPT_KEY should be exactly 24 characters in length.");
}
if (strlen(FEED_CRYPT_KEY) > 0 && !function_exists("mcrypt_decrypt")) {
array_push($errors, "FEED_CRYPT_KEY requires mcrypt functions which are not found.");
}
if (GENERATED_CONFIG_CHECK != EXPECTED_CONFIG_VERSION) {
array_push($errors,
"Configuration option checker sanity_config.php is outdated, please recreate it using ./utils/regen_config_checks.sh");
@@ -76,14 +88,10 @@
}
if (SINGLE_USER_MODE) {
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$result = db_query("SELECT id FROM ttrss_users WHERE id = 1");
if ($link) {
$result = db_query($link, "SELECT id FROM ttrss_users WHERE id = 1");
if (db_num_rows($result) != 1) {
array_push($errors, "SINGLE_USER_MODE is enabled in config.php but default admin account is not found.");
}
if (db_num_rows($result) != 1) {
array_push($errors, "SINGLE_USER_MODE is enabled in config.php but default admin account is not found.");
}
}
@@ -102,10 +110,6 @@
array_push($errors, "LOCK_DIRECTORY defined in config.php is not writable (chmod -R 777 ".LOCK_DIRECTORY.").\n");
}
if (ini_get("open_basedir")) {
array_push($errors, "PHP configuration option open_basedir is not supported. Please disable this in PHP settings file (php.ini).");
}
if (!function_exists("curl_init") && !ini_get("allow_url_fopen")) {
array_push($errors, "PHP configuration option allow_url_fopen is disabled, and CURL functions are not present. Either enable allow_url_fopen or install PHP extension for CURL.");
}
@@ -114,7 +118,7 @@
array_push($errors, "PHP support for JSON is required, but was not found.");
}
if (DB_TYPE == "mysql" && !function_exists("mysql_connect")) {
if (DB_TYPE == "mysql" && !function_exists("mysql_connect") && !function_exists("mysqli_connect")) {
array_push($errors, "PHP support for MySQL is required for configured DB_TYPE in config.php.");
}
@@ -194,6 +198,6 @@
}
}
initial_sanity_check($link);
initial_sanity_check();
?>

View File

@@ -1,3 +1,3 @@
<?php # This file has been generated at: Mon Apr 1 18:30:54 IDT 2013
<?php # This file has been generated at: Fri Apr 19 09:22:33 MSK 2013
define('GENERATED_CONFIG_CHECK', 26);
$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', '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_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_HOST', 'SMTP_PORT', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', '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', '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', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'LOG_DESTINATION', 'CONFIG_VERSION'); ?>

View File

@@ -2,7 +2,9 @@
// Original from http://www.daniweb.com/code/snippet43.html
require_once "config.php";
require_once "db.php";
require_once "classes/db.php";
require_once "autoload.php";
require_once "errorhandler.php";
require_once "lib/accept-to-gettext.php";
require_once "lib/gettext/gettext.inc";
require_once "version.php";
@@ -21,14 +23,12 @@
ini_set("session.gc_maxlifetime", $session_expire);
ini_set("session.cookie_lifetime", min(0, SESSION_COOKIE_LIFETIME));
global $session_connection;
function session_get_schema_version($link, $nocache = false) {
function session_get_schema_version($nocache = false) {
global $schema_version;
if (!$schema_version) {
$result = db_query($link, "SELECT schema_version FROM ttrss_version");
$version = db_fetch_result($result, 0, "schema_version");
$result = Db::get()->query("SELECT schema_version FROM ttrss_version");
$version = Db::get()->fetch_result($result, 0, "schema_version");
$schema_version = $version;
return $version;
} else {
@@ -36,11 +36,10 @@
}
}
function validate_session($link) {
function validate_session() {
if (SINGLE_USER_MODE) return true;
if (!$link) return false;
if (VERSION != $_SESSION["version"]) return false;
if (VERSION_STATIC != $_SESSION["version"]) return false;
$check_ip = $_SESSION['ip_address'];
@@ -63,21 +62,21 @@
return false;
}
if ($_SESSION["ref_schema_version"] != session_get_schema_version($link, true))
if ($_SESSION["ref_schema_version"] != session_get_schema_version(true))
return false;
if (sha1($_SERVER['HTTP_USER_AGENT']) != $_SESSION["user_agent"])
return false;
if ($_SESSION["uid"]) {
$result = db_query($link,
$result = Db::get()->query(
"SELECT pwd_hash FROM ttrss_users WHERE id = '".$_SESSION["uid"]."'");
// user not found
if (db_num_rows($result) == 0) {
if (Db::get()->num_rows($result) == 0) {
return false;
} else {
$pwd_hash = db_fetch_result($result, 0, "pwd_hash");
$pwd_hash = Db::get()->fetch_result($result, 0, "pwd_hash");
if ($pwd_hash != $_SESSION["pwd_hash"]) {
return false;
@@ -85,101 +84,63 @@
}
}
/* if ($_SESSION["cookie_lifetime"] && $_SESSION["uid"]) {
//print_r($_SESSION);
if (time() > $_SESSION["cookie_lifetime"]) {
return false;
}
} */
return true;
}
function ttrss_open ($s, $n) {
global $session_connection;
$session_connection = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
return true;
}
function ttrss_read ($id){
global $session_expire;
global $session_connection,$session_read;
$res = Db::get()->query("SELECT data FROM ttrss_sessions WHERE id='$id'");
$query = "SELECT data FROM ttrss_sessions WHERE id='$id'";
if (Db::get()->num_rows($res) != 1) {
$res = db_query($session_connection, $query);
$expire = time() + $session_expire;
Db::get()->query("INSERT INTO ttrss_sessions (id, data, expire)
VALUES ('$id', '', '$expire')");
if (db_num_rows($res) != 1) {
return "";
} else {
$session_read = db_fetch_assoc($res);
$session_read["data"] = base64_decode($session_read["data"]);
return $session_read["data"];
return base64_decode(Db::get()->fetch_result($res, 0, "data"));
}
}
function ttrss_write ($id, $data) {
global $session_expire;
if (! $data) {
return false;
}
global $session_connection, $session_read, $session_expire;
$data = base64_encode($data);
$expire = time() + $session_expire;
$data = db_escape_string($session_connection, base64_encode($data), false);
Db::get()->query("UPDATE ttrss_sessions SET data='$data', expire='$expire' WHERE id='$id'");
if ($session_read) {
$query = "UPDATE ttrss_sessions SET data='$data',
expire='$expire' WHERE id='$id'";
} else {
$query = "INSERT INTO ttrss_sessions (id, data, expire)
VALUES ('$id', '$data', '$expire')";
}
db_query($session_connection, $query);
return true;
}
function ttrss_close () {
global $session_connection;
//db_close($session_connection);
return true;
}
function ttrss_destroy ($id) {
global $session_connection;
$query = "DELETE FROM ttrss_sessions WHERE id = '$id'";
db_query($session_connection, $query);
function ttrss_destroy($id) {
Db::get()->query("DELETE FROM ttrss_sessions WHERE id = '$id'");
return true;
}
function ttrss_gc ($expire) {
global $session_connection;
$query = "DELETE FROM ttrss_sessions WHERE expire < " . time();
db_query($session_connection, $query);
Db::get()->query("DELETE FROM ttrss_sessions WHERE expire < " . time());
}
if (!SINGLE_USER_MODE /* && DB_TYPE == "pgsql" */) {
session_set_save_handler("ttrss_open",
"ttrss_close", "ttrss_read", "ttrss_write",
"ttrss_destroy", "ttrss_gc");
register_shutdown_function('session_write_close');
}
if (!defined('NO_SESSION_AUTOSTART')) {

View File

@@ -1,3 +1,19 @@
<?php
define('VERSION', "1.7.8");
define('VERSION_STATIC', '1.7.8');
function get_version() {
date_default_timezone_set('UTC');
$root_dir = dirname(dirname(__FILE__));
if (is_dir("$root_dir/.git") && file_exists("$root_dir/.git/ORIG_HEAD")) {
$suffix = substr(trim(file_get_contents("$root_dir/.git/ORIG_HEAD")), 0, 7);
return VERSION_STATIC . ".$suffix";
} else {
return VERSION_STATIC;
}
}
define('VERSION', get_version());
?>

View File

@@ -19,6 +19,7 @@
set_include_path(dirname(__FILE__) ."/include" . PATH_SEPARATOR .
get_include_path());
require_once "autoload.php";
require_once "sessions.php";
require_once "functions.php";
require_once "sanity_check.php";
@@ -29,28 +30,22 @@
$mobile = new Mobile_Detect();
$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if (!init_connection($link)) return;
global $pluginhost;
if (!init_plugins()) return;
if (!$_REQUEST['mobile']) {
if ($mobile->isTablet() && $pluginhost->get_plugin("digest")) {
if ($mobile->isTablet() && PluginHost::getInstance()->get_plugin("digest")) {
header('Location: backend.php?op=digest');
exit;
} else if ($mobile->isMobile() && $pluginhost->get_plugin("mobile")) {
} else if ($mobile->isMobile() && PluginHost::getInstance()->get_plugin("mobile")) {
header('Location: backend.php?op=mobile');
exit;
} else if ($mobile->isMobile() && $pluginhost->get_plugin("digest")) {
} else if ($mobile->isMobile() && PluginHost::getInstance()->get_plugin("digest")) {
header('Location: backend.php?op=digest');
exit;
}
}
login_sequence($link);
no_cache_incantation();
login_sequence();
header('Content-Type: text/html; charset=utf-8');
@@ -61,23 +56,23 @@
<head>
<title>Tiny Tiny RSS</title>
<?php echo stylesheet_tag("lib/dijit/themes/claro/claro.css"); ?>
<?php echo stylesheet_tag("tt-rss.css"); ?>
<?php echo stylesheet_tag("cdm.css"); ?>
<?php stylesheet_tag("lib/dijit/themes/claro/claro.css"); ?>
<?php stylesheet_tag("tt-rss.css"); ?>
<?php stylesheet_tag("cdm.css"); ?>
<?php if ($_SESSION["uid"]) {
$theme = get_pref($link, "USER_CSS_THEME", $_SESSION["uid"], false);
$theme = get_pref( "USER_CSS_THEME", $_SESSION["uid"], false);
if ($theme) {
echo stylesheet_tag("themes/$theme");
stylesheet_tag("themes/$theme");
}
}
?>
<?php print_user_stylesheet($link) ?>
<?php print_user_stylesheet() ?>
<style type="text/css">
<?php
foreach ($pluginhost->get_plugins() as $n => $p) {
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
if (method_exists($p, "get_css")) {
echo $p->get_css();
}
@@ -96,7 +91,7 @@
"lib/dojo/tt-rss-layer.js",
"errors.php?mode=js") as $jsfile) {
echo javascript_tag($jsfile);
javascript_tag($jsfile);
} ?>
@@ -105,11 +100,9 @@
require 'lib/jshrink/Minifier.php';
print get_minified_js(array("tt-rss",
"functions", "feedlist", "viewfeed", "FeedTree"));
"functions", "feedlist", "viewfeed", "FeedTree", "PluginHost"));
global $pluginhost;
foreach ($pluginhost->get_plugins() as $n => $p) {
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
if (method_exists($p, "get_js")) {
echo JShrink\Minifier::minify($p->get_js());
}
@@ -140,7 +133,7 @@
</div>
</div>
<div id="notify" class="notify"><span id="notify_body">&nbsp;</span></div>
<div id="notify" class="notify" style="display : none"></div>
<div id="cmdline" style="display : none"></div>
<div id="headlines-tmp" style="display : none"></div>
@@ -208,8 +201,7 @@
<div class="actionChooser">
<?php
global $pluginhost;
foreach ($pluginhost->get_hooks($pluginhost::HOOK_TOOLBAR_BUTTON) as $p) {
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_TOOLBAR_BUTTON) as $p) {
echo $p->hook_toolbar_button();
}
?>
@@ -241,18 +233,14 @@
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcCatchupAll')"><?php echo __('Mark as read') ?></div>
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcShowOnlyUnread')"><?php echo __('(Un)hide read feeds') ?></div>
<div dojoType="dijit.MenuItem" disabled="1"><?php echo __('Other actions:') ?></div>
<!-- <?php if ($pluginhost->get_plugin("digest")) { ?>
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcDigest')"><?php echo __('Switch to digest...') ?></div>
<?php } ?> -->
<!-- <div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcTagCloud')"><?php echo __('Show tag cloud...') ?></div> -->
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcToggleWidescreen')"><?php echo __('Toggle widescreen mode') ?></div>
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcToggleWidescreen')"><?php echo __('Toggle widescreen mode') ?></div>
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcTagSelect')"><?php echo __('Select by tags...') ?></div>
<!-- <div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcAddLabel')"><?php echo __('Create label...') ?></div>
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcAddFilter')"><?php echo __('Create filter...') ?></div> -->
<div dojoType="dijit.MenuItem" onclick="quickMenuGo('qmcHKhelp')"><?php echo __('Keyboard shortcuts help') ?></div>
<?php
foreach ($pluginhost->get_hooks($pluginhost::HOOK_ACTION_ITEM) as $p) {
foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_ACTION_ITEM) as $p) {
echo $p->hook_action_item();
}
?>
@@ -286,7 +274,5 @@
</div>
</div>
<?php db_close($link); ?>
</body>
</html>

View File

@@ -10,6 +10,25 @@
<body>
<?php
function make_password($length = 8) {
$password = "";
$possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ*%+^";
$i = 0;
while ($i < $length) {
$char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
if (!strstr($password, $char)) {
$password .= $char;
$i++;
}
}
return $password;
}
function sanity_check($db_type) {
$errors = array();
@@ -17,10 +36,6 @@
array_push($errors, "PHP version 5.3.0 or newer required.");
}
if (ini_get("open_basedir")) {
array_push($errors, "PHP configuration option open_basedir is not supported. Please disable this in PHP settings file (php.ini).");
}
if (!function_exists("curl_init") && !ini_get("allow_url_fopen")) {
array_push($errors, "PHP configuration option allow_url_fopen is disabled, and CURL functions are not present. Either enable allow_url_fopen or install PHP extension for CURL.");
}
@@ -29,7 +44,7 @@
array_push($errors, "PHP support for JSON is required, but was not found.");
}
if ($db_type == "mysql" && !function_exists("mysql_connect")) {
if ($db_type == "mysql" && !function_exists("mysql_connect") && !function_exists("mysqli_connect")) {
array_push($errors, "PHP support for MySQL is required for configured $db_type in config.php.");
}
@@ -65,15 +80,16 @@
}
function print_error($msg) {
print "<div class='error'><img src='../images/sign_excl.svg'> $msg</div>";
print "<div class='error'><span><img src='../images/sign_excl.svg'></span>
<span>$msg</span></div>";
}
function print_notice($msg) {
print "<div class=\"notice\">
<img src=\"../images/sign_info.svg\">$msg</div>";
<span><img src=\"../images/sign_info.svg\"></span><span>$msg</span></div>";
}
function db_connect($host, $user, $pass, $db, $type) {
function db_connect($host, $user, $pass, $db, $type, $port = false) {
if ($type == "pgsql") {
$string = "dbname=$db user=$user";
@@ -86,8 +102,8 @@
$string .= " host=$host";
}
if (defined('DB_PORT')) {
$string = "$string port=" . DB_PORT;
if ($port) {
$string = "$string port=" . $port;
}
$link = pg_connect($string);
@@ -95,10 +111,18 @@
return $link;
} else if ($type == "mysql") {
$link = mysql_connect($host, $user, $pass);
if ($link) {
$result = mysql_select_db($db, $link);
if ($result) return $link;
if (function_exists("mysqli_connect")) {
if ($port)
return mysqli_connect($host, $user, $pass, $db, $port);
else
return mysqli_connect($host, $user, $pass, $db);
} else {
$link = mysql_connect($host, $user, $pass);
if ($link) {
$result = mysql_select_db($db, $link);
if ($result) return $link;
}
}
}
}
@@ -112,6 +136,12 @@
$finished = false;
if (function_exists("mcrypt_decrypt")) {
$crypt_key = make_password(24);
} else {
$crypt_key = "";
}
foreach ($data as $line) {
if (preg_match("/define\('DB_TYPE'/", $line)) {
$rv .= "\tdefine('DB_TYPE', '$DB_TYPE');\n";
@@ -127,6 +157,8 @@
$rv .= "\tdefine('DB_PORT', '$DB_PORT');\n";
} else if (preg_match("/define\('SELF_URL_PATH'/", $line)) {
$rv .= "\tdefine('SELF_URL_PATH', '$SELF_URL_PATH');\n";
} else if (preg_match("/define\('FEED_CRYPT_KEY'/", $line)) {
$rv .= "\tdefine('FEED_CRYPT_KEY', '$crypt_key');\n";
} else if (!$finished) {
$rv .= "$line\n";
}
@@ -150,7 +182,12 @@
}
return $result;
} else if ($type == "mysql") {
$result = mysql_query($query, $link);
if (function_exists("mysqli_connect")) {
$result = mysqli_query($link, $query);
} else {
$result = mysql_query($query, $link);
}
if (!$result) {
$query = htmlspecialchars($query);
if ($die_on_error) {
@@ -231,17 +268,19 @@
<fieldset>
<label>Database name</label>
<input name="DB_NAME" size="20" value="<?php echo $DB_NAME ?>"/>
<input required name="DB_NAME" size="20" value="<?php echo $DB_NAME ?>"/>
</fieldset>
<fieldset>
<label>Host name</label>
<input name="DB_HOST" placeholder="if needed" size="20" value="<?php echo $DB_HOST ?>"/>
<input name="DB_HOST" size="20" value="<?php echo $DB_HOST ?>"/>
<span class="hint">If needed</span>
</fieldset>
<fieldset>
<label>Port</label>
<input name="DB_PORT" type="number" placeholder="if needed, PgSQL only" size="20" value="<?php echo $DB_PORT ?>"/>
<input name="DB_PORT" type="number" size="20" value="<?php echo $DB_PORT ?>"/>
<span class="hint">Usually 3306 for MySQL or 5432 for PostgreSQL</span>
</fieldset>
<h2>Other settings</h2>
@@ -304,7 +343,7 @@
<h2>Checking database</h2>
<?php
$link = db_connect($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME, $DB_TYPE);
$link = db_connect($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME, $DB_TYPE, $DB_PORT);
if (!$link) {
print_error("Unable to connect to database using specified parameters.");

View File

@@ -100,7 +100,7 @@ dojo.declare("fox.FeedTree", dijit.Tree, {
_createTreeNode: function(args) {
var tnode = new dijit._TreeNode(args);
if (args.item.icon)
if (args.item.icon && args.item.icon[0])
tnode.iconNode.src = args.item.icon[0];
var id = args.item.id[0];

34
js/PluginHost.js Normal file
View File

@@ -0,0 +1,34 @@
// based on http://www.velvetcache.org/2010/08/19/a-simple-javascript-hooks-system
var PluginHost = {
HOOK_ARTICLE_RENDERED: 1,
HOOK_ARTICLE_RENDERED_CDM: 2,
HOOK_ARTICLE_SET_ACTIVE: 3,
HOOK_FEED_SET_ACTIVE: 4,
HOOK_FEED_LOADED: 5,
HOOK_ARTICLE_EXPANDED: 6,
HOOK_ARTICLE_COLLAPSED: 7,
HOOK_PARAMS_LOADED: 8,
HOOK_RUNTIME_INFO_LOADED: 9,
hooks: [],
register: function (name, callback) {
if (typeof(this.hooks[name]) == 'undefined')
this.hooks[name] = [];
this.hooks[name].push(callback);
},
run: function (name, args) {
console.warn('PluginHost::run ' + name);
if (typeof(this.hooks[name]) != 'undefined')
for (i = 0; i < this.hooks[name].length; i++)
if (!this.hooks[name][i](args)) break;
}
};
/* PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED,
function (args) { console.log('ARTICLE_RENDERED: ' + args); return true; });
PluginHost.register(PluginHost.HOOK_ARTICLE_RENDERED_CDM,
function (args) { console.log('ARTICLE_RENDERED_CDM: ' + args); return true; }); */

View File

@@ -139,6 +139,7 @@ function viewfeed(feed, method, is_cat, offset, background, infscroll_req) {
onComplete: function(transport) {
setFeedExpandoIcon(feed, is_cat, 'images/blank_icon.gif');
headlines_callback2(transport, offset, background, infscroll_req);
PluginHost.run(PluginHost.HOOK_FEED_LOADED, [feed, is_cat]);
} });
} catch (e) {
@@ -150,6 +151,8 @@ function feedlist_init() {
try {
console.log("in feedlist init");
loading_set_progress(50);
document.onkeydown = hotkey_handler;
setTimeout("hotkey_prefix_timeout()", 5*1000);

View File

@@ -1,8 +1,8 @@
var notify_silent = false;
var loading_progress = 0;
var sanity_check_done = false;
var init_params = {};
var _label_base_index = -1024;
var notify_hide_timerid = false;
Ajax.Base.prototype.initialize = Ajax.Base.prototype.initialize.wrap(
function (callOriginal, options) {
@@ -50,6 +50,21 @@ function exception_error(location, e, ext_info) {
}
}
try {
new Ajax.Request("backend.php", {
parameters: {op: "rpc", method: "log", logmsg: msg},
onComplete: function (transport) {
console.log(transport.responseText);
} });
} catch (eii) {
console.log("Exception while trying to log the error.");
console.log(eii);
}
msg += "<p>"+ __("The error will be reported to the configured log destination.") +
"</p>";
var content = "<div class=\"fatalError\">" +
"<pre>" + msg + "</pre>";
@@ -106,7 +121,28 @@ function exception_error(location, e, ext_info) {
dialog.show();
} catch (e) {
} catch (ei) {
console.log("Exception while trying to report an exception. Oh boy.");
console.log(ei);
console.log("Original exception:");
console.log(e);
msg += "\n\nAdditional exception caught while trying to show the error dialog.\n\n" + format_exception_error('exception_error', ei);
try {
new Ajax.Request("backend.php", {
parameters: {op: "rpc", method: "log", logmsg: msg},
onComplete: function (transport) {
console.log(transport.responseText);
} });
} catch (eii) {
console.log("Third exception while trying to log the error! Seriously?");
console.log(eii);
}
msg += "\n\nThe error will be reported to the configured log destination.";
alert(msg);
}
@@ -147,42 +183,28 @@ function param_unescape(arg) {
return unescape(arg);
}
var notify_hide_timerid = false;
function hide_notify() {
var n = $("notify");
if (n) {
n.style.display = "none";
}
}
function notify_silent_next() {
notify_silent = true;
Element.hide('notify');
}
function notify_real(msg, no_hide, n_type) {
if (notify_silent) {
notify_silent = false;
return;
}
var n = $("notify");
var nb = $("notify_body");
if (!n || !nb) return;
if (!n) return;
if (notify_hide_timerid) {
window.clearTimeout(notify_hide_timerid);
}
if (msg == "") {
if (n.style.display == "block") {
if (Element.visible(n)) {
notify_hide_timerid = window.setTimeout("hide_notify()", 0);
}
return;
} else {
n.style.display = "block";
Element.show(n);
}
/* types:
@@ -194,33 +216,31 @@ function notify_real(msg, no_hide, n_type) {
*/
msg = __(msg);
msg = "<span class=\"msg\"> " + __(msg) + "</span>";
if (n_type == 1) {
n.className = "notify";
} else if (n_type == 2) {
n.className = "notify progress";
msg = "<img src='images/indicator_white.gif'> " + msg;
msg = "<span><img src='images/indicator_white.gif'></span>" + msg;
no_hide = true;
} else if (n_type == 3) {
n.className = "notify error";
msg = "<img src='images/sign_excl.svg'> " + msg;
msg = "<span><img src='images/sign_excl.svg'></span>" + msg;
} else if (n_type == 4) {
n.className = "notify info";
msg = "<img src='images/sign_info.svg'> " + msg;
}
if (no_hide) {
msg += " <span>(<a href='#' onclick=\"notify('')\">" +
__("close") + "</a>)</span>";
msg = "<span><img src='images/sign_info.svg'></span>" + msg;
}
msg += " <span><img src=\"images/close_notify.svg\" class=\"close\" title=\"" +
__("Click to close") + "\" onclick=\"notify('')\"></span>";
// msg = "<img src='images/live_com_loading.gif'> " + msg;
nb.innerHTML = msg;
n.innerHTML = msg;
if (!no_hide) {
notify_hide_timerid = window.setTimeout("hide_notify()", 3000);
notify_hide_timerid = window.setTimeout("hide_notify()", 5*1000);
}
}
@@ -368,6 +388,9 @@ function toggleSelectRow2(sender, row, is_cdm) {
row.addClassName('Selected');
else
row.removeClassName('Selected');
if (typeof updateSelectedPrompt != undefined)
updateSelectedPrompt();
}
@@ -379,6 +402,9 @@ function toggleSelectRow(sender, row) {
row.addClassName('Selected');
else
row.removeClassName('Selected');
if (typeof updateSelectedPrompt != undefined)
updateSelectedPrompt();
}
function checkboxToggleElement(elem, id) {
@@ -810,7 +836,7 @@ function quickAddFeed() {
notify('');
Element.hide("feed_add_spinner");
console.log("GOT RC: " + rc);
console.log(rc);
switch (parseInt(rc['code'])) {
case 1:
@@ -826,39 +852,6 @@ function quickAddFeed() {
alert(__("Specified URL doesn't seem to contain any feeds."));
break;
case 4:
/* notify_progress("Searching for feed urls...", true);
new Ajax.Request("backend.php", {
parameters: 'op=rpc&method=extractfeedurls&url=' + param_escape(feed_url),
onComplete: function(transport, dialog, feed_url) {
notify('');
var reply = JSON.parse(transport.responseText);
var feeds = reply['urls'];
console.log(transport.responseText);
var select = dijit.byId("feedDlg_feedContainerSelect");
while (select.getOptions().length > 0)
select.removeOption(0);
var count = 0;
for (var feedUrl in feeds) {
select.addOption({value: feedUrl, label: feeds[feedUrl]});
count++;
}
// if (count > 5) count = 5;
// select.size = count;
Effect.Appear('feedDlg_feedsContainer', {duration : 0.5});
}
});
break; */
feeds = rc['feeds'];
var select = dijit.byId("feedDlg_feedContainerSelect");
@@ -866,6 +859,8 @@ function quickAddFeed() {
while (select.getOptions().length > 0)
select.removeOption(0);
select.addOption({value: '', label: __("Expand to select feed")});
var count = 0;
for (var feedUrl in feeds) {
select.addOption({value: feedUrl, label: feeds[feedUrl]});
@@ -879,6 +874,11 @@ function quickAddFeed() {
alert(__("Couldn't download the specified URL: %s").
replace("%s", rc['message']));
break;
case 6:
alert(__("XML validation failed: %s").
replace("%s", rc['message']));
break;
break;
case 0:
alert(__("You are already subscribed to this feed."));
break;
@@ -1269,16 +1269,17 @@ function backend_sanity_check_callback(transport) {
if (params) {
console.log('reading init-params...');
if (params) {
for (k in params) {
var v = params[k];
console.log("IP: " + k + " => " + v);
for (k in params) {
var v = params[k];
console.log("IP: " + k + " => " + v);
if (k == "label_base_index") _label_base_index = parseInt(v);
}
if (k == "label_base_index") _label_base_index = parseInt(v);
}
init_params = params;
// PluginHost might not be available on non-index pages
window.PluginHost && PluginHost.run(PluginHost.HOOK_PARAMS_LOADED, init_params);
}
sanity_check_done = true;

0
js/index.html Normal file
View File

View File

@@ -852,6 +852,15 @@ function updatePrefsList() {
} });
}
function updateSystemList() {
new Ajax.Request("backend.php", {
parameters: "?op=pref-system",
onComplete: function(transport) {
dijit.byId('systemConfigTab').attr('content', transport.responseText);
notify("");
} });
}
function selectTab(id, noupdate, method) {
try {
if (!noupdate) {
@@ -867,6 +876,8 @@ function selectTab(id, noupdate, method) {
updatePrefsList();
} else if (id == "userConfig") {
updateUsersList();
} else if (id == "systemConfig") {
updateSystemList();
}
var tab = dijit.byId(id + "Tab");
@@ -951,8 +962,11 @@ function init() {
dojo.addOnLoad(function() {
loading_set_progress(50);
var clientTzOffset = new Date().getTimezoneOffset() * 60;
new Ajax.Request("backend.php", {
parameters: {op: "rpc", method: "sanityCheck"},
parameters: {op: "rpc", method: "sanityCheck",
clientTzOffset: clientTzOffset },
onComplete: function(transport) {
backend_sanity_check_callback(transport);
} });
@@ -1596,21 +1610,6 @@ function resetCatOrder() {
}
}
function toggleHiddenFeedCats() {
try {
notify_progress("Loading, please wait...");
new Ajax.Request("backend.php", {
parameters: "?op=pref-feeds&method=togglehiddenfeedcats",
onComplete: function(transport) {
updateFeedList();
} });
} catch (e) {
exception_error("toggleHiddenFeedCats");
}
}
function editCat(id, item, event) {
try {
var new_name = prompt(__('Rename category to:'), item.name);
@@ -1819,3 +1818,21 @@ function clearPluginData(name) {
exception_error("clearPluginData", e);
}
}
function clearSqlLog() {
if (confirm(__("Clear all messages in the error log?"))) {
notify_progress("Loading, please wait...");
var query = "?op=pref-system&method=clearLog";
new Ajax.Request("backend.php", {
parameters: query,
onComplete: function(transport) {
updateSystemList();
} });
}
}

View File

@@ -40,6 +40,8 @@ function setActiveFeedId(id, is_cat) {
$("headlines-frame").setAttribute("is-cat", is_cat ? 1 : 0);
selectFeed(id, is_cat);
PluginHost.run(PluginHost.HOOK_FEED_SET_ACTIVE, _active_article_id);
} catch (e) {
exception_error("setActiveFeedId", e);
}
@@ -134,7 +136,8 @@ function catchupAllFeeds() {
new Ajax.Request("backend.php", {
parameters: query_str,
onComplete: function(transport) {
feedlist_callback2(transport);
request_counters(true);
viewCurrentFeed();
} });
global_unread = 0;
@@ -246,13 +249,19 @@ function init() {
if (!genericSanityCheck())
return false;
loading_set_progress(20);
loading_set_progress(30);
var hasAudio = !!((myAudioTag = document.createElement('audio')).canPlayType);
var a = document.createElement('audio');
var hasAudio = !!a.canPlayType;
var hasSandbox = "sandbox" in document.createElement("iframe");
var hasMp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
var clientTzOffset = new Date().getTimezoneOffset() * 60;
new Ajax.Request("backend.php", {
parameters: {op: "rpc", method: "sanityCheck", hasAudio: hasAudio,
hasMp3: hasMp3,
clientTzOffset: clientTzOffset,
hasSandbox: hasSandbox},
onComplete: function(transport) {
backend_sanity_check_callback(transport);
@@ -302,7 +311,7 @@ function init() {
var id = getActiveArticleId();
var elem = $("CICD-"+id);
if(elem.visible()) {
cdmUnexpandArticle(null, id);
cdmCollapseArticle(null, id, false);
}
else {
cdmExpandArticle(id);
@@ -323,7 +332,7 @@ function init() {
hotkey_actions["edit_tags"] = function() {
var id = getActiveArticleId();
if (id) {
editArticleTags(id, getActiveFeedId(), isCdmMode());
editArticleTags(id);
};
}
hotkey_actions["dismiss_selected"] = function() {
@@ -564,7 +573,7 @@ function init_second_stage() {
setActiveFeedId(hash_feed_id, hash_feed_is_cat);
}
loading_set_progress(30);
loading_set_progress(50);
// can't use cache_clear() here because viewfeed might not have initialized yet
if ('sessionStorage' in window && window['sessionStorage'] !== null)
@@ -744,6 +753,8 @@ function parse_runtime_info(data) {
init_params[k] = v;
notify('');
}
PluginHost.run(PluginHost.HOOK_RUNTIME_INFO_LOADED, data);
}
function collapse_feedlist() {
@@ -983,7 +994,7 @@ function handle_rpc_json(transport, scheduled_call) {
if (counters)
parse_counters(counters, scheduled_call);
var runtime_info = reply['runtime-info'];;
var runtime_info = reply['runtime-info'];
if (runtime_info)
parse_runtime_info(runtime_info);
@@ -1072,7 +1083,7 @@ function hash_get(key) {
kv = window.location.hash.substring(1).toQueryParams();
return kv[key];
} catch (e) {
exception_error("hash_set", e);
exception_error("hash_get", e);
}
}
function hash_set(key, value) {

View File

@@ -20,8 +20,6 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
try {
handle_rpc_json(transport);
loading_set_progress(25);
console.log("headlines_callback2 [offset=" + offset + "] B:" + background + " I:" + infscroll_req);
var is_cat = false;
@@ -43,9 +41,7 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
if (background) {
var content = reply['headlines']['content'];
if (getInitParam("cdm_auto_catchup") == 1) {
content = content + "<div id='headlines-spacer'></div>";
}
content = content + "<div id='headlines-spacer'></div>";
return;
}
@@ -93,11 +89,9 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
}
});
if (getInitParam("cdm_auto_catchup") == 1) {
var hsp = $("headlines-spacer");
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
dijit.byId('headlines-frame').domNode.appendChild(hsp);
}
var hsp = $("headlines-spacer");
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
dijit.byId('headlines-frame').domNode.appendChild(hsp);
initHeadlinesMenu();
@@ -140,8 +134,6 @@ function headlines_callback2(transport, offset, background, infscroll_req) {
if (!hsp) hsp = new Element("DIV", {"id": "headlines-spacer"});
fixHeadlinesOrder(getLoadedArticleIds());
if (getInitParam("cdm_auto_catchup") == 1) {
c.domNode.appendChild(hsp);
}
@@ -232,6 +224,8 @@ function render_article(article) {
c.domNode.scrollTop = 0;
} catch (e) { };
PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED, article);
c.attr('content', article);
correctHeadlinesOffset(getActiveArticleId());
@@ -639,11 +633,33 @@ function toggleSelected(id, force_on) {
if (cb) cb.attr("checked", true);
}
}
updateSelectedPrompt();
} catch (e) {
exception_error("toggleSelected", e);
}
}
function updateSelectedPrompt() {
try {
var count = getSelectedArticleIds2().size();
var elem = $("selected_prompt");
if (elem) {
elem.innerHTML = ngettext("%d article selected",
"%d articles selected", count).replace("%d", count);
if (count > 0)
Element.show(elem);
else
Element.hide(elem);
}
} catch (e) {
exception_error("updateSelectedPrompt", e);
}
}
function toggleUnread_afh(effect) {
try {
@@ -960,6 +976,8 @@ function selectArticles(mode) {
}
});
updateSelectedPrompt();
} catch (e) {
exception_error("selectArticles", e);
}
@@ -1169,6 +1187,7 @@ function cdmScrollToArticleId(id, force) {
function setActiveArticleId(id) {
_active_article_id = id;
PluginHost.run(PluginHost.HOOK_ARTICLE_SET_ACTIVE, _active_article_id);
}
function getActiveArticleId() {
@@ -1195,6 +1214,8 @@ function unpackVisibleHeadlines() {
var cencw = $("CENCW-" + child.id.replace("RROW-", ""));
if (cencw) {
PluginHost.run(PluginHost.HOOK_ARTICLE_RENDERED_CDM, child);
cencw.innerHTML = htmlspecialchars_decode(cencw.innerHTML);
cencw.setAttribute('id', '');
Element.show(cencw);
@@ -1370,8 +1391,10 @@ function catchupRelativeToArticle(below, id) {
}
}
function cdmCollapseArticle(event, id) {
function cdmCollapseArticle(event, id, unmark) {
try {
if (unmark == undefined) unmark = true;
var row = $("RROW-" + id);
var elem = $("CICD-" + id);
@@ -1382,15 +1405,22 @@ function cdmCollapseArticle(event, id) {
Element.hide(elem);
Element.show("CEXC-" + id);
Element.hide(collapse);
row.removeClassName("active");
markHeadline(id, false);
if (unmark) {
row.removeClassName("active");
if (id == getActiveArticleId()) {
setActiveArticleId(0);
markHeadline(id, false);
if (id == getActiveArticleId()) {
setActiveArticleId(0);
}
updateSelectedPrompt();
}
if (event) Event.stop(event);
PluginHost.run(PluginHost.HOOK_ARTICLE_COLLAPSED, id);
}
} catch (e) {
@@ -1398,27 +1428,6 @@ function cdmCollapseArticle(event, id) {
}
}
function cdmUnexpandArticle(event, id) {
try {
var row = $("RROW-" + id);
var elem = $("CICD-" + id);
if (elem && row) {
var collapse = $$("div#RROW-" + id +
" span[class='collapseBtn']")[0];
Element.hide(elem);
Element.show("CEXC-" + id);
Element.hide(collapse);
if (event) Event.stop(event);
}
} catch (e) {
exception_error("cdmUnexpandArticle", e);
}
}
function cdmExpandArticle(id, noexpand) {
try {
console.log("cdmExpandArticle " + id);
@@ -1478,6 +1487,8 @@ function cdmExpandArticle(id, noexpand) {
toggleSelected(id);
$("RROW-" + id).addClassName("active");
PluginHost.run(PluginHost.HOOK_ARTICLE_EXPANDED, id);
} catch (e) {
exception_error("cdmExpandArticle", e);
}
@@ -1485,26 +1496,6 @@ function cdmExpandArticle(id, noexpand) {
return false;
}
function fixHeadlinesOrder(ids) {
try {
for (var i = 0; i < ids.length; i++) {
var e = $("RROW-" + ids[i]);
if (e) {
if (i % 2 == 0) {
e.removeClassName("even");
e.addClassName("odd");
} else {
e.removeClassName("odd");
e.addClassName("even");
}
}
}
} catch (e) {
exception_error("fixHeadlinesOrder", e);
}
}
function getArticleUnderPointer() {
return post_under_pointer;
}
@@ -1585,7 +1576,6 @@ function dismissSelectedArticles() {
if (sel.length > 0)
selectionToggleUnread(false);
fixHeadlinesOrder(tmp);
} catch (e) {
exception_error("dismissSelectedArticles", e);
@@ -1610,8 +1600,6 @@ function dismissReadArticles() {
}
}
fixHeadlinesOrder(tmp);
} catch (e) {
exception_error("dismissSelectedArticles", e);
}
@@ -2003,34 +1991,6 @@ function initHeadlinesMenu() {
}
}
function player(elem) {
var aid = elem.getAttribute("audio-id");
var status = elem.getAttribute("status");
var audio = $(aid);
if (audio) {
if (status == 0) {
audio.play();
status = 1;
elem.innerHTML = __("Playing...");
elem.title = __("Click to pause");
elem.addClassName("playing");
} else {
audio.pause();
status = 0;
elem.innerHTML = __("Play");
elem.title = __("Click to play");
elem.removeClassName("playing");
}
elem.setAttribute("status", status);
} else {
alert("Your browser doesn't seem to support HTML5 audio.");
}
}
function cache_set(id, obj) {
//console.log("cache_set: " + id);
if (has_storage)

View File

@@ -336,7 +336,7 @@ function processBeginBlockCmd ($parms, $cmdTPosBegin, $cmdTPosEnd) {
$this->openBlocksTab[$this->currentNestingLevel] = $blockNo;
$this->currentNestingLevel += 1;
if ($this->currentNestingLevel > $this->maxNestingLevel) {
$trhis->triggerError ("Block nesting overflow in template at offset $cmdTPosBegin.");
$this->triggerError ("Block nesting overflow in template at offset $cmdTPosBegin.");
return false; }
return true; }
@@ -844,7 +844,7 @@ function readFileIntoString ($fileName, &$s) {
$fh = fopen($fileName,"rb");
if ($fh === false) return false;
$fileSize = filesize($fileName);
if ($fileSize === false) {close ($fh); return false; }
if ($fileSize === false) {fclose ($fh); return false; }
$s = fread($fh,$fileSize);
fclose ($fh);
if (strlen($s) != $fileSize) return false;

849
lib/floIcon.php Normal file
View File

@@ -0,0 +1,849 @@
<?php
/***************************************************************************
* Original floIcon copyright (C) 2007 by Joshua Hatfield. *
* *
* In order to use any part of this floIcon Class, you must comply with *
* the license in 'license.doc'. In particular, you may not remove this *
* copyright notice. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************
Version 1.1.1:
Date: 2009-03-16
Changes:
I was a little hasty on that last update. A couple new bugs from 1.1.0 have
been fixed.
Version 1.1.0:
Date: 2009-03-16
Changes:
Added Vista support.
Fixed a number of minor bugs. Many thanks to Dvir Berebi for pointing
them out.
Version 1.0.5:
Date: 2009-03-15
Changes:
Fixed bug when operating on low bit count images (1 or 4) with odd dimensions.
Version 1.0.4:
Date: 2007-05-25
Changes:
Made function not break quite so bad when reading a PNG file on a Vista icon.
Now, you shouldn't be loading Vista icons anyways, but since I'm trying to
upgrade to Vista compatible and I need a comparison, I've got to.
Version 1.0.3:
Date: 2007-05-25
Changes:
Okay, this one was just stupid. When adding large image support, I messed up
and when reading, it doubled the image size. Now, it's fixed.
I took the opportunity to also add a dummy AND map for 32 images on those
readers who might be looking for it (though it's not supposed to be used.)
Version 1.0.2:
Date: 2007-05-24
Sorry about two versions so quickly back to back, but something needed to be
done with speed...things were getting too slow. I'm sure you'll be okay.
Changes:
Told palette determination to stop at 257 colors or is 32 bit because the
palette is not used at that point and gets really slow when it starts
getting into the high numbers, for instance, in photographs or gradient
truecolor images with lots of unique colors.
After experimenting, it appears that Windows XP does in fact support 256x256
images and larger by setting the entry value to 0 in the 1 byte that holds
that value and storing the true dimentions in the image header later. Of
course, it still doesn't use these images in normal operation. XP will
resize these and use them if no other images are available.
Wrapped main documentation (this) to the 80th column for easier reading.
Version 1.0.1:
Date: 2007-05-23
Thank you everyone for actively using the implementation on my site and
illuminating me very quickly to a number of glaring bugs in this class.
Changes:
Added version history.
Fixed bug with non-standard sizes in AND map reading AND writing.
Fixed bug with palette images using non-black color in backgrounds.
Fixed bug with height/width reversal reading files.
Version 1.0.0:
Date: 2007-05-17
Original release date.
Foreword:
If you are simply in the effort of making an ICO file, may I recommend visiting
my site, http://www.flobi.com/ , and clicking on floIcon. I have a fully
functional implementation (on which the sample.php is based) where you can also
see recent icons submitted by other visitors. No registration required, no
intrusive ads. (As of this writing, there aren't actually any ads at all, I
might add google ads at some point.)
If you are trying to get an idea of how ICO files, work, may I recommend the
page I used, http://www.daubnet.com/formats/ICO.html . It does not fully cover
icon files, but it does a very good job of what it does. Any additional
information, I will try to post at
http://www.flobi.com/test/floIcon/more_on_icons.php for your convenience.
If you are trying to get an idea of how image resource files work, I recommend
ANY other class that deals with images. This class essentially plots points on
the image, and that's not perticularly advanced.
For any purpose, I wish you luck and feel free to contact me with any bugs,
comments, questions, etc. - Flobi
Summary:
This class parses ICO files. It reads directly from the ICO file, headers
first, so that if you are only retrieving 1 image, the entire ICO file need not
be parsed. It supports merging ICO files. It supports adding PHP image
resources as new images to the file. It has an export capability that can
easily be written to a new (or the same) ICO file for saving ICO files. All
sizes from 1x1 to 255x255 pixels and 1, 4, 8, 24 (plus transparency) and 32 bit
images are supported. Image retrieval by size is supported.
Included is a fully functional sample that allows users to upload ICO, GIF,
JPEG and PNG files into a session icon file as well as remove images from the
file and download the completed file (sample.php).
Known Limitations: Does not support Vista icons. Does not support inversion
palette method (because of the limitations of the PHP image resource).
Addendum on Limitations:
Windows Vista has added support for 256x256 size icons and now stores files as
PNG's. This class is for older ICO files. A new class is currently under
development that supports the new Windows Vista format.
Palette inversion (my name for this technique) is the technique of using a black
pixel (0, 0, 0) with a 1 "AND" pixel. White pixels with a 1 "AND" show
transparent (or "don't" show). Black pixels with a 1 "AND" show inverted
(sometimes). Because this method isn't uniformly supported or documented and
the PHP image resource doesn't support it, I have decided to not as well. This
does not apply to 32 bit images which include alpha transparency and no AND map.
Though other functions exist, these are the only ones I believe offer usefulness
to be public.
floIcon public functions:
readICO($file, $offset = 0)
Loads the icon from the specified filepath ($file) starting at the
specified file offset ($offset). This function MERGES the loaded icon
images into the floIcon object.
formatICO($offset = 0)
Returns the current floIcon object formatted as an .ICO file with the
file offset altered by $offset. If there are too many or too large
images, causing any images saved past the 4,294,967,296th byte, this
will return false. (This is well outside PHP's default memory
allocation.)
addImage($imageResource, $desiredBitCount = 1, $pngIfWidthExceeds = 48)
Adds an icon image to the icon file based on the passed image resource
($imageResource). It will automatically determine the bit count, but
can be persuaded to increase that to $desiredBitCount if that value is
greater than the determined bit count.
NOTE: The image resource is saved by REFERRENCE. So, if you edit it
then call getImage, the resource returned will be the same, editions and
all. Destruction of the resource will cause a new resource to be
created in getImage().
getImage($offset)
Returns the php image resource either assigned by addImage or created
dynamically at calltime by the data loaded with readICO(). The offset
specified here ($offset) is the array offset starting at 0 and ending
at countImages().
getBestImage($height = 32, $width = 32)
Returns the php images resource of the highest quality image closest to
the size specified. This could be useful when you only want to display
the icon in an icon list with a single representative icon. A resized
copy of the highest quality available image will be returned if there is
no 32 or 24 bit icon present at the speficied dimentions.
sortImagesBySize()
Sorts the $this->images array by order of size, smallest to largest.
This is the optimal sorting for icon files.
countImages()
Returns a count of how many images are present in the current floIcon
object.
floIcon public variables:
$images
Contains a numerically indexed array of floIconImage objects.
$updated
True if an image has been added since load or last formatICO, otherwise
false.
floIconImage public functions:
getHeader()
Returns an associative array containing the information from the ICO
image header.
getEntry()
Returns an associative array containing the information from the ICO
entry header.
NOTE: If this icon image was created by php image resource, this may not
have accurate information until saving from floIcon with the formatICO()
function. Specifically, offset information will be inaccurate.
getImageResource()
Returns a php image resource. Same as floIcon's getImage() function.
setImageResource($imageResource, $desiredBitCount = 1, $pngIfWidthExceeds = 48)
Changes this icon image based on the passed image resource
($imageResource). It will automatically determine the bit count, but can
be persuaded to increase that to $desiredBitCount if that value is
greater than the determined bit count.
NOTE: The image resource is saved by REFERRENCE. So, if you edit it
then call getImageResource, the resource returned will be the same,
editions and all. Destruction of the resource will cause a new resource
to be created in getImageResource().
dealocateResource()
This destroys the image resource variable, freeing up memory. The image
will automatically be recreated when getImageResource is executed.
*/
class floIcon {
/*
* $images is an associative array of offset integer => floIconImage object
*/
var $images; // Array of floIconImage objects.
var $updated = false;
function floIcon() {
$this->images = array();
}
function countImages() {
return count($this->images);
}
function getBestImage($height = 32, $width = 32) {
$best = false;
$bestEntry = array();
$secondBest = false;
$secondBestEntry = array();
foreach ($this->images as $key => $image) {
$entry = $image->getEntry();
$header = $image->getHeader();
if (!@$entry["BitCount"]) {
$entry["BitCount"] = $header["BitCount"];
}
if ($entry["Height"] == $height && $entry["Width"] == $width && $entry["BitCount"] == 32) {
return $image->getImageResource();
} elseif ($entry["Height"] == $height && $entry["Width"] == $width && $entry["BitCount"] > min(4, @$bestEntry["BitCount"])) {
$best = $image;
$bestEntry = $entry;
} elseif (
!$secondBest or
$entry["Height"] >= $secondBestEntry["Height"] &&
$entry["Width"] >= $secondBestEntry["Width"] &&
$secondBestEntry["BitCount"] >= $secondBestEntry["BitCount"] and
(
$entry["Height"] <= 64 && $entry["Height"] > $secondBestEntry["Height"] and
$entry["Height"] > 64 && $entry["Height"] < $secondBestEntry["Height"]
) ||
(
$entry["Width"] <= 64 && $entry["Width"] > $secondBestEntry["Width"] and
$entry["Width"] > 64 && $entry["Width"] < $secondBestEntry["Width"]
) ||
$secondBestEntry["BitCount"] > $secondBestEntry["BitCount"]
) {
$secondBest = $image;
$secondBestEntry = $entry;
}
}
if ($best) {
return $best->getImageResource();
} elseif ($secondBest) {
if ($secondBestEntry["Width"] != $width || $secondBestEntry["Height"] != $height) {
$imageResource = $secondBest->getImageResource();
$newImageResource = imagecreatetruecolor($width, $height);
imagesavealpha($newImageResource, true);
imagealphablending($newImageResource, false);
imagecopyresampled($newImageResource, $imageResource, 0, 0, 0, 0, $width, $height, $secondBestEntry["Width"], $secondBestEntry["Height"]);
$this->addImage($newImageResource, 32);
return $newImageResource;
} else {
return $secondBest->getImageResource();
}
}
}
/*
* readICO merges the icon images from the file to the current list
*/
function readICO($file, $offset = 0) {
if (file_exists($file) && filesize($file) > 0 && $filePointer = fopen($file, "r")) {
fseek($filePointer, $offset);
$header = unpack("SReserved/SType/SCount", fread($filePointer, 6));
for ($t = 0; $t < $header["Count"]; $t++) {
$newImage = new floIconImage();
if ($newImage->readImageFromICO($filePointer, 6 + ($t * 16))) {
$this->images[] = $newImage;
}
}
fclose($filePointer);
}
}
function sortImagesBySize() {
usort($this->images, array("floIcon", "_cmpObj"));
}
function formatICO($offset = 0) {
$this->updated = false;
$output = "";
$output .= pack("SSS", 0, 1, count($this->images));
$output_images = "";
foreach ($this->images as $image) {
$newImageOffset = $offset + // Whatever offset we've been given.
6 // Header.
+ (count($this->images) * 16) // Entries.
+ strlen($output_images);
if ($newImageOffset > pow(256, 4) /* 4 bytes available for position */ ) {
return false;
}
$output .= $image->formatEntryForIco($newImageOffset); // The images already in there.
$output_images .= $image->formatImageForIco();
}
return $output.$output_images;
}
function _cmpObj($a, $b) {
$aSize = $a->getSize();
$bSize = $b->getSize();
if ($aSize == $bSize) {
return 0;
}
return ($aSize > $bSize)?1:-1;
}
function addImage($imageResource, $desiredBitCount = 1, $pngIfWidthExceeds = 48) {
$this->updated = true;
$newImage = new floIconImage();
$newImage->setImageResource($imageResource, $desiredBitCount, $pngIfWidthExceeds);
$this->images[] = $newImage;
}
function getImage($offset) {
if (isset($this->images[$offset])) {
return $this->images[$offset]->getImageResource();
} else {
return false;
}
}
/*
* getSize computes the
*/
function getSize() {
// Compute headers.
$computedSize = 6; // Always 6 bytes.
// Add image entry headers
$computedSize += count($this->images) * 16; // Entry headers are always 16 bytes.
foreach ($this->images as $image) {
$computedSize += $image->getSize() + $image->getHeaderSize(); // getSize does not include the header.
}
}
}
class floIconImage {
var $_imageResource = null;
var $_entry = "";
var $_entryIconFormat = "";
var $_header = "";
var $_headerIconFormat = "";
var $_imageIconFormat = ""; // Includes palette and mask.
function formatEntryForIco($offset) {
// Format the entry, this has to be done here because we need the offset to get the full information.
$this->_entry["FileOffset"] = $offset;
$this->_entryIconFormat = pack("CCCCSSLL",
$this->_entry["Width"]>=256?0:$this->_entry["Width"],
$this->_entry["Height"]>=256?0:$this->_entry["Height"],
$this->_entry["ColorCount"],
$this->_entry["Reserved"],
$this->_entry["Planes"],
$this->_entry["BitCount"],
$this->_entry["SizeInBytes"],
$this->_entry["FileOffset"]
);
return $this->_entryIconFormat;
}
function formatImageForIco() {
// Format the entry, this has to be done here because we need the offset to get the full information.
return ($this->_headerIconFormat.$this->_imageIconFormat);
}
// Will move $bitCount UP to $desiredBitCount if $bitCount is found to be less than it.
function setImageResource($imageResource, $desiredBitCount = 1, $pngIfWidthExceeds = 48) {
imagesavealpha($imageResource, true);
imagealphablending($imageResource, false);
$height = imagesy($imageResource);
$width = imagesx($imageResource);
// Parse resource to determine header and icon format
// Find Palette information
$is_32bit = false; // Start with an assumption and get proven wrong.
$hasTransparency = 0;
$blackColor = false;
$bitCount = 0;
$realPalette = array();
$realIndexPalette = array();
for ($x = 0; $x < $width && !$is_32bit; $x++) {
for ($y = 0; $y < $height && !$is_32bit; $y++) {
$colorIndex = imagecolorat($imageResource, $x, $y);
$color = imagecolorsforindex($imageResource, $colorIndex);
if ($color["alpha"] == 0) {
// No point continuing if there's more than 256 colors or it's 32bit.
if (count($realPalette) < 257 && !$is_32bit) {
$inRealPalette = false;
foreach($realPalette as $realPaletteKey => $realPaletteColor) {
if (
$color["red"] == $realPaletteColor["red"] and
$color["green"] == $realPaletteColor["green"] and
$color["blue"] == $realPaletteColor["blue"]
) {
$inRealPalette = $realPaletteKey;
break;
}
}
if ($inRealPalette === false) {
$realIndexPalette[$colorIndex] = count($realPalette);
if (
$blackColor === false and
$color["red"] == 0 and
$color["green"] == 0 and
$color["blue"] == 0
) {
$blackColor = count($realPalette);
}
$realPalette[] = $color;
} else {
$realIndexPalette[$colorIndex] = $inRealPalette;
}
}
} else {
$hasTransparency = 1;
}
if ($color["alpha"] != 0 && $color["alpha"] != 127) {
$is_32bit = true;
}
}
}
if ($is_32bit) {
$colorCount = 0;
$bitCount = 32;
} else {
if ($hasTransparency && $blackColor === false) {
// We need a black color to facilitate transparency. Unfortunately, this can
// increase the palette size by 1 if there's no other black color.
$blackColor = count($realPalette);
$color = array(
"red" => 0,
"blue" => 0,
"green" => 0,
"alpha" => 0
);
$realPalette[] = $color;
}
$colorCount = count($realPalette);
if ($colorCount > 256 || $colorCount == 0) {
$bitCount = 24;
} elseif ($colorCount > 16) {
$bitCount = 8;
// 8 bit
} elseif ($colorCount > 2) {
$bitCount = 4;
// 4 bit
} else {
$bitCount = 1;
// 1 bit
}
if ($desiredBitCount > $bitCount) {
$bitCount = $desiredBitCount;
}
switch ($bitCount) {
case 24:
$colorCount = 0;
break;
case 8:
$colorCount = 256;
break;
case 4:
$colorCount = 16;
break;
case 1:
$colorCount = 2;
break;
}
}
// Create $this->_imageIconFormat...
$this->_imageIconFormat = "";
if ($bitCount < 24) {
$iconPalette = array();
// Save Palette
foreach ($realIndexPalette as $colorIndex => $paletteIndex) {
$color = $realPalette[$paletteIndex];
$this->_imageIconFormat .= pack("CCCC", $color["blue"], $color["green"], $color["red"], 0);
}
while (strlen($this->_imageIconFormat) < $colorCount * 4) {
$this->_imageIconFormat .= pack("CCCC", 0, 0, 0, 0);
}
// Save Each Pixel as Palette Entry
$byte = 0; // For $bitCount < 8 math
$bitPosition = 0; // For $bitCount < 8 math
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
$color = imagecolorat($imageResource, $x, $height-$y-1);
if (isset($realIndexPalette[$color])) {
$color = $realIndexPalette[$color];
} else {
$color = $blackColor;
}
if ($bitCount < 8) {
$bitPosition += $bitCount;
$colorAdjusted = $color * pow(2, 8 - $bitPosition);
$byte += $colorAdjusted;
if ($bitPosition == 8) {
$this->_imageIconFormat .= chr($byte);
$bitPosition = 0;
$byte = 0;
}
} else {
$this->_imageIconFormat .= chr($color);
}
}
// Each row ends with dumping the remaining bits and filling up to the 32bit line with 0's.
if ($bitPosition) {
$this->_imageIconFormat .= chr($byte);
$bitPosition = 0;
$byte = 0;
}
if (strlen($this->_imageIconFormat)%4) $this->_imageIconFormat .= str_repeat(chr(0), 4-(strlen($this->_imageIconFormat)%4));
}
} else {
// Save each pixel.
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
$color = imagecolorat($imageResource, $x, $height-$y-1);
$color = imagecolorsforindex($imageResource, $color);
if ($bitCount == 24) {
if ($color["alpha"]) {
$this->_imageIconFormat .= pack("CCC", 0, 0, 0);
} else {
$this->_imageIconFormat .= pack("CCC", $color["blue"], $color["green"], $color["red"]);
}
} else {
$color["alpha"] = round((127-$color["alpha"]) / 127 * 255);
$this->_imageIconFormat .= pack("CCCC", $color["blue"], $color["green"], $color["red"], $color["alpha"]);
}
}
if (strlen($this->_imageIconFormat)%4) $this->_imageIconFormat .= str_repeat(chr(0), 4-(strlen($this->_imageIconFormat)%4));
}
}
// save AND map (transparency)
$byte = 0; // For $bitCount < 8 math
$bitPosition = 0; // For $bitCount < 8 math
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
if ($bitCount < 32) {
$color = imagecolorat($imageResource, $x, $height-$y-1);
$color = imagecolorsforindex($imageResource, $color);
$color = $color["alpha"] == 127?1:0;
} else {
$color = 0;
}
$bitPosition += 1;
$colorAdjusted = $color * pow(2, 8 - $bitPosition);
$byte += $colorAdjusted;
if ($bitPosition == 8) {
$this->_imageIconFormat .= chr($byte);
$bitPosition = 0;
$byte = 0;
}
}
// Each row ends with dumping the remaining bits and filling up to the 32bit line with 0's.
if ($bitPosition) {
$this->_imageIconFormat .= chr($byte);
$bitPosition = 0; // For $bitCount < 8 math
$byte = 0;
}
while (strlen($this->_imageIconFormat)%4) {
$this->_imageIconFormat .= chr(0);
}
}
if ($colorCount >= 256) {
$colorCount = 0;
}
// Create header information...
$this->_header = array(
"Size" => 40,
"Width" => $width,
"Height" => $height*2,
"Planes" => 1,
"BitCount" => $bitCount,
"Compression" => 0,
"ImageSize" => strlen($this->_imageIconFormat),
"XpixelsPerM" => 0,
"YpixelsPerM" => 0,
"ColorsUsed" => $colorCount,
"ColorsImportant" => 0,
);
$this->_headerIconFormat = pack("LLLSSLLLLLL",
$this->_header["Size"],
$this->_header["Width"],
$this->_header["Height"],
$this->_header["Planes"],
$this->_header["BitCount"],
$this->_header["Compression"],
$this->_header["ImageSize"],
$this->_header["XpixelsPerM"],
$this->_header["YpixelsPerM"],
$this->_header["ColorsUsed"],
$this->_header["ColorsImportant"]
);
$this->_entry = array(
"Width" => $width,
"Height" => $height,
"ColorCount" => $colorCount,
"Reserved" => 0,
"Planes" => 1,
"BitCount" => $bitCount,
"SizeInBytes" => $this->_header["Size"] + $this->_header["ImageSize"],
"FileOffset" => -1,
);
$this->_entryIconFormat = ""; // This won't get set until it's needed with the offset.
$this->_imageResource = $imageResource;
// Make png if width exceeds limit for old ico style
if ($width > $pngIfWidthExceeds) {
// I wish there were a better way to get the info than this. If anyone needs a version that doesn't use OB, I can have one that creates a TMP file.
ob_start();
imagepng($imageResource);
$imageAsPng = ob_get_contents();
ob_end_clean();
$this->_headerIconFormat = "";
$this->_imageIconFormat = $imageAsPng;
}
}
function _createImageResource() {
if ($newImage = @imagecreatefromstring($this->_headerIconFormat.$this->_imageIconFormat)) {
// Vista supports PNG.
$this->_headerIconFormat = "";
$this->_imageIconFormat = $this->_headerIconFormat.$this->_imageIconFormat;
imagesavealpha($newImage, true);
imagealphablending($newImage, false);
$this->_imageResource = $newImage;
} elseif ($this->_entry["Height"] <= 1024 && $this->_entry["Width"] <= 1024) {
$newImage = imagecreatetruecolor($this->_entry["Width"], $this->_entry["Height"]);
imagesavealpha($newImage, true);
imagealphablending($newImage, false);
$readPosition = 0;
$palette = array();
if ($this->_header["BitCount"] < 24) {
// Read Palette for low bitcounts
$colorsInPalette = $this->_header["ColorsUsed"]?$this->_header["ColorsUsed"]:$this->_entry["ColorCount"];
for ($t = 0; $t < pow(2, $this->_header["BitCount"]); $t++) {
$blue = ord($this->_imageIconFormat[$readPosition++]);
$green = ord($this->_imageIconFormat[$readPosition++]);
$red = ord($this->_imageIconFormat[$readPosition++]);
$readPosition++; // Unused "Reserved" value.
$existingPaletteEntry = imagecolorexactalpha($newImage, $red, $green, $blue, 0);
if ($existingPaletteEntry >= 0) {
$palette[] = $existingPaletteEntry;
} else {
$palette[] = imagecolorallocatealpha($newImage, $red, $green, $blue, 0);
}
}
// XOR
for ($y = 0; $y < $this->_entry["Height"]; $y++) {
$colors = array();
for ($x = 0; $x < $this->_entry["Width"]; $x++) {
if ($this->_header["BitCount"] < 8) {
$color = array_shift($colors);
if (is_null($color)) {
$byte = ord($this->_imageIconFormat[$readPosition++]);
$tmp_color = 0;
for ($t = 7; $t >= 0; $t--) {
$bit_value = pow(2, $t);
$bit = floor($byte / $bit_value);
$byte = $byte - ($bit * $bit_value);
$tmp_color += $bit * pow(2, $t%$this->_header["BitCount"]);
if ($t%$this->_header["BitCount"] == 0) {
array_push($colors, $tmp_color);
$tmp_color = 0;
}
}
$color = array_shift($colors);
}
} else {
$color = ord($this->_imageIconFormat[$readPosition++]);
}
imagesetpixel($newImage, $x, $this->_entry["Height"]-$y-1, $palette[$color]) or die("can't set pixel");
}
// All rows end on the 32 bit
if ($readPosition%4) $readPosition += 4-($readPosition%4);
}
} else {
// BitCount >= 24, No Palette.
// marking position because some icons mark all pixels transparent when using an AND map.
$markPosition = $readPosition;
$retry = true;
$ignoreAlpha = false;
while ($retry) {
$alphas = array();
$retry = false;
for ($y = 0; $y < $this->_entry["Height"] and !$retry; $y++) {
for ($x = 0; $x < $this->_entry["Width"] and !$retry; $x++) {
$blue = ord($this->_imageIconFormat[$readPosition++]);
$green = ord($this->_imageIconFormat[$readPosition++]);
$red = ord($this->_imageIconFormat[$readPosition++]);
if ($this->_header["BitCount"] < 32) {
$alpha = 0;
} elseif($ignoreAlpha) {
$alpha = 0;
$readPosition++;
} else {
$alpha = ord($this->_imageIconFormat[$readPosition++]);
$alphas[$alpha] = $alpha;
$alpha = 127-round($alpha/255*127);
}
$paletteEntry = imagecolorexactalpha($newImage, $red, $green, $blue, $alpha);
if ($paletteEntry < 0) {
$paletteEntry = imagecolorallocatealpha($newImage, $red, $green, $blue, $alpha);
}
imagesetpixel($newImage, $x, $this->_entry["Height"]-$y-1, $paletteEntry) or die("can't set pixel");
}
if ($readPosition%4) $readPosition += 4-($readPosition%4);
}
if ($this->_header["BitCount"] == 32 && isset($alphas[0]) && count($alphas) == 1) {
$retry = true;
$readPosition = $markPosition;
$ignoreAlpha = true;
}
}
}
// AND map
if ($this->_header["BitCount"] < 32 || $ignoreAlpha) {
// Bitcount == 32, No AND (if using alpha).
$palette[-1] = imagecolorallocatealpha($newImage, 0, 0, 0, 127);
imagecolortransparent($newImage, $palette[-1]);
for ($y = 0; $y < $this->_entry["Height"]; $y++) {
$colors = array();
for ($x = 0; $x < $this->_entry["Width"]; $x++) {
$color = array_shift($colors);
if (is_null($color)) {
$byte = ord($this->_imageIconFormat[$readPosition++]);
$tmp_color = 0;
for ($t = 7; $t >= 0; $t--) {
$bit_value = pow(2, $t);
$bit = floor($byte / $bit_value);
$byte = $byte - ($bit * $bit_value);
array_push($colors, $bit);
}
$color = array_shift($colors);
}
if ($color) {
imagesetpixel($newImage, $x, $this->_entry["Height"]-$y-1, $palette[-1]) or die("can't set pixel");
}
}
// All rows end on the 32 bit.
if ($readPosition%4) $readPosition += 4-($readPosition%4);
}
}
if ($this->_header["BitCount"] < 24) {
imagetruecolortopalette($newImage, true, pow(2, $this->_header["BitCount"]));
}
}
$this->_imageResource = $newImage;
}
// this function expects that $_entry, $_header and $_imageIconFormat have already been read, specifically from readImageFromICO.
// Don't call this function except from there.
function readImageFromICO($filePointer, $entryOffset) {
$tmpPosition = ftell($filePointer); // So any other applications won't loose their position.
// Get the entry.
fseek($filePointer, $entryOffset);
$this->_entryIconFormat = fread($filePointer, 16);
$this->_entry = unpack("CWidth/CHeight/CColorCount/CReserved/SPlanes/SBitCount/LSizeInBytes/LFileOffset", $this->_entryIconFormat);
if ($this->_entry["SizeInBytes"] > 16384)
return false;
// Position the file pointer.
fseek($filePointer, $this->_entry["FileOffset"]);
// Get the header.
$this->_headerIconFormat = fread($filePointer, 40);
$this->_header = unpack("LSize/LWidth/LHeight/SPlanes/SBitCount/LCompression/LImageSize/LXpixelsPerM/LYpixelsPerM/LColorsUsed/LColorsImportant", $this->_headerIconFormat);
// Get the image.
$this->_imageIconFormat = @fread($filePointer, $this->_entry["SizeInBytes"] - strlen($this->_headerIconFormat));
fseek($filePointer, $tmpPosition); // So any other applications won't loose their position.
if ($newImage = @imagecreatefromstring($this->_headerIconFormat.$this->_imageIconFormat)) {
// This is a PNG, the supposed header information is useless.
$this->_header = array (
"Size" => 0,
"Width" => imagesx($newImage),
"Height" => imagesy($newImage) * 2,
"Planes" => 0,
"BitCount" => 32,
"Compression" => 0,
"ImageSize" => strlen($this->_imageIconFormat),
"XpixelsPerM" => 0,
"YpixelsPerM" => 0,
"ColorsUsed" => 0,
"ColorsImportant" => 0,
);
imagedestroy($newImage);
}
// Support for larger images requires entry marked as 0.
if ($this->_entry["Width"] == 0) {
$this->_entry["Width"] = $this->_header["Width"];
}
if ($this->_entry["Height"] == 0) {
$this->_entry["Height"] = $this->_header["Height"]/2;
}
return true;
}
function getHeader() {
return $this->_header;
}
function getEntry() {
return $this->_entry;
}
function floIconImage() {
}
function getHeaderSize() {
return strlen($this->_headerIconFormat);
}
function getSize() {
return strlen($this->_imageIconFormat);
}
function getImageResource() {
if (!$this->_imageResource) $this->_createImageResource();
return $this->_imageResource;
}
function dealocateResource() {
@imagedestroy($this->_imageResource);
$this->_imageResource = null;
}
}
?>

0
lib/index.html Normal file
View File

View File

@@ -1101,7 +1101,7 @@ if (!class_exists('QRcode', false)) {
protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false) {
$b = 0;
$bitMask = array();
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
if ($maskGenOnly) {
return;
}
@@ -1399,7 +1399,7 @@ if (!class_exists('QRcode', false)) {
$p += 2;
}
$this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr));
return $run;
return $p;
}
/**
@@ -1470,7 +1470,7 @@ if (!class_exists('QRcode', false)) {
break;
}
case QR_MODE_KJ: {
if ($hint == QR_MODE_KJ) {
if ($this->hint == QR_MODE_KJ) {
$length = $this->eatKanji();
} else {
$length = $this->eat8();
@@ -1499,7 +1499,7 @@ if (!class_exists('QRcode', false)) {
$stringLen = strlen($this->dataStr);
$p = 0;
while ($p < $stringLen) {
$mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint);
$mode = $this->identifyMode(substr($this->dataStr, $p));
if ($mode == QR_MODE_KJ) {
$p += 2;
} else {

View File

@@ -2195,7 +2195,7 @@
case QR_MODE_NUM: $length = $this->eatNum(); break;
case QR_MODE_AN: $length = $this->eatAn(); break;
case QR_MODE_KANJI:
if ($hint == QR_MODE_KANJI)
if ($this->modeHint == QR_MODE_KANJI)
$length = $this->eatKanji();
else $length = $this->eat8();
break;
@@ -2217,7 +2217,7 @@
$p = 0;
while ($p<$stringLen) {
$mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
$mode = self::identifyMode(substr($this->dataStr, $p));
if($mode == QR_MODE_KANJI) {
$p += 2;
} else {
@@ -2621,13 +2621,13 @@
if (file_exists($fileName)) {
$bitMask = self::unserial(file_get_contents($fileName));
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
file_put_contents($fileName, self::serial($bitMask));
}
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
}
if ($maskGenOnly)
@@ -2937,7 +2937,7 @@
//----------------------------------------------------------------------
public function getCode()
{
$ret;
$ret = 0;
if($this->count < $this->dataLength) {
$row = $this->count % $this->blocks;
@@ -3059,7 +3059,7 @@
$input = new QRinput($version, $level);
if($input == NULL) return NULL;
$ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
$ret = $input->append(QR_MODE_8, strlen($string), str_split($string));
if($ret < 0) {
unset($input);
return NULL;

View File

@@ -129,7 +129,7 @@
//----------------------------------------------------------------------
public function getCode()
{
$ret;
$ret = 0;
if($this->count < $this->dataLength) {
$row = $this->count % $this->blocks;

View File

@@ -149,13 +149,13 @@
if (file_exists($fileName)) {
$bitMask = self::unserial(file_get_contents($fileName));
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
file_put_contents($fileName, self::serial($bitMask));
}
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
$bitMask = $this->generateMaskNo($maskNo, $width, $s);
}
if ($maskGenOnly)

View File

@@ -186,7 +186,7 @@
if($ret < 0)
return -1;
return $run;
return $ret;
}
//----------------------------------------------------------------------
@@ -258,7 +258,7 @@
case QR_MODE_NUM: $length = $this->eatNum(); break;
case QR_MODE_AN: $length = $this->eatAn(); break;
case QR_MODE_KANJI:
if ($hint == QR_MODE_KANJI)
if ($this->modeHint == QR_MODE_KANJI)
$length = $this->eatKanji();
else $length = $this->eat8();
break;
@@ -280,7 +280,7 @@
$p = 0;
while ($p<$stringLen) {
$mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
$mode = self::identifyMode(substr($this->dataStr, $p));
if($mode == QR_MODE_KANJI) {
$p += 2;
} else {

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
Automatic
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa

2
locale/.htaccess Normal file
View File

@@ -0,0 +1,2 @@
Order deny,allow
Deny from all

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More