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 ""; @@ -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))); diff --git a/classes/auth/base.php b/classes/auth/base.php index ad7ff3646..69acd0985 100644 --- a/classes/auth/base.php +++ b/classes/auth/base.php @@ -1,9 +1,9 @@ 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; } diff --git a/classes/backend.php b/classes/backend.php index c03d583db..7737df0f6 100644 --- a/classes/backend.php +++ b/classes/backend.php @@ -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] = "
" . $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 "
"; $owner_uid = $_SESSION["uid"]; - db_query($this->link, "BEGIN"); + $this->dbh->query("BEGIN"); print ""; print "
"; @@ -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 "