index.php 9.99 KB
Newer Older
Andrew Dolgov's avatar
Andrew Dolgov committed
1 2 3 4
<?php
	error_reporting(E_ERROR | E_PARSE);

	require_once "../config.php";
5

Andrew Dolgov's avatar
Andrew Dolgov committed
6 7 8 9
	require_once "../db.php";
	require_once "../db-prefs.php";
	require_once "../functions.php";

10 11 12
	define('API_STATUS_OK', 0);
	define('API_STATUS_ERR', 1);

13 14 15 16
	if (defined('ENABLE_GZIP_OUTPUT') && ENABLE_GZIP_OUTPUT) {
		ob_start("ob_gzhandler");
	}

17
	$link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
Andrew Dolgov's avatar
Andrew Dolgov committed
18 19 20 21

	$session_expire = SESSION_EXPIRE_TIME; //seconds
	$session_name = (!defined('TTRSS_SESSION_NAME')) ? "ttrss_sid_api" : TTRSS_SESSION_NAME . "_api";

22 23
	session_name($session_name);

24 25 26 27 28 29 30 31 32 33 34
	$input = file_get_contents("php://input");

	// Override $_REQUEST with JSON-encoded data if available
	if ($input) {
		$input = json_decode($input, true);

		if ($input) {
			$_REQUEST = $input;
		}
	}

35 36 37 38
	if ($_REQUEST["sid"]) {
		session_id($_REQUEST["sid"]);
	}

Andrew Dolgov's avatar
Andrew Dolgov committed
39 40 41 42 43 44
	session_start();

	if (!$link) {
		if (DB_TYPE == "mysql") {
			print mysql_error();
		}
45
		// PG seems to display its own errors just fine by default.
Andrew Dolgov's avatar
Andrew Dolgov committed
46 47 48 49 50 51
		return;
	}

	init_connection($link);

	$op = db_escape_string($_REQUEST["op"]);
52
	$seq = (int) $_REQUEST["seq"];
Andrew Dolgov's avatar
Andrew Dolgov committed
53

Andrew Dolgov's avatar
Andrew Dolgov committed
54
	header("Content-Type: text/plain");
Andrew Dolgov's avatar
Andrew Dolgov committed
55

56 57 58 59 60 61
	function api_wrap_reply($status, $seq, $reply) {
		print json_encode(array("seq" => $seq,
			"status" => $status,
			"content" => $reply));
	}

Andrew Dolgov's avatar
Andrew Dolgov committed
62
	if (!$_SESSION["uid"] && $op != "login" && $op != "isLoggedIn") {
63
		print api_wrap_reply(API_STATUS_ERR, $seq, array("error" => 'NOT_LOGGED_IN'));
Andrew Dolgov's avatar
Andrew Dolgov committed
64 65 66
		return;
	}

67
	if ($_SESSION["uid"] && $op != "logout" && !get_pref($link, 'ENABLE_API_ACCESS')) {
68
		print api_wrap_reply(API_STATUS_ERR, $seq, array("error" => 'API_DISABLED'));
Andrew Dolgov's avatar
Andrew Dolgov committed
69
		return;
70
	}
Andrew Dolgov's avatar
Andrew Dolgov committed
71 72

	switch ($op) {
73

Andrew Dolgov's avatar
Andrew Dolgov committed
74 75
		case "getVersion":
			$rv = array("version" => VERSION);
76
			print api_wrap_reply(API_STATUS_OK, $seq, $rv);
77
			break;
78

Andrew Dolgov's avatar
Andrew Dolgov committed
79 80 81
		case "login":
			$login = db_escape_string($_REQUEST["user"]);
			$password = db_escape_string($_REQUEST["password"]);
82
			$password_base64 = db_escape_string(base64_decode($_REQUEST["password"]));
Andrew Dolgov's avatar
Andrew Dolgov committed
83

84 85
			if (SINGLE_USER_MODE) $login = "admin";

86 87 88 89 90 91 92 93
			$result = db_query($link, "SELECT id FROM ttrss_users WHERE login = '$login'");

			if (db_num_rows($result) != 0) {
				$uid = db_fetch_result($result, 0, "id");
			} else {
				$uid = 0;
			}

94 95 96 97 98 99 100
			if (!$uid) {
				print api_wrap_reply(API_STATUS_ERR, $seq,
					array("error" => "LOGIN_ERROR"));
				return;
			}

			if (get_pref($link, "ENABLE_API_ACCESS", $uid)) {
101
				if (authenticate_user($link, $login, $password)) {               // try login with normal password
102
					print api_wrap_reply(API_STATUS_OK, $seq,
103
						array("session_id" => session_id()));
104
				} else if (authenticate_user($link, $login, $password_base64)) { // else try with base64_decoded password
105
					print api_wrap_reply(API_STATUS_OK, $seq,
106
						array("session_id" => session_id()));
107
				} else {                                                         // else we are not logged in
108
					print api_wrap_reply(API_STATUS_ERR, $seq,
109
						array("error" => "LOGIN_ERROR"));
110
				}
Andrew Dolgov's avatar
Andrew Dolgov committed
111
			} else {
112 113
				print api_wrap_reply(API_STATUS_ERR, $seq,
					array("error" => "API_DISABLED"));
Andrew Dolgov's avatar
Andrew Dolgov committed
114 115 116
			}

			break;
117

Andrew Dolgov's avatar
Andrew Dolgov committed
118 119
		case "logout":
			logout_user();
120
			print api_wrap_reply(API_STATUS_OK, $seq, array("status" => "OK"));
Andrew Dolgov's avatar
Andrew Dolgov committed
121
			break;
122

Andrew Dolgov's avatar
Andrew Dolgov committed
123
		case "isLoggedIn":
124
			print api_wrap_reply(API_STATUS_OK, $seq,
125
				array("status" => $_SESSION["uid"] != ''));
Andrew Dolgov's avatar
Andrew Dolgov committed
126
			break;
127

Andrew Dolgov's avatar
Andrew Dolgov committed
128 129 130 131 132
		case "getUnread":
			$feed_id = db_escape_string($_REQUEST["feed_id"]);
			$is_cat = db_escape_string($_REQUEST["is_cat"]);

			if ($feed_id) {
133
				print api_wrap_reply(API_STATUS_OK, $seq,
134
					array("unread" => getFeedUnread($link, $feed_id, $is_cat)));
Andrew Dolgov's avatar
Andrew Dolgov committed
135
			} else {
136
				print api_wrap_reply(API_STATUS_OK, $seq,
137
					array("unread" => getGlobalUnread($link)));
Andrew Dolgov's avatar
Andrew Dolgov committed
138
			}
139
			break;
140

141
		/* Method added for ttrss-reader for Android */
142
		case "getCounters":
143

144 145
			/* flct (flc is the default) FIXME: document */
			$output_mode = db_escape_string($_REQUEST["output_mode"]);
146

147
			print api_wrap_reply(API_STATUS_OK, $seq,
148
				getAllCounters($link, $output_mode));
Andrew Dolgov's avatar
Andrew Dolgov committed
149
			break;
150

Andrew Dolgov's avatar
Andrew Dolgov committed
151 152 153
		case "getFeeds":
			$cat_id = db_escape_string($_REQUEST["cat_id"]);
			$unread_only = (bool)db_escape_string($_REQUEST["unread_only"]);
154 155 156
			$limit = (int) db_escape_string($_REQUEST["limit"]);
			$offset = (int) db_escape_string($_REQUEST["offset"]);

157 158
			chdir(".."); // so feed_has_icon() would work properly for relative ICONS_DIR

159
			$feeds = api_get_feeds($link, $cat_id, $unread_only, $limit, $offset);
160

161
			print api_wrap_reply(API_STATUS_OK, $seq, $feeds);
Andrew Dolgov's avatar
Andrew Dolgov committed
162 163

			break;
164

Andrew Dolgov's avatar
Andrew Dolgov committed
165
		case "getCategories":
Andrew Dolgov's avatar
Andrew Dolgov committed
166 167
			$unread_only = (bool)db_escape_string($_REQUEST["unread_only"]);

168 169 170
			$result = db_query($link, "SELECT
					id, title FROM ttrss_feed_categories
				WHERE owner_uid = " .
Andrew Dolgov's avatar
Andrew Dolgov committed
171 172 173 174 175 176
				$_SESSION["uid"]);

			$cats = array();

			while ($line = db_fetch_assoc($result)) {
				$unread = getFeedUnread($link, $line["id"], true);
Andrew Dolgov's avatar
Andrew Dolgov committed
177 178

				if ($unread || !$unread_only) {
179
					array_push($cats, array("id" => $line["id"],
180
						"title" => $line["title"],
181
						"unread" => $unread));
Andrew Dolgov's avatar
Andrew Dolgov committed
182
				}
Andrew Dolgov's avatar
Andrew Dolgov committed
183 184
			}

185
			print api_wrap_reply(API_STATUS_OK, $seq, $cats);
Andrew Dolgov's avatar
Andrew Dolgov committed
186
			break;
187

Andrew Dolgov's avatar
Andrew Dolgov committed
188 189 190
		case "getHeadlines":
			$feed_id = db_escape_string($_REQUEST["feed_id"]);
			$limit = (int)db_escape_string($_REQUEST["limit"]);
191
			$offset = (int)db_escape_string($_REQUEST["skip"]);
Andrew Dolgov's avatar
Andrew Dolgov committed
192 193
			$filter = db_escape_string($_REQUEST["filter"]);
			$is_cat = (bool)db_escape_string($_REQUEST["is_cat"]);
194 195
			$show_excerpt = (bool)db_escape_string($_REQUEST["show_excerpt"]);
			$show_content = (bool)db_escape_string($_REQUEST["show_content"]);
196 197
			/* all_articles, unread, adaptive, marked, updated */
			$view_mode = db_escape_string($_REQUEST["view_mode"]);
198
			$include_attachments = (bool)db_escape_string($_REQUEST["include_attachments"]);
Andrew Dolgov's avatar
Andrew Dolgov committed
199
			$since_id = (int)db_escape_string($_REQUEST["since_id"]);
Andrew Dolgov's avatar
Andrew Dolgov committed
200

201
			$headlines = api_get_headlines($link, $feed_id, $limit, $offset,
202
				$filter, $is_cat, $show_excerpt, $show_content, $view_mode, false,
Andrew Dolgov's avatar
Andrew Dolgov committed
203
				$include_attachments, $since_id);
Andrew Dolgov's avatar
Andrew Dolgov committed
204

205
			print api_wrap_reply(API_STATUS_OK, $seq, $headlines);
Andrew Dolgov's avatar
Andrew Dolgov committed
206

Andrew Dolgov's avatar
Andrew Dolgov committed
207
			break;
208

Andrew Dolgov's avatar
Andrew Dolgov committed
209
		case "updateArticle":
210
			$article_ids = array_filter(explode(",", db_escape_string($_REQUEST["article_ids"])), is_numeric);
Andrew Dolgov's avatar
Andrew Dolgov committed
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
			$mode = (int) db_escape_string($_REQUEST["mode"]);
			$field_raw = (int)db_escape_string($_REQUEST["field"]);

			$field = "";
			$set_to = "";

			switch ($field_raw) {
				case 0:
					$field = "marked";
					break;
				case 1:
					$field = "published";
					break;
				case 2:
					$field = "unread";
					break;
			};

			switch ($mode) {
				case 1:
					$set_to = "true";
					break;
				case 0:
					$set_to = "false";
					break;
				case 2:
					$set_to = "NOT $field";
					break;
			}

241 242 243 244
			if ($field && $set_to && count($article_ids) > 0) {

				$article_ids = join(", ", $article_ids);

Andrew Dolgov's avatar
Andrew Dolgov committed
245 246 247
				if ($field == "unread") {
					$result = db_query($link, "UPDATE ttrss_user_entries SET $field = $set_to,
						last_read = NOW()
248
						WHERE ref_id IN ($article_ids) AND owner_uid = " . $_SESSION["uid"]);
Andrew Dolgov's avatar
Andrew Dolgov committed
249 250
				} else {
					$result = db_query($link, "UPDATE ttrss_user_entries SET $field = $set_to
251
						WHERE ref_id IN ($article_ids) AND owner_uid = " . $_SESSION["uid"]);
Andrew Dolgov's avatar
Andrew Dolgov committed
252
				}
253

254 255 256 257 258 259 260 261 262 263 264
				$num_updated = db_affected_rows($link, $result);

				if ($num_updated > 0 && $field == "unread") {
					$result = db_query($link, "SELECT DISTINCT feed_id FROM ttrss_user_entries
						WHERE ref_id IN ($article_ids)");

					while ($line = db_fetch_assoc($result)) {
						ccache_update($link, $line["feed_id"], $_SESSION["uid"]);
					}
				}

265
				print api_wrap_reply(API_STATUS_OK, $seq, array("status" => "OK",
266 267 268
					"updated" => $num_updated));

			} else {
269
				print api_wrap_reply(API_STATUS_ERR, $seq,
270
					array("error" => 'INCORRECT_USAGE'));
Andrew Dolgov's avatar
Andrew Dolgov committed
271 272 273 274
			}

			break;

Andrew Dolgov's avatar
Andrew Dolgov committed
275 276
		case "getArticle":

277
			$article_id = join(",", array_filter(explode(",", db_escape_string($_REQUEST["article_id"])), is_numeric));
Andrew Dolgov's avatar
Andrew Dolgov committed
278

279
			$query = "SELECT id,title,link,content,feed_id,comments,int_id,
Andrew Dolgov's avatar
Andrew Dolgov committed
280
				marked,unread,published,
Andrew Dolgov's avatar
Andrew Dolgov committed
281 282 283
				".SUBSTRING_FOR_DATE."(updated,1,16) as updated,
				author
				FROM ttrss_entries,ttrss_user_entries
284
				WHERE	id IN ($article_id) AND ref_id = id AND owner_uid = " .
Andrew Dolgov's avatar
Andrew Dolgov committed
285 286 287
					$_SESSION["uid"] ;

			$result = db_query($link, $query);
288 289 290

			$articles = array();

Andrew Dolgov's avatar
Andrew Dolgov committed
291 292
			if (db_num_rows($result) != 0) {

293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
				while ($line = db_fetch_assoc($result)) {

					$attachments = get_article_enclosures($link, $line['id']);

					$article = array(
						"id" => $line["id"],
						"title" => $line["title"],
						"link" => $line["link"],
						"labels" => get_article_labels($link, $line['id']),
						"unread" => sql_bool_to_bool($line["unread"]),
						"marked" => sql_bool_to_bool($line["marked"]),
						"published" => sql_bool_to_bool($line["published"]),
						"comments" => $line["comments"],
						"author" => $line["author"],
						"updated" => strtotime($line["updated"]),
						"content" => $line["content"],
						"feed_id" => $line["feed_id"],
						"attachments" => $attachments
					);

313 314
					array_push($articles, $article);

315 316
				}
			}
Andrew Dolgov's avatar
Andrew Dolgov committed
317

318 319
			print api_wrap_reply(API_STATUS_OK, $seq, $articles);

Andrew Dolgov's avatar
Andrew Dolgov committed
320
			break;
321

Andrew Dolgov's avatar
Andrew Dolgov committed
322 323 324 325 326
		case "getConfig":
			$config = array(
				"icons_dir" => ICONS_DIR,
				"icons_url" => ICONS_URL);

327
			$config["daemon_is_running"] = file_is_locked("update_daemon.lock");
Andrew Dolgov's avatar
Andrew Dolgov committed
328 329 330 331 332 333 334

			$result = db_query($link, "SELECT COUNT(*) AS cf FROM
				ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);

			$num_feeds = db_fetch_result($result, 0, "cf");

			$config["num_feeds"] = (int)$num_feeds;
335

336
			print api_wrap_reply(API_STATUS_OK, $seq, $config);
Andrew Dolgov's avatar
Andrew Dolgov committed
337

Andrew Dolgov's avatar
Andrew Dolgov committed
338
			break;
Andrew Dolgov's avatar
Andrew Dolgov committed
339

Andrew Dolgov's avatar
Andrew Dolgov committed
340 341 342
		case "updateFeed":
			$feed_id = db_escape_string($_REQUEST["feed_id"]);

343
			update_rss_feed($link, $feed_id, true);
Andrew Dolgov's avatar
Andrew Dolgov committed
344

345
			print api_wrap_reply(API_STATUS_OK, $seq, array("status" => "OK"));
Andrew Dolgov's avatar
Andrew Dolgov committed
346

Andrew Dolgov's avatar
Andrew Dolgov committed
347 348
			break;

Andrew Dolgov's avatar
Andrew Dolgov committed
349 350
		case "catchupFeed":
			$feed_id = db_escape_string($_REQUEST["feed_id"]);
351
			$is_cat = db_escape_string($_REQUEST["is_cat"]);
Andrew Dolgov's avatar
Andrew Dolgov committed
352

Andrew Dolgov's avatar
Andrew Dolgov committed
353
			catchup_feed($link, $feed_id, $is_cat);
Andrew Dolgov's avatar
Andrew Dolgov committed
354

355
			print api_wrap_reply(API_STATUS_OK, $seq, array("status" => "OK"));
Andrew Dolgov's avatar
Andrew Dolgov committed
356 357 358

			break;

Andrew Dolgov's avatar
Andrew Dolgov committed
359 360
		case "getPref":
			$pref_name = db_escape_string($_REQUEST["pref_name"]);
361

362
			print api_wrap_reply(API_STATUS_OK, $seq,
363
				array("value" => get_pref($link, $pref_name)));
Andrew Dolgov's avatar
Andrew Dolgov committed
364
			break;
365

366
		default:
367
			print api_wrap_reply(API_STATUS_ERR, $seq,
368
				array("error" => 'UNKNOWN_METHOD'));
369 370
			break;

Andrew Dolgov's avatar
Andrew Dolgov committed
371 372 373
	}

	db_close($link);
374

Andrew Dolgov's avatar
Andrew Dolgov committed
375
?>