diff --git a/.gitignore b/.gitignore
index d98c0efc3..b4853806c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/messages.mo
*~
*.DS_Store
#*
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 000000000..22b33f000
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,3 @@
+AddType image/svg+xml svg
+AddType image/svg+xml svgz
+
diff --git a/api/index.php b/api/index.php
index 53b78b010..facdf82c5 100644
--- a/api/index.php
+++ b/api/index.php
@@ -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();
diff --git a/backend.php b/backend.php
index 9eb3989e4..84abc9730 100644
--- a/backend.php
+++ b/backend.php
@@ -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);
?>
diff --git a/plugins/example_article/init.js b/cache/upload/.empty
similarity index 100%
rename from plugins/example_article/init.js
rename to cache/upload/.empty
diff --git a/cdm.css b/cdm.css
index 9893f43fc..657950140 100644
--- a/cdm.css
+++ b/cdm.css
@@ -60,6 +60,7 @@ div.cdmContentInner {
div.cdmContentInner img {
border-width : 0px;
max-width : 98%;
+ height : auto;
}
div.cdmFooter {
diff --git a/classes/.htaccess b/classes/.htaccess
new file mode 100644
index 000000000..93169e4eb
--- /dev/null
+++ b/classes/.htaccess
@@ -0,0 +1,2 @@
+Order deny,allow
+Deny from all
diff --git a/classes/api.php b/classes/api.php
index 4427834eb..f5e4a0c5c 100644
--- a/classes/api.php
+++ b/classes/api.php
@@ -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;
}
diff --git a/classes/article.php b/classes/article.php
index 9a0970140..e9f86f298 100644
--- a/classes/article.php
+++ b/classes/article.php
@@ -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 '';
}
- $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):")."
";
- $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 "";
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 "
" . $rv[3] . ""; @@ -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) { diff --git a/classes/db.php b/classes/db.php new file mode 100644 index 000000000..695ca6ea2 --- /dev/null +++ b/classes/db.php @@ -0,0 +1,98 @@ +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(); + } + +} +?> diff --git a/classes/db/mysql.php b/classes/db/mysql.php new file mode 100644 index 000000000..aab05aca2 --- /dev/null +++ b/classes/db/mysql.php @@ -0,0 +1,73 @@ +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; + } + +} +?> diff --git a/classes/db/mysqli.php b/classes/db/mysqli.php new file mode 100644 index 000000000..550df6f15 --- /dev/null +++ b/classes/db/mysqli.php @@ -0,0 +1,77 @@ +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; + } + +} +?> diff --git a/classes/db/pdo.php b/classes/db/pdo.php new file mode 100644 index 000000000..126f5150a --- /dev/null +++ b/classes/db/pdo.php @@ -0,0 +1,100 @@ +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; + } + +} +?> diff --git a/classes/db/pgsql.php b/classes/db/pgsql.php new file mode 100644 index 000000000..4d860790b --- /dev/null +++ b/classes/db/pgsql.php @@ -0,0 +1,82 @@ + 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; + } +} +?> diff --git a/classes/db/prefs.php b/classes/db/prefs.php new file mode 100644 index 000000000..26fb4666b --- /dev/null +++ b/classes/db/prefs.php @@ -0,0 +1,190 @@ +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; + } + } + } + +} +?> diff --git a/classes/db/stmt.php b/classes/db/stmt.php new file mode 100644 index 000000000..4d3596ef1 --- /dev/null +++ b/classes/db/stmt.php @@ -0,0 +1,32 @@ +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(); + } +} +?> diff --git a/classes/dbupdater.php b/classes/dbupdater.php index a9a713273..a319da03d 100644 --- a/classes/dbupdater.php +++ b/classes/dbupdater.php @@ -1,18 +1,18 @@ 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 { diff --git a/classes/dlg.php b/classes/dlg.php index e56560a47..cfa960d9a 100644 --- a/classes/dlg.php +++ b/classes/dlg.php @@ -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 "