]> git.wh0rd.org - tt-rss.git/blame - classes/handler/public.php
rename url_to_tag_uri to a more relevant name
[tt-rss.git] / classes / handler / public.php
CommitLineData
5f0a3741 1<?php
369dbc19 2class Handler_Public extends Handler {
5f0a3741 3
79178062 4 private function generate_syndicated_feed($owner_uid, $feed, $is_cat,
ca5d9be4 5 $limit, $offset, $search, $search_mode,
d1e631f3 6 $view_mode = false, $format = 'atom', $order = false, $orig_guid = false, $start_ts = false) {
79178062
AD
7
8 require_once "lib/MiniTemplator.class.php";
9
10 $note_style = "background-color : #fff7d5;
11 border-width : 1px; ".
12 "padding : 5px; border-style : dashed; border-color : #e7d796;".
13 "margin-bottom : 1em; color : #9a8c59;";
14
2faef834 15 if (!$limit) $limit = 60;
79178062 16
8aa01d79 17 $date_sort_field = "date_entered DESC, updated DESC";
84c53d0e 18 $date_check_field = "date_entered";
79178062 19
84c53d0e 20 if ($feed == -2 && !$is_cat) {
7ef7dd31 21 $date_sort_field = "last_published DESC";
84c53d0e
AD
22 $date_check_field = "last_published";
23 } else if ($feed == -1 && !$is_cat) {
7ef7dd31 24 $date_sort_field = "last_marked DESC";
84c53d0e
AD
25 $date_check_field = "last_marked";
26 }
008ebad9 27
25051fb8
AD
28 switch ($order) {
29 case "title":
30 $date_sort_field = "ttrss_entries.title";
31 break;
32 case "date_reverse":
33 $date_sort_field = "date_entered, updated";
34 break;
35 case "feed_dates":
36 $date_sort_field = "updated DESC";
37 break;
38 }
39
d1e631f3
AD
40 //function queryFeedHeadlines($feed, $limit, $view_mode, $cat_view, $search, $search_mode, $override_order = false, $offset = 0, $owner_uid = 0, $filter = false, $since_id = 0, $include_children = false, $ignore_vfeed_group = false, $override_strategy = false, $override_vfeed = false, $start_ts = false) {
41
a42c55f0 42 $qfh_ret = queryFeedHeadlines($feed,
2e35a707
AD
43 1, $view_mode, $is_cat, $search, $search_mode,
44 $date_sort_field, $offset, $owner_uid,
9b1e5918 45 false, 0, true, true, false, false, $start_ts);
2e35a707
AD
46
47 $result = $qfh_ret[0];
48
d9c85e0f 49 if ($this->dbh->num_rows($result) != 0) {
84c53d0e
AD
50
51 $ts = strtotime($this->dbh->fetch_result($result, 0, $date_check_field));
2e35a707
AD
52
53 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
d6ba77f3 54 strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $ts) {
2e35a707
AD
55 header('HTTP/1.0 304 Not Modified');
56 return;
57 }
58
59 $last_modified = gmdate("D, d M Y H:i:s", $ts) . " GMT";
60 header("Last-Modified: $last_modified", true);
61 }
62
a42c55f0 63 $qfh_ret = queryFeedHeadlines($feed,
79178062 64 $limit, $view_mode, $is_cat, $search, $search_mode,
8aa01d79 65 $date_sort_field, $offset, $owner_uid,
9b1e5918 66 false, 0, true, true, false, false, $start_ts);
79178062 67
2e35a707 68
79178062
AD
69 $result = $qfh_ret[0];
70 $feed_title = htmlspecialchars($qfh_ret[1]);
71 $feed_site_url = $qfh_ret[2];
4a80c57c 72 /* $last_error = $qfh_ret[3]; */
79178062
AD
73
74 $feed_self_url = get_self_url_prefix() .
39119f02
JT
75 "/public.php?op=rss&id=$feed&key=" .
76 get_feed_access_key($feed, false, $owner_uid);
79178062
AD
77
78 if (!$feed_site_url) $feed_site_url = get_self_url_prefix();
79
2ebf38a9
AD
80 if ($format == 'atom') {
81 $tpl = new MiniTemplator;
79178062 82
2ebf38a9 83 $tpl->readTemplateFromFile("templates/generated_feed.txt");
79178062 84
2ebf38a9
AD
85 $tpl->setVariable('FEED_TITLE', $feed_title, true);
86 $tpl->setVariable('VERSION', VERSION, true);
87 $tpl->setVariable('FEED_URL', htmlspecialchars($feed_self_url), true);
79178062 88
2ebf38a9
AD
89 if (PUBSUBHUBBUB_HUB && $feed == -2) {
90 $tpl->setVariable('HUB_URL', htmlspecialchars(PUBSUBHUBBUB_HUB), true);
91 $tpl->addBlock('feed_hub');
92 }
79178062 93
2ebf38a9 94 $tpl->setVariable('SELF_URL', htmlspecialchars(get_self_url_prefix()), true);
d9c85e0f 95 while ($line = $this->dbh->fetch_assoc($result)) {
bf5bcb8e 96 $line["content_preview"] = truncate_string(strip_tags($line["content"]), 100, '...');
bc262b67 97
891e36f5 98 foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
99 $line = $p->hook_query_headlines($line);
100 }
2e35a707 101
fcf6bfba
AD
102 $tpl->setVariable('ARTICLE_ID',
103 htmlspecialchars($orig_guid ? $line['link'] :
f75e7c64 104 $this->make_article_tag_uri($line['id'], $line['date_entered'])), true);
2ebf38a9
AD
105 $tpl->setVariable('ARTICLE_LINK', htmlspecialchars($line['link']), true);
106 $tpl->setVariable('ARTICLE_TITLE', htmlspecialchars($line['title']), true);
67631438 107 $tpl->setVariable('ARTICLE_EXCERPT', $line["content_preview"], true);
79178062 108
4b19d4ac
AD
109 $content = sanitize($line["content"], false, $owner_uid,
110 $feed_site_url);
79178062 111
2ebf38a9
AD
112 if ($line['note']) {
113 $content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" .
114 $content;
e9c6e27d 115 $tpl->setVariable('ARTICLE_NOTE', htmlspecialchars($line['note']), true);
116 }
2ebf38a9
AD
117
118 $tpl->setVariable('ARTICLE_CONTENT', $content, true);
119
120 $tpl->setVariable('ARTICLE_UPDATED_ATOM',
121 date('c', strtotime($line["updated"])), true);
122 $tpl->setVariable('ARTICLE_UPDATED_RFC822',
123 date(DATE_RFC822, strtotime($line["updated"])), true);
124
125 $tpl->setVariable('ARTICLE_AUTHOR', htmlspecialchars($line['author']), true);
126
4b7391de 127 $tpl->setVariable('ARTICLE_SOURCE_LINK', htmlspecialchars($line['site_url'] ? $line["site_url"] : get_self_url_prefix()), true);
0ee126ee 128 $tpl->setVariable('ARTICLE_SOURCE_TITLE', htmlspecialchars($line['feed_title'] ? $line['feed_title'] : $feed_title), true);
2ebf38a9 129
a42c55f0 130 $tags = get_article_tags($line["id"], $owner_uid);
2ebf38a9
AD
131
132 foreach ($tags as $tag) {
133 $tpl->setVariable('ARTICLE_CATEGORY', htmlspecialchars($tag), true);
134 $tpl->addBlock('category');
135 }
79178062 136
a42c55f0 137 $enclosures = get_article_enclosures($line["id"]);
79178062 138
2ebf38a9
AD
139 foreach ($enclosures as $e) {
140 $type = htmlspecialchars($e['content_type']);
141 $url = htmlspecialchars($e['content_url']);
4b7391de 142 $length = $e['duration'] ? $e['duration'] : 1;
9c97041d 143
2ebf38a9
AD
144 $tpl->setVariable('ARTICLE_ENCLOSURE_URL', $url, true);
145 $tpl->setVariable('ARTICLE_ENCLOSURE_TYPE', $type, true);
146 $tpl->setVariable('ARTICLE_ENCLOSURE_LENGTH', $length, true);
79178062 147
2ebf38a9
AD
148 $tpl->addBlock('enclosure');
149 }
79178062 150
2ebf38a9 151 $tpl->addBlock('entry');
79178062
AD
152 }
153
2ebf38a9
AD
154 $tmp = "";
155
156 $tpl->addBlock('feed');
157 $tpl->generateOutputToString($tmp);
158
10bdeb4b
AD
159 if (@!$_REQUEST["noxml"]) {
160 header("Content-Type: text/xml; charset=utf-8");
161 } else {
162 header("Content-Type: text/plain; charset=utf-8");
163 }
2ebf38a9
AD
164
165 print $tmp;
166 } else if ($format == 'json') {
79178062 167
2ebf38a9 168 $feed = array();
79178062 169
2ebf38a9
AD
170 $feed['title'] = $feed_title;
171 $feed['version'] = VERSION;
172 $feed['feed_url'] = $feed_self_url;
79178062 173
2ebf38a9
AD
174 if (PUBSUBHUBBUB_HUB && $feed == -2) {
175 $feed['hub_url'] = PUBSUBHUBBUB_HUB;
79178062
AD
176 }
177
2ebf38a9
AD
178 $feed['self_url'] = get_self_url_prefix();
179
180 $feed['articles'] = array();
181
d9c85e0f 182 while ($line = $this->dbh->fetch_assoc($result)) {
575a5287 183 $line["content_preview"] = truncate_string(strip_tags($line["content_preview"]), 100, '...');
891e36f5 184 foreach (PluginHost::getInstance()->get_hooks(PluginHost::HOOK_QUERY_HEADLINES) as $p) {
185 $line = $p->hook_query_headlines($line, 100);
186 }
2ebf38a9 187 $article = array();
79178062 188
2ebf38a9
AD
189 $article['id'] = $line['link'];
190 $article['link'] = $line['link'];
191 $article['title'] = $line['title'];
67631438 192 $article['excerpt'] = $line["content_preview"];
891e36f5 193 $article['content'] = sanitize($line["content"], false, $owner_uid);
2ebf38a9 194 $article['updated'] = date('c', strtotime($line["updated"]));
79178062 195
2ebf38a9
AD
196 if ($line['note']) $article['note'] = $line['note'];
197 if ($article['author']) $article['author'] = $line['author'];
79178062 198
a42c55f0 199 $tags = get_article_tags($line["id"], $owner_uid);
2ebf38a9
AD
200
201 if (count($tags) > 0) {
202 $article['tags'] = array();
203
204 foreach ($tags as $tag) {
205 array_push($article['tags'], $tag);
206 }
207 }
208
a42c55f0 209 $enclosures = get_article_enclosures($line["id"]);
2ebf38a9
AD
210
211 if (count($enclosures) > 0) {
212 $article['enclosures'] = array();
213
214 foreach ($enclosures as $e) {
215 $type = $e['content_type'];
216 $url = $e['content_url'];
217 $length = $e['duration'];
218
219 array_push($article['enclosures'], array("url" => $url, "type" => $type, "length" => $length));
220 }
221 }
222
223 array_push($feed['articles'], $article);
224 }
225
10bdeb4b 226 header("Content-Type: text/json; charset=utf-8");
2ebf38a9
AD
227 print json_encode($feed);
228
229 } else {
230 header("Content-Type: text/plain; charset=utf-8");
231 print json_encode(array("error" => array("message" => "Unknown format")));
232 }
79178062
AD
233 }
234
5f0a3741 235 function getUnread() {
d9c85e0f 236 $login = $this->dbh->escape_string($_REQUEST["login"]);
5f0a3741
AD
237 $fresh = $_REQUEST["fresh"] == "1";
238
d9c85e0f 239 $result = $this->dbh->query("SELECT id FROM ttrss_users WHERE login = '$login'");
5f0a3741 240
d9c85e0f
AD
241 if ($this->dbh->num_rows($result) == 1) {
242 $uid = $this->dbh->fetch_result($result, 0, "id");
5f0a3741 243
a42c55f0 244 print getGlobalUnread($uid);
5f0a3741
AD
245
246 if ($fresh) {
247 print ";";
a42c55f0 248 print getFeedArticles(-3, false, true, $uid);
5f0a3741
AD
249 }
250
251 } else {
252 print "-1;User not found";
253 }
254
255 }
256
257 function getProfiles() {
d9c85e0f 258 $login = $this->dbh->escape_string($_REQUEST["login"]);
5f0a3741 259
0806d68b 260 $result = $this->dbh->query("SELECT ttrss_settings_profiles.* FROM ttrss_settings_profiles,ttrss_users
97acbaf1 261 WHERE ttrss_users.id = ttrss_settings_profiles.owner_uid AND login = '$login' ORDER BY title");
5f0a3741 262
eeee2ccf 263 print "<select dojoType='dijit.form.Select' style='width : 220px; margin : 0px' name='profile'>";
5f0a3741 264
97acbaf1 265 print "<option value='0'>" . __("Default profile") . "</option>";
5f0a3741 266
d9c85e0f 267 while ($line = $this->dbh->fetch_assoc($result)) {
97acbaf1
AD
268 $id = $line["id"];
269 $title = $line["title"];
5f0a3741 270
97acbaf1 271 print "<option value='$id'>$title</option>";
5f0a3741 272 }
97acbaf1
AD
273
274 print "</select>";
5f0a3741
AD
275 }
276
277 function pubsub() {
d9c85e0f 278 $mode = $this->dbh->escape_string($_REQUEST['hub_mode']);
43d790f0
AD
279 if (!$mode) $mode = $this->dbh->escape_string($_REQUEST['hub.mode']);
280
d9c85e0f
AD
281 $feed_id = (int) $this->dbh->escape_string($_REQUEST['id']);
282 $feed_url = $this->dbh->escape_string($_REQUEST['hub_topic']);
5f0a3741 283
43d790f0
AD
284 if (!$feed_url) $feed_url = $this->dbh->escape_string($_REQUEST['hub.topic']);
285
5f0a3741
AD
286 if (!PUBSUBHUBBUB_ENABLED) {
287 header('HTTP/1.0 404 Not Found');
43d790f0 288 echo "404 Not found (Disabled by server)";
5f0a3741
AD
289 return;
290 }
291
292 // TODO: implement hub_verifytoken checking
43d790f0
AD
293 // TODO: store requested rel=self or whatever for verification
294 // (may be different from stored feed url) e.g. http://url/ or http://url
5f0a3741 295
d9c85e0f 296 $result = $this->dbh->query("SELECT feed_url FROM ttrss_feeds
5f0a3741
AD
297 WHERE id = '$feed_id'");
298
d9c85e0f 299 if ($this->dbh->num_rows($result) != 0) {
5f0a3741 300
d9c85e0f 301 $check_feed_url = $this->dbh->fetch_result($result, 0, "feed_url");
5f0a3741 302
43d790f0
AD
303 // ignore url checking for the time being
304 if ($check_feed_url && (true || $check_feed_url == $feed_url || !$feed_url)) {
5f0a3741
AD
305 if ($mode == "subscribe") {
306
d9c85e0f 307 $this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 2
5f0a3741
AD
308 WHERE id = '$feed_id'");
309
310 print $_REQUEST['hub_challenge'];
311 return;
312
313 } else if ($mode == "unsubscribe") {
314
d9c85e0f 315 $this->dbh->query("UPDATE ttrss_feeds SET pubsub_state = 0
5f0a3741
AD
316 WHERE id = '$feed_id'");
317
318 print $_REQUEST['hub_challenge'];
319 return;
320
321 } else if (!$mode) {
322
323 // Received update ping, schedule feed update.
a42c55f0 324 //update_rss_feed($feed_id, true, true);
5f0a3741 325
d9c85e0f 326 $this->dbh->query("UPDATE ttrss_feeds SET
5f0a3741
AD
327 last_update_started = '1970-01-01',
328 last_updated = '1970-01-01' WHERE id = '$feed_id'");
329
330 }
331 } else {
332 header('HTTP/1.0 404 Not Found');
43d790f0 333 echo "404 Not found (URL check failed)";
5f0a3741
AD
334 }
335 } else {
336 header('HTTP/1.0 404 Not Found');
43d790f0 337 echo "404 Not found (Feed not found)";
5f0a3741
AD
338 }
339
340 }
341
342 function logout() {
343 logout_user();
344 header("Location: index.php");
345 }
346
5f0a3741 347 function share() {
d9c85e0f 348 $uuid = $this->dbh->escape_string($_REQUEST["key"]);
5f0a3741 349
d9c85e0f 350 $result = $this->dbh->query("SELECT ref_id, owner_uid FROM ttrss_user_entries WHERE
5f0a3741
AD
351 uuid = '$uuid'");
352
d9c85e0f 353 if ($this->dbh->num_rows($result) != 0) {
5f0a3741
AD
354 header("Content-Type: text/html");
355
d9c85e0f
AD
356 $id = $this->dbh->fetch_result($result, 0, "ref_id");
357 $owner_uid = $this->dbh->fetch_result($result, 0, "owner_uid");
5f0a3741 358
a42c55f0 359 $article = format_article($id, false, true, $owner_uid);
5f0a3741
AD
360
361 print_r($article['content']);
362
363 } else {
364 print "Article not found.";
365 }
366
367 }
368
369 function rss() {
d9c85e0f
AD
370 $feed = $this->dbh->escape_string($_REQUEST["id"]);
371 $key = $this->dbh->escape_string($_REQUEST["key"]);
356e13b1 372 $is_cat = sql_bool_to_bool($_REQUEST["is_cat"]);
d9c85e0f
AD
373 $limit = (int)$this->dbh->escape_string($_REQUEST["limit"]);
374 $offset = (int)$this->dbh->escape_string($_REQUEST["offset"]);
5f0a3741 375
d9c85e0f
AD
376 $search = $this->dbh->escape_string($_REQUEST["q"]);
377 $search_mode = $this->dbh->escape_string($_REQUEST["smode"]);
378 $view_mode = $this->dbh->escape_string($_REQUEST["view-mode"]);
25051fb8 379 $order = $this->dbh->escape_string($_REQUEST["order"]);
d1e631f3 380 $start_ts = $this->dbh->escape_string($_REQUEST["ts"]);
5f0a3741 381
d9c85e0f 382 $format = $this->dbh->escape_string($_REQUEST['format']);
5bcb7b61 383 $orig_guid = sql_bool_to_bool($_REQUEST["orig_guid"]);
2ebf38a9
AD
384
385 if (!$format) $format = 'atom';
386
5f0a3741 387 if (SINGLE_USER_MODE) {
a42c55f0 388 authenticate_user("admin", null);
5f0a3741
AD
389 }
390
391 $owner_id = false;
392
393 if ($key) {
d9c85e0f 394 $result = $this->dbh->query("SELECT owner_uid FROM
5f0a3741
AD
395 ttrss_access_keys WHERE access_key = '$key' AND feed_id = '$feed'");
396
d9c85e0f
AD
397 if ($this->dbh->num_rows($result) == 1)
398 $owner_id = $this->dbh->fetch_result($result, 0, "owner_uid");
5f0a3741
AD
399 }
400
401 if ($owner_id) {
2fb947eb 402 $this->generate_syndicated_feed($owner_id, $feed, $is_cat, $limit,
d1e631f3 403 $offset, $search, $search_mode, $view_mode, $format, $order, $orig_guid, $start_ts);
5f0a3741
AD
404 } else {
405 header('HTTP/1.1 403 Forbidden');
406 }
407 }
408
910592b4 409 function updateTask() {
4a80c57c 410 PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", false);
910592b4
AD
411 }
412
4e5ddeaf 413 function housekeepingTask() {
4a80c57c 414 PluginHost::getInstance()->run_hooks(PluginHost::HOOK_HOUSE_KEEPING, "hook_house_keeping", false);
4e5ddeaf
AD
415 }
416
07391e36 417 function globalUpdateFeeds() {
113c3dec 418 RPC::updaterandomfeed_real($this->dbh);
cda55d67 419
4a80c57c 420 PluginHost::getInstance()->run_hooks(PluginHost::HOOK_UPDATE_TASK, "hook_update_task", false);
07391e36 421 }
8361e724
AD
422
423 function sharepopup() {
61a748f8 424 if (SINGLE_USER_MODE) {
6322ac79 425 login_sequence();
61a748f8
AD
426 }
427
8361e724 428 header('Content-Type: text/html; charset=utf-8');
d0ee0f52
AD
429 print "<html><head><title>Tiny Tiny RSS</title>
430 <link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
431 <link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
9a2aed91 432
cdbcb277 433 echo stylesheet_tag("css/utility.css");
6214a076 434 echo stylesheet_tag("css/dijit.css");
cdbcb277 435 echo javascript_tag("lib/prototype.js");
6214a076 436 echo javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,controls");
9a2aed91
AD
437 print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
438 </head><body id='sharepopup'>";
8361e724
AD
439
440 $action = $_REQUEST["action"];
441
442 if ($_SESSION["uid"]) {
443
d493aba2 444 if ($action == 'share') {
8361e724 445
d9c85e0f
AD
446 $title = $this->dbh->escape_string(strip_tags($_REQUEST["title"]));
447 $url = $this->dbh->escape_string(strip_tags($_REQUEST["url"]));
448 $content = $this->dbh->escape_string(strip_tags($_REQUEST["content"]));
449 $labels = $this->dbh->escape_string(strip_tags($_REQUEST["labels"]));
8361e724 450
a42c55f0 451 Article::create_published_article($title, $url, $content, $labels,
1b4d1a6b 452 $_SESSION["uid"]);
8361e724 453
d493aba2
AD
454 print "<script type='text/javascript'>";
455 print "window.close();";
456 print "</script>";
8361e724 457
d493aba2 458 } else {
8361e724
AD
459 $title = htmlspecialchars($_REQUEST["title"]);
460 $url = htmlspecialchars($_REQUEST["url"]);
461
d493aba2 462 ?>
8361e724 463
d493aba2
AD
464 <table height='100%' width='100%'><tr><td colspan='2'>
465 <h1><?php echo __("Share with Tiny Tiny RSS") ?></h1>
466 </td></tr>
8361e724 467
d493aba2 468 <form id='share_form' name='share_form'>
8361e724 469
d493aba2
AD
470 <input type="hidden" name="op" value="sharepopup">
471 <input type="hidden" name="action" value="share">
8361e724 472
22439dad 473 <tr><td align='right'><?php echo __("Title:") ?></td>
d493aba2 474 <td width='80%'><input name='title' value="<?php echo $title ?>"></td></tr>
22439dad 475 <tr><td align='right'><?php echo __("URL:") ?></td>
d493aba2 476 <td><input name='url' value="<?php echo $url ?>"></td></tr>
22439dad 477 <tr><td align='right'><?php echo __("Content:") ?></td>
d493aba2 478 <td><input name='content' value=""></td></tr>
1b4d1a6b
AD
479 <tr><td align='right'><?php echo __("Labels:") ?></td>
480 <td><input name='labels' id="labels_value"
481 placeholder='Alpha, Beta, Gamma' value="">
482 </td></tr>
483
484 <tr><td>
485 <div class="autocomplete" id="labels_choices"
486 style="display : block"></div></td></tr>
8361e724 487
d493aba2 488 <script type='text/javascript'>document.forms[0].title.focus();</script>
8361e724 489
1b4d1a6b
AD
490 <script type='text/javascript'>
491 new Ajax.Autocompleter('labels_value', 'labels_choices',
492 "backend.php?op=rpc&method=completeLabels",
493 { tokens: ',', paramName: "search" });
494 </script>
495
d493aba2
AD
496 <tr><td colspan='2'>
497 <div style='float : right' class='insensitive-small'>
498 <?php echo __("Shared article will appear in the Published feed.") ?>
499 </div>
500 <button type="submit"><?php echo __('Share') ?></button>
501 <button onclick="return window.close()"><?php echo __('Cancel') ?></button>
502 </div>
8361e724 503
d493aba2
AD
504 </form>
505 </td></tr></table>
506 </body></html>
507 <?php
8361e724 508
8361e724
AD
509 }
510
511 } else {
512
d493aba2
AD
513 $return = urlencode($_SERVER["REQUEST_URI"])
514 ?>
515
516 <form action="public.php?return=<?php echo $return ?>"
22439dad 517 method="POST" id="loginForm" name="loginForm">
d493aba2
AD
518
519 <input type="hidden" name="op" value="login">
520
521 <table height='100%' width='100%'><tr><td colspan='2'>
22439dad 522 <h1><?php echo __("Not logged in") ?></h1></td></tr>
d493aba2
AD
523
524 <tr><td align="right"><?php echo __("Login:") ?></td>
525 <td align="right"><input name="login"
526 value="<?php echo $_SESSION["fake_login"] ?>"></td></tr>
527 <tr><td align="right"><?php echo __("Password:") ?></td>
528 <td align="right"><input type="password" name="password"
529 value="<?php echo $_SESSION["fake_password"] ?>"></td></tr>
d493aba2
AD
530 <tr><td colspan='2'>
531 <button type="submit">
532 <?php echo __('Log in') ?></button>
533
534 <button onclick="return window.close()">
535 <?php echo __('Cancel') ?></button>
536 </td></tr>
537 </table>
538
539 </form>
540 <?php
8361e724
AD
541 }
542 }
543
97acbaf1 544 function login() {
97acbaf1
AD
545 if (!SINGLE_USER_MODE) {
546
d9c85e0f 547 $login = $this->dbh->escape_string($_POST["login"]);
97acbaf1 548 $password = $_POST["password"];
aadd636a 549 $remember_me = $_POST["remember_me"];
97acbaf1 550
f231f438
AD
551 if ($remember_me) {
552 session_set_cookie_params(SESSION_COOKIE_LIFETIME);
553 } else {
554 session_set_cookie_params(0);
555 }
556
aadd636a 557 @session_start();
60ed4c9a 558
a42c55f0 559 if (authenticate_user($login, $password)) {
97acbaf1
AD
560 $_POST["password"] = "";
561
b18d109f
AD
562 if (get_schema_version() >= 120) {
563 $_SESSION["language"] = get_pref("USER_LANGUAGE", $_SESSION["uid"]);
564 }
565
a42c55f0 566 $_SESSION["ref_schema_version"] = get_schema_version(true);
97acbaf1
AD
567 $_SESSION["bw_limit"] = !!$_POST["bw_limit"];
568
569 if ($_POST["profile"]) {
570
d9c85e0f 571 $profile = $this->dbh->escape_string($_POST["profile"]);
97acbaf1 572
d9c85e0f 573 $result = $this->dbh->query("SELECT id FROM ttrss_settings_profiles
97acbaf1
AD
574 WHERE id = '$profile' AND owner_uid = " . $_SESSION["uid"]);
575
d9c85e0f 576 if ($this->dbh->num_rows($result) != 0) {
97acbaf1 577 $_SESSION["profile"] = $profile;
97acbaf1
AD
578 }
579 }
580 } else {
581 $_SESSION["login_error_msg"] = __("Incorrect username or password");
fd94d631 582 user_error("Failed login attempt for $login from {$_SERVER['REMOTE_ADDR']}", E_USER_WARNING);
97acbaf1
AD
583 }
584
585 if ($_REQUEST['return']) {
586 header("Location: " . $_REQUEST['return']);
587 } else {
588 header("Location: " . SELF_URL_PATH);
589 }
590 }
591 }
592
f7439d69 593 /* function subtest() {
97b7d5c0
AD
594 header("Content-type: text/plain; charset=utf-8");
595
596 $url = $_REQUEST["url"];
597
598 print "$url\n\n";
599
600
601 print_r(get_feeds_from_html($url, fetch_file_contents($url)));
602
f7439d69 603 } */
97b7d5c0 604
97acbaf1 605 function subscribe() {
61a748f8 606 if (SINGLE_USER_MODE) {
6322ac79 607 login_sequence();
61a748f8
AD
608 }
609
97acbaf1
AD
610 if ($_SESSION["uid"]) {
611
d9c85e0f 612 $feed_url = $this->dbh->escape_string(trim($_REQUEST["feed_url"]));
97acbaf1
AD
613
614 header('Content-Type: text/html; charset=utf-8');
615 print "<html>
616 <head>
617 <title>Tiny Tiny RSS</title>
5bbc4bb4 618 <link rel=\"stylesheet\" type=\"text/css\" href=\"css/utility.css\">
97acbaf1 619 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
d0ee0f52
AD
620 <link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
621 <link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">
622
97acbaf1
AD
623 </head>
624 <body>
884d1650 625 <img class=\"floatingLogo\" src=\"images/logo_small.png\"
97acbaf1 626 alt=\"Tiny Tiny RSS\"/>
884d1650 627 <h1>".__("Subscribe to feed...")."</h1><div class='content'>";
97acbaf1 628
a42c55f0 629 $rc = subscribe_to_feed($feed_url);
97acbaf1
AD
630
631 switch ($rc['code']) {
632 case 0:
633 print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
634 break;
635 case 1:
636 print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
637 break;
638 case 2:
639 print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
640 break;
641 case 3:
642 print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
643 break;
644 case 4:
645 print_notice(__("Multiple feed URLs found."));
759e5132 646 $feed_urls = $rc["feeds"];
97acbaf1
AD
647 break;
648 case 5:
649 print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
650 break;
651 }
652
653 if ($feed_urls) {
654
655 print "<form action=\"public.php\">";
656 print "<input type=\"hidden\" name=\"op\" value=\"subscribe\">";
657
658 print "<select name=\"feed_url\">";
659
660 foreach ($feed_urls as $url => $name) {
661 $url = htmlspecialchars($url);
662 $name = htmlspecialchars($name);
663
664 print "<option value=\"$url\">$name</option>";
665 }
666
667 print "<input type=\"submit\" value=\"".__("Subscribe to selected feed").
668 "\">";
669
670 print "</form>";
671 }
672
673 $tp_uri = get_self_url_prefix() . "/prefs.php";
674 $tt_uri = get_self_url_prefix();
675
676 if ($rc['code'] <= 2){
d9c85e0f 677 $result = $this->dbh->query("SELECT id FROM ttrss_feeds WHERE
97acbaf1
AD
678 feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
679
d9c85e0f 680 $feed_id = $this->dbh->fetch_result($result, 0, "id");
97acbaf1
AD
681 } else {
682 $feed_id = 0;
683 }
684 print "<p>";
685
686 if ($feed_id) {
687 print "<form method=\"GET\" style='display: inline'
688 action=\"$tp_uri\">
689 <input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
690 <input type=\"hidden\" name=\"method\" value=\"editFeed\">
691 <input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
692 <input type=\"submit\" value=\"".__("Edit subscription options")."\">
693 </form>";
694 }
695
696 print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
697 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
698 </form></p>";
699
884d1650 700 print "</div></body></html>";
97acbaf1
AD
701
702 } else {
6322ac79 703 render_login_form();
97acbaf1
AD
704 }
705 }
706
97acbaf1
AD
707 function index() {
708 header("Content-Type: text/plain");
709 print json_encode(array("error" => array("code" => 7)));
710 }
711
f43e9e97 712 function forgotpass() {
67e0cf9a
AD
713 startup_gettext();
714
5303f9a7
AD
715 @$hash = $_REQUEST["hash"];
716
f43e9e97 717 header('Content-Type: text/html; charset=utf-8');
d0ee0f52
AD
718 print "<html><head><title>Tiny Tiny RSS</title>
719 <link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
720 <link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">";
e216d302 721
cdbcb277
AD
722 echo stylesheet_tag("css/utility.css");
723 echo javascript_tag("lib/prototype.js");
e216d302
AD
724
725 print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
726 </head><body id='forgotpass'>";
f43e9e97 727
884d1650 728 print '<div class="floatingLogo"><img src="images/logo_small.png"></div>';
483f15d5 729 print "<h1>".__("Password recovery")."</h1>";
884d1650 730 print "<div class='content'>";
f43e9e97
AD
731
732 @$method = $_POST['method'];
733
5303f9a7
AD
734 if ($hash) {
735 $login = $_REQUEST["login"];
736
737 if ($login) {
738 $result = $this->dbh->query("SELECT id, resetpass_token FROM ttrss_users
739 WHERE login = '$login'");
740
741 if ($this->dbh->num_rows($result) != 0) {
742 $id = $this->dbh->fetch_result($result, 0, "id");
743 $resetpass_token_full = $this->dbh->fetch_result($result, 0, "resetpass_token");
744 list($timestamp, $resetpass_token) = explode(":", $resetpass_token_full);
745
746 if ($timestamp && $resetpass_token &&
747 $timestamp >= time() - 15*60*60 &&
748 $resetpass_token == $hash) {
749
750 $result = $this->dbh->query("UPDATE ttrss_users SET resetpass_token = NULL
751 WHERE id = $id");
752
753 Pref_Users::resetUserPassword($id, true);
754
755 print "<p>"."Completed."."</p>";
756
757 } else {
758 print_error("Some of the information provided is missing or incorrect.");
759 }
760 } else {
761 print_error("Some of the information provided is missing or incorrect.");
762 }
763 } else {
764 print_error("Some of the information provided is missing or incorrect.");
765 }
766
767 print "<form method=\"GET\" action=\"index.php\">
768 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
769 </form>";
770
771 } else if (!$method) {
772 print_notice(__("You will need to provide valid account name and email. A password reset link will be sent to your email address."));
483f15d5 773
f43e9e97 774 print "<form method='POST' action='public.php'>";
f43e9e97
AD
775 print "<input type='hidden' name='method' value='do'>";
776 print "<input type='hidden' name='op' value='forgotpass'>";
777
778 print "<fieldset>";
779 print "<label>".__("Login:")."</label>";
780 print "<input type='text' name='login' value='' required>";
781 print "</fieldset>";
782
783 print "<fieldset>";
784 print "<label>".__("Email:")."</label>";
785 print "<input type='email' name='email' value='' required>";
786 print "</fieldset>";
787
788 print "<fieldset>";
789 print "<label>".__("How much is two plus two:")."</label>";
790 print "<input type='text' name='test' value='' required>";
791 print "</fieldset>";
792
793 print "<p/>";
794 print "<button type='submit'>".__("Reset password")."</button>";
795
796 print "</form>";
797 } else if ($method == 'do') {
798
d9c85e0f
AD
799 $login = $this->dbh->escape_string($_POST["login"]);
800 $email = $this->dbh->escape_string($_POST["email"]);
801 $test = $this->dbh->escape_string($_POST["test"]);
f43e9e97
AD
802
803 if (($test != 4 && $test != 'four') || !$email || !$login) {
804 print_error(__('Some of the required form parameters are missing or incorrect.'));
805
483f15d5
AD
806 print "<form method=\"GET\" action=\"public.php\">
807 <input type=\"hidden\" name=\"op\" value=\"forgotpass\">
808 <input type=\"submit\" value=\"".__("Go back")."\">
809 </form>";
f43e9e97 810
e216d302 811 } else {
f43e9e97 812
5303f9a7
AD
813 print_notice("Password reset instructions are being sent to your email address.");
814
d9c85e0f 815 $result = $this->dbh->query("SELECT id FROM ttrss_users
f43e9e97
AD
816 WHERE login = '$login' AND email = '$email'");
817
d9c85e0f
AD
818 if ($this->dbh->num_rows($result) != 0) {
819 $id = $this->dbh->fetch_result($result, 0, "id");
f43e9e97 820
5303f9a7
AD
821 if ($id) {
822 $resetpass_token = sha1(get_random_bytes(128));
823 $resetpass_link = get_self_url_prefix() . "/public.php?op=forgotpass&hash=" . $resetpass_token .
824 "&login=" . urlencode($login);
825
826 require_once 'classes/ttrssmailer.php';
827 require_once "lib/MiniTemplator.class.php";
828
829 $tpl = new MiniTemplator;
830
831 $tpl->readTemplateFromFile("templates/resetpass_link_template.txt");
832
833 $tpl->setVariable('LOGIN', $login);
834 $tpl->setVariable('RESETPASS_LINK', $resetpass_link);
835
836 $tpl->addBlock('message');
837
838 $message = "";
f43e9e97 839
5303f9a7 840 $tpl->generateOutputToString($message);
483f15d5 841
5303f9a7
AD
842 $mail = new ttrssMailer();
843
844 $rc = $mail->quickMail($email, $login,
845 __("[tt-rss] Password reset request"),
846 $message, false);
847
848 if (!$rc) print_error($mail->ErrorInfo);
849
850 $resetpass_token_full = $this->dbh->escape_string(time() . ":" . $resetpass_token);
851
852 $result = $this->dbh->query("UPDATE ttrss_users
853 SET resetpass_token = '$resetpass_token_full'
854 WHERE login = '$login' AND email = '$email'");
855
856 //Pref_Users::resetUserPassword($id, false);
857
858 print "<p>";
859
860 print "<p>"."Completed."."</p>";
861 } else {
862 print_error("User ID not found.");
863 }
483f15d5
AD
864
865 print "<form method=\"GET\" action=\"index.php\">
866 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
867 </form>";
f43e9e97
AD
868
869 } else {
870 print_error(__("Sorry, login and email combination not found."));
483f15d5
AD
871
872 print "<form method=\"GET\" action=\"public.php\">
873 <input type=\"hidden\" name=\"op\" value=\"forgotpass\">
874 <input type=\"submit\" value=\"".__("Go back")."\">
875 </form>";
876
f43e9e97 877 }
f43e9e97
AD
878 }
879
880 }
881
884d1650 882 print "</div>";
f43e9e97
AD
883 print "</body>";
884 print "</html>";
885
b4c47f7e
AD
886 }
887
888 function dbupdate() {
67e0cf9a
AD
889 startup_gettext();
890
f240d26e
AD
891 if (!SINGLE_USER_MODE && $_SESSION["access_level"] < 10) {
892 $_SESSION["login_error_msg"] = __("Your access level is insufficient to run this script.");
6322ac79 893 render_login_form();
f240d26e
AD
894 exit;
895 }
896
897 ?><html>
898 <head>
899 <title>Database Updater</title>
900 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5bbc4bb4 901 <link rel="stylesheet" type="text/css" href="css/utility.css"/>
d0ee0f52
AD
902 <link rel=\"shortcut icon\" type=\"image/png\" href=\"images/favicon.png\">
903 <link rel=\"icon\" type=\"image/png\" sizes=\"72x72\" href=\"images/favicon-72px.png\">
f240d26e
AD
904 </head>
905 <style type="text/css">
906 span.ok { color : #009000; font-weight : bold; }
907 span.err { color : #ff0000; font-weight : bold; }
908 </style>
909 <body>
910 <script type='text/javascript'>
911 function confirmOP() {
912 return confirm("Update the database?");
913 }
914 </script>
915
916 <div class="floatingLogo"><img src="images/logo_small.png"></div>
917
918 <h1><?php echo __("Database Updater") ?></h1>
919
920 <div class="content">
921
922 <?php
923 @$op = $_REQUEST["subop"];
0630a100 924 $updater = new DbUpdater(Db::get(), DB_TYPE, SCHEMA_VERSION);
f240d26e
AD
925
926 if ($op == "performupdate") {
927 if ($updater->isUpdateRequired()) {
928
929 print "<h2>Performing updates</h2>";
930
931 print "<h3>Updating to schema version " . SCHEMA_VERSION . "</h3>";
932
933 print "<ul>";
934
935 for ($i = $updater->getSchemaVersion() + 1; $i <= SCHEMA_VERSION; $i++) {
936 print "<li>Performing update up to version $i...";
937
938 $result = $updater->performUpdateTo($i);
939
940 if (!$result) {
941 print "<span class='err'>FAILED!</span></li></ul>";
942
943 print_warning("One of the updates failed. Either retry the process or perform updates manually.");
944 print "<p><form method=\"GET\" action=\"index.php\">
945 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
946 </form>";
947
948 break;
949 } else {
950 print "<span class='ok'>OK!</span></li>";
951 }
952 }
953
954 print "</ul>";
b4c47f7e 955
f240d26e 956 print_notice("Your Tiny Tiny RSS database is now updated to the latest version.");
b4c47f7e 957
f240d26e
AD
958 print "<p><form method=\"GET\" action=\"index.php\">
959 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
960 </form>";
961
962 } else {
963 print "<h2>Your database is up to date.</h2>";
964
965 print "<p><form method=\"GET\" action=\"index.php\">
966 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
967 </form>";
968 }
969 } else {
970 if ($updater->isUpdateRequired()) {
971
972 print "<h2>Database update required</h2>";
b4c47f7e 973
f240d26e
AD
974 print "<h3>";
975 printf("Your Tiny Tiny RSS database needs update to the latest version: %d to %d.",
976 $updater->getSchemaVersion(), SCHEMA_VERSION);
977 print "</h3>";
b4c47f7e 978
f240d26e 979 print_warning("Please backup your database before proceeding.");
b4c47f7e 980
f240d26e
AD
981 print "<form method='POST'>
982 <input type='hidden' name='subop' value='performupdate'>
983 <input type='submit' onclick='return confirmOP()' value='".__("Perform updates")."'>
984 </form>";
985
986 } else {
987
3c200461 988 print_notice("Tiny Tiny RSS database is up to date.");
f240d26e
AD
989
990 print "<p><form method=\"GET\" action=\"index.php\">
991 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
992 </form>";
993
994 }
995 }
996 ?>
b4c47f7e 997
f240d26e
AD
998 </div>
999 </body>
1000 </html>
1001 <?php
f43e9e97
AD
1002 }
1003
0c6f7b31
AD
1004 function cached_image() {
1005 @$hash = basename($_GET['hash']);
1006
1007 if ($hash) {
1008
1009 $filename = CACHE_DIR . '/images/' . $hash . '.png';
1010
1011 if (file_exists($filename)) {
1012 /* See if we can use X-Sendfile */
1013 $xsendfile = false;
1014 if (function_exists('apache_get_modules') &&
1015 array_search('mod_xsendfile', apache_get_modules()))
1016 $xsendfile = true;
1017
1018 if ($xsendfile) {
1019 header("X-Sendfile: $filename");
1020 header("Content-type: application/octet-stream");
1021 header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
1022 } else {
1023 header("Content-type: image/png");
1024 $stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT";
1025 header("Last-Modified: $stamp", true);
1026 readfile($filename);
1027 }
1028 } else {
1029 header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
1030 echo "File not found.";
1031 }
1032 }
1033 }
1034
f75e7c64 1035 private function make_article_tag_uri($id, $timestamp) {
4b7391de
AD
1036
1037 $timestamp = date("Y-m-d", strtotime($timestamp));
1038
1039 return "tag:" . parse_url(get_self_url_prefix(), PHP_URL_HOST) . ",$timestamp:/$id";
1040 }
5f0a3741
AD
1041}
1042?>