PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Documents/v4/scripts/output.php

https://github.com/joshuawdavidson/planwatch
PHP | 848 lines | 577 code | 148 blank | 123 comment | 174 complexity | 69a5f6709551bfd47626c2d207f62461 MD5 | raw file
Possible License(s): BSD-2-Clause
  1. <?php
  2. /*
  3. OUTPUT.php
  4. contains the output() function
  5. */
  6. // OUTPUT()
  7. //
  8. // outputs provided content.
  9. // calls output_html() or output_rss() as appropriate
  10. //------------------------------------------------------------------------------
  11. function output($title,$content,$disposition='browser')
  12. {
  13. $_SERVER['PLANOWNER_DISPLAY_NAME']=str_replace("'","",$_SERVER['PLANOWNER_DISPLAY_NAME']);
  14. $_SERVER['STOPWATCH']['content_end']=array_sum(explode(' ',microtime()));
  15. $_SERVER['STOPWATCH']['output_begin']=array_sum(explode(' ',microtime()));
  16. // if there is no cookie, user is 'guest'
  17. if (!$_SERVER['USER']) $_SERVER['USER']='guest';
  18. if ($_SERVER['OUTPUT_MODE']=='HTML')
  19. {
  20. Header("Content-type: text/html; charset=UTF-8");
  21. $page=output_html($title,$content);
  22. }
  23. if ($_SERVER['OUTPUT_MODE']=='IPHONE')
  24. {
  25. Header("Content-type: text/html; charset=UTF-8");
  26. $page=output_iphone($title,$content);
  27. }
  28. if ($_SERVER['OUTPUT_MODE']=='RSS' || strstr($_SERVER['OUTPUT_MODE'],'ATOM'))
  29. {
  30. Header("Content-type: text/xml; charset=UTF-8");
  31. $page=output_feed($title,$content);
  32. }
  33. if ($_SERVER['OUTPUT_MODE']=='AJAX')
  34. {
  35. Header("Content-type: text/html; charset=UTF-8");
  36. $page=output_ajax($title,$content);
  37. }
  38. if ($disposition=='return') return $page;
  39. if (strstr($disposition,$_SERVER['DOCUMENT_ROOT']))
  40. { file_write_contents($disposition,$page); return $page; }
  41. echo $page; exit;
  42. }
  43. // OUTPUT_HTML()
  44. //
  45. // outputs provided content as an HTML page
  46. // depends on formatting_html.php
  47. //------------------------------------------------------------------------------
  48. function output_html($title,$content)
  49. {
  50. require_once("formatting_html.php");
  51. // SKIN AND FONTS
  52. //------------------------------------------------------------------------------
  53. if ($hatespictures) $extracss = 'img { display: none; } #header img { display: inline; }';
  54. // WATCHED LIST
  55. //------------------------------------------------------------------------------
  56. if (!browser_is_modern())
  57. $testwatchlist=$planwatchlist=format_watched_list_html();
  58. else
  59. {
  60. $planwatchlist="&nbsp;";
  61. if ($_SERVER['USER_ROOT'] && file_exists("$_SERVER[USER_ROOT]/watchedlist.txt")) $testwatchlist=file_get_contents("$_SERVER[USER_ROOT]/watchedlist.txt");
  62. }
  63. // HTML <HEAD> TAGS
  64. // AND TOP LINKS & MENUS
  65. //------------------------------------------------------------------------------
  66. $_SERVER['STOPWATCH']['meta_begin']=array_sum(explode(' ',microtime()));
  67. $title=strip_tags($title);
  68. $extracss="<style type='text/css'>{$_SERVER['PLANOWNER_INFO']['css']}</style>";
  69. $thisurl="http://$_SERVER[HTTP_HOST]$web_root$_SERVER[REQUEST_URI]";
  70. // if we're writing or reading our own plan, load the editing javascript
  71. if (strstr($_SERVER[REQUEST_URI],'write') || $_SERVER['USER']==$_SERVER['PLANOWNER'])
  72. $extrajs.="\n<script type='text/javascript' src='/resources/javascript/setplan.js'></script>\n";
  73. // if we're writing, set up draft autosaves
  74. if (strstr($_SERVER[REQUEST_URI],'write'))
  75. $extrajs.="<script type='text/javascript'>setTimeout(\"saveDraft($_SERVER[PLAN_DRAFT_TIME]);\",61131);</script>";
  76. // if we're reading something besides an rss feed, set charset
  77. // to UTF-8. in the html5 template, everything's always set to UTF-8
  78. // and it doesn't seem to break anything. we can probably safely
  79. // remove this once we switch.
  80. if ($_SERVER['URL_ARRAY'][1]=='read' && strstr($urlarray[2],'http')) $encoding="<meta http-equiv='Content-type' content='text/html; charset=UTF-8' />";
  81. // not that anyone will pay attention, but go ahead and put a copyright
  82. // notice in.
  83. if ($_SERVER['PLANOWNER']) $copyright="<meta http-equiv='copyright' content='This plan is copyright ".date("Y")." $_SERVER[PLANOWNER_DISPLAY_NAME], all rights reserved.' />";
  84. // if we're looking at a nonprivate local plan, provide an rss feed
  85. if ($_SERVER['PLANOWNER'] && !plan_is_private($_SERVER['PLANOWNER']) && !plan_is_registered_only($_SERVER['PLANOWNER']) && plan_is_local($_SERVER['PLANOWNER']))
  86. {
  87. $alternate.="<link rel='alternate' type='application/rss+xml' title=\"$_SERVER[PLANOWNER_DISPLAY_NAME]'s RSS Feed\" href='http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]/rss' />\n";
  88. $alternate.="<link rel='alternate' type='application/atom+xml' title=\"$_SERVER[PLANOWNER_DISPLAY_NAME]'s Atom Feed\" href='http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]/atom' />\n";
  89. }
  90. // provide a link to the watched list feed
  91. if (user_is_valid($_SERVER['USERINFO_ARRAY']['username'],$_SERVER['USERINFO_ARRAY']['userpass']))
  92. $alternate.="\n<link rel='alternate' type='application/rss+xml' title='Watched Plans' href='http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]/watched/watched.rss' />\n";
  93. // use a different icon for plan pages
  94. if ($_SERVER['PLANOWNER']) $subimage="_plan";
  95. profile('meta');
  96. profile('menus');
  97. // ____ LOGO AND SITE NAME _______
  98. if (strlen($GLOBALS['pwlogo'])>1)
  99. {
  100. if (!strpos($GLOBALS['pwlogo'],'ttp://'))
  101. {
  102. $logosize=@getimagesize("$_SERVER[FILE_ROOT]/$GLOBALS[pwlogo]");
  103. $logoroot=$_SERVER['WEB_ROOT'];
  104. }
  105. else
  106. {
  107. $logosize=getimagesize("$GLOBALS[pwlogo]");
  108. $logoroot='';
  109. }
  110. $logostring="<img src='$logoroot$GLOBALS[pwlogo]' border='0' $logosize[3] align='absmiddle' />";
  111. }
  112. $sitename="<a href='$_SERVER[WEB_ROOT]/' id='sitename'>$logostring $GLOBALS[sitename]</a>";
  113. $titlesitename=trim(strip_tags($GLOBALS['sitename']));
  114. if (!$titlesitename) { $titlesitename='planwatch'; }
  115. // populates the nav buttons along the top of the page, along
  116. // with their menus.
  117. // TODO: maybe give offsite users a 'write' button tuned to their plan home?
  118. if (user_is_valid($_SERVER['USERINFO_ARRAY']['username'],$_SERVER['USERINFO_ARRAY']['userpass']))
  119. $toplinks=buttons_populate($content);
  120. profile('menus');
  121. // load GA if the user allows it
  122. if($_SERVER['USERINFO_ARRAY']['allow_analytics'])
  123. $analytics="<script type=\"text/javascript\">
  124. var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");
  125. document.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));
  126. </script>
  127. <script type=\"text/javascript\">
  128. try {
  129. var pageTracker = _gat._getTracker(\"UA-12269975-1\");
  130. pageTracker._trackPageview();
  131. } catch(err) {}</script>";
  132. // LOGIN FORM
  133. //------------------------------------------------------------------------------
  134. // If the reader isn't logged in, present a login form.
  135. if (!user_is_valid($_SERVER['USERINFO_ARRAY']['username'],$_SERVER['USERINFO_ARRAY']['userpass']))
  136. {
  137. $toplinks="
  138. <form action='$_SERVER[WEB_ROOT]/scripts/form_shim.php' method='post' name='loginForm'>
  139. user <input id='login_username' type='text' name='user' size='10'/>
  140. pass <input id='login_userpass' type='password' name='pass' size='6'/>
  141. <input type='checkbox' name='remember' id='remember' value='1'/>
  142. <label for='remember'>remember me</label>
  143. <input type='hidden' name='action' value='login'/>
  144. <input type='submit' name='action' value='login' onclick='document.forms.loginForm.submit();' />
  145. <input type='hidden' name='prevpage' value='".str_replace('/','!!',$thisurl)."'/>
  146. </form>\n";
  147. }
  148. // READER TOOLBAR
  149. //------------------------------------------------------------------------------
  150. // If the reader is logged in, and reading a plan, build the reader toolbar.
  151. if ($_SERVER['URL_ARRAY'][1]=='send')
  152. {
  153. $_SERVER['PLANOWNER']=$_SERVER['URL_ARRAY'][2];
  154. plan_get_owner_info($_SERVER['PLANOWNER']);
  155. }
  156. if (user_is_valid($_SERVER['USERINFO_ARRAY']['username'],$_SERVER['USERINFO_ARRAY']['userpass'])
  157. && $_SERVER['PLANOWNER'] && !strstr($content,'<h1>Plan Read Failed</h1>'))
  158. {
  159. profile('reader_toolbar','begin');
  160. $readertoolbar=output_build_reader_toolbar($content);
  161. profile('reader_toolbar','end');
  162. }
  163. // MESSAGEBAR
  164. //------------------------------------------------------------------------------
  165. if ($_SERVER['USERINFO_ARRAY']['username'])
  166. {
  167. if (!strpos($_SERVER['USERINFO_ARRAY']['real_name'],' '))
  168. {
  169. $message .= "<img src='$GLOBALS[toolsicon]'> <a href='$_SERVER[WEB_ROOT]/prefs/userinfo'>Click here to enter a valid (full) real name and make this annoying box go away.</a><br/>\n";
  170. }
  171. if(file_exists("$_SERVER[FILE_ROOT]/temp/system_message.txt"))
  172. {
  173. $message .= file_get_contents("$_SERVER[FILE_ROOT]/temp/system_message.txt")."<br/>\n";
  174. }
  175. }
  176. // SLOGAN
  177. //------------------------------------------------------------------------------
  178. // If the user allows slogans to be presented, go ahead and pick one.
  179. // (randomly, weighted by the popularity of the slogan)
  180. profile('slogans','begin');
  181. if (!$_SERVER['USERINFO_ARRAY']['no_slogans'])
  182. {
  183. include_once('slogan_functions.php');
  184. $slogan_a=slogans_get_one();
  185. $slogan="<span class='slogan' title='slogan #$slogan_a[1], submitted by $slogan_a[2], rated $slogan_a[3]' id='slogan_text'>$slogan_a[0]</span>";
  186. // only logged-in users can vote on slogans
  187. if ($_SERVER['USERINFO_ARRAY']['username'])
  188. {
  189. $slogan.="<span class='slogan' id='slogan_rating'>
  190. <a href=\"javascript:slogans_modify_one_rating('$slogan_a[1]','1');\" class='edit_links' title='mod this slogan up to ".($slogan_a[3]+1)."'>+</a>
  191. <a href=\"javascript:slogans_modify_one_rating('$slogan_a[1]','-1');\" class='edit_links' title='mod this slogan down to ".($slogan_a[3]-1)."'>-</a>\n
  192. </span>";
  193. }
  194. // only admins and slogan owners can edit slogans
  195. if ($_SERVER['USER']==$slogan_a[2] || user_is_administrator())
  196. {
  197. $slogan_js_edit=str_replace(array('"',"'"),array('~','`'),$slogan_a[0]);
  198. $slogan.=" [ <a class='edit_links' href=\"javascript:slogans_edit_one('$slogan_a[1]');\" title=\"edit this slogan. it is yours, after all.\">edit</a> ]";
  199. }
  200. }
  201. $_SERVER['STOPWATCH']['slogans_end']=array_sum(explode(' ',microtime()));
  202. // TEMPLATES AND HEADERS
  203. //------------------------------------------------------------------------------
  204. // header to make sure the pages aren't cached very long.
  205. // we send this right before the page load so it doesn't get in the way of other stuff.
  206. @Header("Expires: 240");
  207. // READ IN AND POPULATE THE TEMPLATE
  208. // everyone but modern browser users gets the lynx template starting with this version.
  209. if (browser_is_modern())
  210. {
  211. // load the HTML5 template if the user prefers
  212. // everyone will eventually get this automatically
  213. // once it's better tested
  214. if($_SERVER['USERINFO_ARRAY']['html5_template']==1)
  215. {
  216. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.default.html"));
  217. $doctype="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
  218. }
  219. else
  220. {
  221. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.html5.html"));
  222. $doctype="<!doctype html>\n";
  223. }
  224. //TODO: find a better solution than eval() for page output
  225. eval ("\$page=\"$page\";");
  226. $page=$doctype.$page;
  227. }
  228. else //if browser isn't modern, hand out the textmode template.
  229. {
  230. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.textmode.html"));
  231. eval ("\$page=\"$page\";");
  232. $page="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">".$page;
  233. }
  234. // planwatch_fixlinks adds session id to links that need it
  235. $page=planwatch_fixlinks($page);
  236. // close out the stopwatch
  237. profile('output','end'); profile('pageload','end');
  238. if(strstr($page,'TIME-->'))
  239. {
  240. $timestring=profile_display();
  241. $page=str_replace('<!--LOADTIME-->',$timestring,$page);
  242. $page=str_replace('<!--TIME-->',round_sigdig($_SERVER['STOPWATCH']['pageload_end']-$_SERVER['STOPWATCH']['pageload_begin'],2),$page);
  243. }
  244. // display the "errors" panel
  245. if ($_SERVER['ERRORS'] && $_SERVER['USER'])
  246. {
  247. $errortime=time();
  248. $page=str_replace('<!--ERRORS-->',"<a id='error_link' href=\"javascript:document.getElementById('error_report').style.display='block';void(null);\">Errors (click me to report)</a> <div id='error_report'>Errors <a href='/report/$errortime'>report to josh</a> <a href=\"javascript:document.getElementById('error_report').style.display='none';void(null);\">hide</a><br/>$_SERVER[ERRORS]</div>",$page);
  249. file_put_contents("$_SERVER[DOCUMENT_ROOT]/temp/$errortime.error","<h2>Error Messages:</h2>$_SERVER[ERRORS]<hr/><h2>Error Details:</h2>$_SERVER[ERROR_DETAILS]<hr/><h2>Debug Info</h2>$_SERVER[DEBUG_INFO]");
  250. }
  251. // display the "debug" panel for administrators
  252. if ($_SERVER['DEBUG_INFO'] && user_is_administrator())
  253. $page=str_replace('<!--DEBUG-->',"<a id='debug_link' href=\"javascript:document.getElementById('debug_report').style.display='block';void(null);\">debug</a> <div id='debug_report'>Debug Info <a href=\"javascript:document.getElementById('debug_report').style.display='none';void(null);\">hide</a><br/>$_SERVER[DEBUG_INFO]</div>",$page);
  254. return $page;
  255. }
  256. // OUTPUT_BUILD_READER_TOOLBAR($content)
  257. // TODO: merge with output_build_reader_toolbar_phone()
  258. function output_build_reader_toolbar($content)
  259. {
  260. if($_SERVER['OUTPUT_MODE']=='IPHONE' || $_SERVER['OUTPUT_MODE']=='MOBILE')
  261. return output_build_reader_toolbar_mobile($content);
  262. else return output_build_reader_toolbar_desktop($content);
  263. }
  264. // OUTPUT_BUILD_READER_TOOLBAR_DESKTOP($content)
  265. // TODO: merge with output_build_reader_toolbar_phone()
  266. function output_build_reader_toolbar_desktop($content)
  267. {
  268. if ($_SERVER['URL_ARRAY'][1]=='read'
  269. || ($_SERVER['URL_ARRAY'][1]=='send' && $_SERVER['URL_ARRAY'][2]))
  270. {
  271. // build a bio link if appropriate (and the bio isn't currently the content)
  272. if ((file_exists("$_SERVER[PWUSERS_DIR]/$_SERVER[PLANOWNER]/bio.txt") ||
  273. (strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'diaryland') ||
  274. strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'livejournal')))
  275. && !($_SERVER['URL_ARRAY'][3]=='bio'))
  276. {
  277. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER_REAL_LOCATION]/bio'>bio</a>\n";
  278. }
  279. if ((strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'planworld.net') ||
  280. strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'amherst.edu') ||
  281. plan_is_local($_SERVER['PLANOWNER']))
  282. && $_SERVER['PLANOWNER']!=$_SERVER['USER']
  283. && $_SERVER['URL_ARRAY'][1]!='send')
  284. {
  285. if(IS_JOSH)
  286. {
  287. $send_files=files_list("$_SERVER[USER_ROOT]/sends",files_encode_safe_name("$_SERVER[PLANOWNER]")."*");
  288. if(is_array($send_files))
  289. {
  290. $lastsend=formattime(filemtime("$_SERVER[USER_ROOT]/sends/".end($send_files)));
  291. if(strstr(end($send_files),'.new')) $lastsend.=" <b>NEW</b>";
  292. }
  293. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/send/$_SERVER[PLANOWNER_REAL_LOCATION]/'>send <span style='opacity: 0.5'>$lastsend</span></a>";
  294. }
  295. else
  296. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/send/$_SERVER[PLANOWNER_REAL_LOCATION]/'>send</a>\n";
  297. }
  298. // build a plan link instead if the reader is reading the bio or send
  299. if ($_SERVER['URL_ARRAY'][3]=='bio' || $_SERVER['URL_ARRAY'][1]=='send')
  300. {
  301. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER_REAL_LOCATION]' >plan</a>\n";
  302. }
  303. // build an archive link, if appropriate
  304. if (plan_has_archives($_SERVER['PLANOWNER_REAL_LOCATION']))
  305. {
  306. if (!in_array('archives',$_SERVER['URL_ARRAY']))
  307. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]/archives' >archives</a>\n";
  308. else
  309. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]' >plan</a>\n";
  310. }
  311. // If the reader isn't watching the writer, offer the option
  312. if (!stristr($testwatchlist,$_SERVER['PLANOWNER']) && !stristr($testwatchlist,$_SERVER['PLANOWNER_REAL_LOCATION']))
  313. {
  314. $readertoolbar[]="<span id='watch_link'><a class='action' href=\"javascript:loadXMLDoc('$_SERVER[WEB_ROOT]/lists/add_ajax/watched/!$_SERVER[PLANOWNER_REAL_LOCATION]:$_SERVER[PLANOWNER_DISPLAY_NAME]!',null,'planwatch');void(null);\" title='add $_SERVER[PLANOWNER_DISPLAY_NAME] to your watched list' >watch</a></span>\n";
  315. }
  316. // if the reader *is* watching the writer, offer removal
  317. else
  318. {
  319. $readertoolbar[]="<span id='watch_link'><a class='action' href=\"javascript:loadXMLDoc('$_SERVER[WEB_ROOT]/lists/remove_ajax/watched/$_SERVER[PLANOWNER_REAL_LOCATION]',null,'planwatch');void(null);\" title='remove $_SERVER[PLANOWNER_DISPLAY_NAME] from your watched list' >unwatch</a></span>\n";
  320. }
  321. // if writer isn't a blog or the same as reader, offer the option of
  322. // blocking, unblocking, allowing, or disallowing access to reader's plan
  323. if ($_SERVER['PLANOWNER']!=$_SERVER['USER'] && !strpos($_SERVER['PLANOWNER'],'://'))
  324. {
  325. if (!user_is_blocked($_SERVER['USER'],$_SERVER[PLANOWNER]))
  326. {
  327. $readertoolbar[]="<a class='action' href='$_SERVER[WEB_ROOT]/lists/add/blocked/$_SERVER[PLANOWNER]' title='block $_SERVER[PLANOWNER_DISPLAY_NAME] from reading your plan altogether' >block</a>\n";
  328. }
  329. else
  330. {
  331. $readertoolbar[]="<a class='action' href='$_SERVER[WEB_ROOT]/lists/remove/blocked/$_SERVER[PLANOWNER]' title='unblock $_SERVER[PLANOWNER_DISPLAY_NAME] so they can read your public plan again' >unblock</a>\n";
  332. }
  333. if (!user_is_authorized($_SERVER['USER'],$_SERVER[PLANOWNER]))
  334. {
  335. $readertoolbar[]="<a class='action' href='$_SERVER[WEB_ROOT]/lists/add/allowed/$_SERVER[PLANOWNER]' title='allow $_SERVER[PLANOWNER_DISPLAY_NAME] to read your private plan' >allow</a>\n";
  336. }
  337. else
  338. {
  339. $readertoolbar[]="<a class='action' href='$_SERVER[WEB_ROOT]/lists/remove/allowed/$_SERVER[PLANOWNER]' title='disallow $_SERVER[PLANOWNER_DISPLAY_NAME] from reading your private plan'>disallow</a>\n";
  340. }
  341. // offer administrators a link to masquerade as writer
  342. // this is so it's easy to follow up on plan-reported bugs
  343. if (user_is_administrator()
  344. && file_exists("$_SERVER[PWUSERS_DIR]/$_SERVER[PLANOWNER]/userinfo.dat"))
  345. {
  346. $readertoolbar[]="<a class='action' href='$_SERVER[WEB_ROOT]/masq/on/$_SERVER[PLANOWNER]'>masq</a>";
  347. }
  348. $readertoolbar[]="<a class='action' href='/lists/unread/$_SERVER[PLANOWNER]'>unread</a>";
  349. }
  350. if ($_SERVER['PLANOWNER'] && $_SERVER['PLANOWNER']==$_SERVER['USER'] && !strpos($_SERVER['PLANOWNER'],'@') && browser_is_modern())
  351. {
  352. $readertoolbar[]="<a class='action' href='/write'>new entry</a>";
  353. }
  354. // make the links into a string for output.
  355. foreach($readertoolbar as $tool)
  356. {
  357. if(strstr($tool,'action')) $class=" class='action' ";
  358. else $class='';
  359. $readertoolbar_html .= "<li $class>$tool</li>";
  360. }
  361. $readertoolbar = "\n<li class='listheader'>$_SERVER[PLANOWNER_DISPLAY_NAME]</li>".$readertoolbar_html;
  362. if(IS_JOSH)
  363. {
  364. if ($lasttime=plan_get_last_update($_SERVER['PLANOWNER']))
  365. {
  366. $readertoolbar.="<li class='action' style='font-size: 80%; float: right;'>updated ".formattime($lasttime)."</li>";
  367. }
  368. if ($lastlogin = plan_get_last_login($_SERVER['PLANOWNER']))
  369. {
  370. if (trim($lastlogin) && $lastlogin>0) $readertoolbar.="<li class='action' style='font-size: 80%; float: right;'>active ".formattime($lastlogin)."</li>";
  371. }
  372. }
  373. else
  374. {
  375. if ($lasttime=plan_get_last_update($_SERVER['PLANOWNER']))
  376. {
  377. $readertoolbar.="<li class='plan_data_block'>Last Update: ".formattime($lasttime)."</li>";
  378. }
  379. if ($lastlogin = plan_get_last_login($_SERVER['PLANOWNER']))
  380. {
  381. if (trim($lastlogin) && $lastlogin>0) $readertoolbar.="<li class='plan_data_block' id='lastaction'>Last Action: ".formattime($lastlogin)."</li>";
  382. }
  383. }
  384. }
  385. return $readertoolbar;
  386. }
  387. // OUTPUT_BUILD_READER_TOOLBAR_MOBILE($content)
  388. //------------------------------------------------------------------------------
  389. // If the reader is logged in, and reading a plan, build the reader toolbar.
  390. function output_build_reader_toolbar_mobile($content)
  391. {
  392. if ($_SERVER['URL_ARRAY'][3]=='bio') $is_bio=TRUE;
  393. elseif ($_SERVER['URL_ARRAY'][1]=='send') $is_send=TRUE;
  394. elseif (in_array('archives',$_SERVER['URL_ARRAY'])) $is_archives=TRUE;
  395. else $is_plan=TRUE;
  396. $planwatchlist=file_get_contents("$_SERVER[USER_ROOT]/watchedlist.txt");
  397. if ($is_send)
  398. {
  399. $_SERVER['PLANOWNER']=$_SERVER['URL_ARRAY'][2];
  400. plan_get_owner_info($_SERVER['PLANOWNER']);
  401. }
  402. if (user_is_valid($_SERVER['USERINFO_ARRAY']['username'],$_SERVER['USERINFO_ARRAY']['userpass'])
  403. && $_SERVER['PLANOWNER'] && !strstr($content,'<h1>Plan Read Failed</h1>'))
  404. {
  405. profile('reader_toolbar','begin');
  406. if ($is_plan || $is_bio || $is_archives || ($is_send && $_SERVER['URL_ARRAY'][2]))
  407. {
  408. // bio
  409. if ((file_exists("$_SERVER[PWUSERS_DIR]/$_SERVER[PLANOWNER]/bio.txt") ||
  410. (strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'diaryland') ||
  411. strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'livejournal')))
  412. && !$is_bio)
  413. {
  414. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER_REAL_LOCATION]/bio'>bio</a>";
  415. }
  416. // send
  417. if ((strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'planworld.net') ||
  418. strpos($_SERVER['PLANOWNER_REAL_LOCATION'],'amherst.edu') ||
  419. plan_is_local($_SERVER['PLANOWNER']))
  420. && $_SERVER['PLANOWNER']!=$_SERVER['USER']
  421. && !$is_send)
  422. {
  423. $send_files=files_list("$_SERVER[USER_ROOT]/sends",files_encode_safe_name("$_SERVER[PLANOWNER]")."*");
  424. if(is_array($send_files))
  425. {
  426. $lastsend=formattime(filemtime("$_SERVER[USER_ROOT]/sends/".end($send_files)));
  427. if(strstr(end($send_files),'.new')) $lastsend.=" <b>NEW</b>";
  428. $lastsend="($lastsend)";
  429. }
  430. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/send/$_SERVER[PLANOWNER_REAL_LOCATION]/'>send</a>";
  431. }
  432. // planread
  433. if ($is_send || $is_bio)
  434. {
  435. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER_REAL_LOCATION]/'>plan</a>";
  436. }
  437. // archives
  438. if (plan_has_archives($_SERVER['PLANOWNER_REAL_LOCATION']))
  439. {
  440. if (!$is_archives)
  441. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]/archives' >archives</a>";
  442. else
  443. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]' >plan</a>";
  444. }
  445. // If the reader isn't watching the writer, offer the option
  446. if (!stristr($planwatchlist,$_SERVER['PLANOWNER']) && $is_plan)
  447. {
  448. $readertoolbar[]="<span id='watch_link'><a href=\"javascript:loadXMLDoc('$_SERVER[WEB_ROOT]/lists/add_ajax/watched/!$_SERVER[PLANOWNER_REAL_LOCATION]:$_SERVER[PLANOWNER_DISPLAY_NAME]!',null,'planwatch');void(null);\" title='add $_SERVER[PLANOWNER_DISPLAY_NAME] to your watched list' >watch</a></span>";
  449. }
  450. // if writer isn't a blog or the same as reader, offer the option of
  451. // blocking, unblocking, allowing, or disallowing access to reader's plan
  452. if ($_SERVER['PLANOWNER']!=$_SERVER['USER'] && !strpos($_SERVER['PLANOWNER'],'://'))
  453. {
  454. // offer administrators a link to masquerade as writer
  455. // this is so it's easy to follow up on plan-reported bugs
  456. if (user_is_administrator()
  457. && file_exists("$_SERVER[PWUSERS_DIR]/$_SERVER[PLANOWNER]/userinfo.dat"))
  458. {
  459. $readertoolbar[]="<a href='$_SERVER[WEB_ROOT]/masq/on/$_SERVER[PLANOWNER]'>masq</a>";
  460. }
  461. if ($is_plan) $readertoolbar[]="<a href='/lists/unread/$_SERVER[PLANOWNER]'>unread</a>";
  462. if ($is_send) $readertoolbar[]="<a href='/send/$_SERVER[PLANOWNER]/unread'>unread</a>";
  463. }
  464. // make the links into a string for output.
  465. $readertoolbar = "<li class='toolbutton'>".implode("</li><li class='toolbutton'>",$readertoolbar)."</li>\n";
  466. $readertoolbar = str_replace("<li class='toolbutton'></li>","",$readertoolbar);
  467. if (($lasttime=plan_get_last_update($_SERVER['PLANOWNER'])) && $is_plan)
  468. {
  469. $readertoolbar="<li class='plan_data_block'>Last Update: ".formattime($lasttime)."</li>".$readertoolbar;
  470. }
  471. if ($lastlogin = plan_get_last_login($_SERVER['PLANOWNER']))
  472. {
  473. if ($lastlogin > 1) $readertoolbar="<li class='plan_data_block' id='lastaction'>Last Action: ".formattime($lastlogin)."</li>".$readertoolbar;
  474. }
  475. }
  476. profile('reader_toolbar','end');
  477. }
  478. return $readertoolbar;
  479. }
  480. //function output_iphone($title,$content) { output_mobile($title,$content); }
  481. // OUTPUT_MOBILE()
  482. //
  483. // outputs iphone-formatted page. depends on iui library, template.iphone.html
  484. //------------------------------------------------------------------------------
  485. function output_iphone($title,$content)
  486. {
  487. if (strstr($_SERVER['REQUEST_URI'],'/watched') || $_SERVER['REQUEST_URI']=='/') $current='watchedtab';
  488. if (strstr($_SERVER['REQUEST_URI'],'/send')) $current='sendtab';
  489. if (strstr($_SERVER['REQUEST_URI'],'/tools')) $current='toolstab';
  490. if (strstr($_SERVER['REQUEST_URI'],'/snitch')) $current='snitchtab';
  491. if (strstr($_SERVER['REQUEST_URI'],'/write')) $current='writetab';
  492. if (strstr($_SERVER['REQUEST_URI'],'/read')) $current='NULL';
  493. if (strstr($_SERVER['REQUEST_URI'],'/read') || strstr($_SERVER['REQUEST_URI'],'/send') || strstr($_SERVER['REQUEST_URI'],'/bio'))
  494. {
  495. $readertoolbar="<ul id='reader_toolbar'>".output_build_reader_toolbar($content)."</ul>";
  496. }
  497. $extracss="<style type='text/css'>{$_SERVER['PLANOWNER_INFO']['css']}</style>";
  498. if ($_SERVER['USER'] && $_SERVER['USER']!='guest') $tabbar="
  499. <ul class=\"tabbar\">
  500. <li id='writetab'><a id='write' onclick='setCurrent(\"writetab\");' href=\"/write/\">Write</a></li>
  501. <li id='snitchtab'><a id='snitch' onclick='setCurrent(\"snitchtab\");void(0);' href=\"/snitch/\">Snitch</a></li>
  502. <li id='sendtab'><a id='send' onclick='setCurrent(\"sendtab\");void(0);' href=\"/send/\">Send</a></li>
  503. <li id='watchedtab'><a id='watched' onclick='setCurrent(\"watchedtab\");void(0);' href=\"/\">Watched</a></li>
  504. <!--<li style='border: 0px; background: transparent;'>&nbsp;</li>-->
  505. <!--<li id='viewtab'><a id='view' onclick='setCurrent(\"viewtab\");void(0);' href=\"/read/$_SERVER[USER]\">View</a></li>-->
  506. <li id='xtab' ><a onclick='setCurrent(\"xtab\");void(0);' href='/logout' style='color: $GLOBALS[listsbgcolor]; font-weight: bold;'>&nbsp; X &nbsp;</a></li>
  507. <li id='toolstab' ><a id='tools' style='color: $GLOBALS[listsbgcolor]; font-weight: bold;' onclick='setCurrent(\"toolstab\");void(0);' href=\"/tools/\">&#x2699;</a></li>
  508. </ul>\n";
  509. else $tabbar="<!--
  510. <ul class=\"tabbar\">
  511. <li id='logintab'>Log In to Planwatch</li>
  512. </ul>-->\n";
  513. if (agent_is_lowfi())
  514. {
  515. $tabbar=str_replace(array("<ul","</ul>","<li","</li>"),array("<div","</div>"," [<span","</span>] "),$tabbar);
  516. $content=str_replace(array("<ul","</ul>","<li","</li>"),array("<div","</div>"," <div","</div> "),$content);
  517. $tabbar=str_replace(array("<ul","</ul>","<li","</li>"),array("<div","</div>","<span","</span>"),$tabbar);
  518. $tabbar=str_replace("> X <",">Logout<",$tabbar);
  519. $tabbar.="<hr />";
  520. }
  521. // READ IN AND POPULATE THE TEMPLATE
  522. if (((!strstr($_SERVER['HTTP_REFERER'],'iphone.planwatch') && !strstr($_SERVER['HTTP_REFERER'],'m.planwatch') && !strstr($_SERVER['HTTP_REFERER'],'m2.planwatch')) || $_COOKIE['redirected']=="1" || agent_is_lowfi()) && !strstr($_SERVER['REQUEST_URI'],'ajax'))
  523. {
  524. $cookie_host=$_SERVER['HTTP_HOST'];
  525. if (substr_count($cookie_host,'.') < 2) $cookie_host=".$cookie_host";
  526. $cookie_host=str_replace('www','',$cookie_host);
  527. setcookie("redirected","0",time()-1,$_SERVER['WEB_ROOT']."/",$cookie_host);
  528. $res_dir="$_SERVER[FILE_ROOT]/resources/";
  529. $version=max(
  530. filemtime("$res_dir/javascript/ajax.js"),
  531. filemtime("$res_dir/javascript/iphone_ajax.js"),
  532. filemtime("$res_dir/javascript/iui.js"),
  533. filemtime("$res_dir/templates/iui.css"),
  534. filemtime("$res_dir/templates/rss.css"),
  535. filemtime("$res_dir/templates/atom.css")
  536. );
  537. $page=str_replace("/includes/","/includes/$version/",$page);
  538. if($_SERVER['HTTP_HOST']=='m2.planwatch.org')
  539. {
  540. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.iui3.html"));
  541. if (strstr($page,'</body>')) $page=str_replace('</body>',"<script type='application/x-javascript'>setCurrent('$current');</script>\n</body>",$page);
  542. else $page.="n<script type='application/x-javascript'>setCurrent('$current');</script>";
  543. eval ("\$page=\"$page\";");
  544. $page="<!DOCTYPE html>".$page;
  545. }
  546. else
  547. {
  548. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.iphone.html"));
  549. if (strstr($page,'</body>')) $page=str_replace('</body>',"<script type='application/x-javascript'>setCurrent('$current');</script>\n</body>",$page);
  550. else $page.="n<script type='application/x-javascript'>setCurrent('$current');</script>";
  551. eval ("\$page=\"$page\";");
  552. $page=str_replace(array("& ","&& "),array("&amp;","&amp;&amp;"),$page);
  553. $page="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">".$page;
  554. }
  555. }
  556. else { $page="<div class='main_content' title='$title' id='$_SERVER[QUERY_STRING]'><style type='text/css'>{$_SERVER['PLANOWNER_INFO']['css']}</style>$readertoolbar $content</div>\n<script type='application/x-javascript'>setCurrent('$current');</script>"; }
  557. @Header("Expires: 240");
  558. @Header("Cache-control: max-age=240, must-revalidate");
  559. return $page;
  560. }
  561. // OUTPUT_FEED()
  562. //
  563. // outputs provided content as an rss feed
  564. // depends on formatting_rss.php
  565. //------------------------------------------------------------------------------
  566. function output_feed($title,$content)
  567. {
  568. if (strstr($content,'FEED_DIVIDER'))
  569. {
  570. $content=explode("<!-- FEED_DIVIDER -->",$content);
  571. $items=$content[0];
  572. $plan=$content[1];
  573. }
  574. else $plan=$content;
  575. if ($_SERVER['PLANOWNER'])
  576. {
  577. $rss_link = "http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]/read/$_SERVER[PLANOWNER]";
  578. }
  579. else
  580. {
  581. $rss_link = "http://$_SERVER[HTTP_HOST]$_SERVER[WEB_ROOT]/home";
  582. }
  583. $thisDate = gmdate('Y-m-d\TH:i:s+00:00');
  584. $thisYear = gmdate('Y');
  585. $fullcount=substr_count($plan,"<entry");
  586. // select a template based on feed type
  587. if ($_SERVER['OUTPUT_MODE']=='RSS')
  588. {
  589. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.rss_1.0.xml"));
  590. }
  591. if ($_SERVER['OUTPUT_MODE']=='ATOM0.3')
  592. {
  593. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.atom0.3.xml"));
  594. }
  595. if ($_SERVER['OUTPUT_MODE']=='ATOM1.0')
  596. {
  597. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.atom.xml"));
  598. }
  599. if ($_SERVER['OUTPUT_MODE']=='ATOM_PRIVATE')
  600. {
  601. $page=str_replace('"','\"',file_get_contents("$_SERVER[FILE_ROOT]/resources/templates/template.atom.xml"));
  602. }
  603. eval ("\$page=\"$page\";");
  604. return $page;
  605. }
  606. // OUTPUT_AJAX()
  607. //
  608. // outputs provided content as plain data for AJAX
  609. //------------------------------------------------------------------------------
  610. function output_ajax($title,$content)
  611. {
  612. // i am really serious about not caching ajax content. any of these directives
  613. // should be sufficient, but i am going ahead and issuing all of them just
  614. // to be on the safe side
  615. header("Cache-control: no-cache");
  616. header("Cache-control: no-store");
  617. header("Pragma: no-cache");
  618. header("Expires: 0");
  619. // the title attribute has no purpose ajax output, so we just send back the content.
  620. return $content;
  621. }
  622. // OUTPUT_SET_MODE
  623. // defines the output mode.
  624. // called near the beginning of the load process
  625. function output_set_mode()
  626. {
  627. // assume we're outputting HTML for the moment.
  628. // TODO: transition from polluting $_SERVER to using the constant
  629. // TODO: add a JSON output mode
  630. $_SERVER['OUTPUT_MODE']='HTML';
  631. // these tests determine if the output mode should be something else
  632. if ((strpos($_SERVER['REQUEST_URI'],'/rss')
  633. || strpos($_SERVER['REQUEST_URI'],'/rdf'))
  634. && !strpos($_SERVER['REQUEST_URI'],'http'))
  635. $_SERVER['OUTPUT_MODE']='RSS';
  636. if ((strpos($_SERVER['REQUEST_URI'],'/atom')
  637. || strpos($_SERVER['REQUEST_URI'],'/xml'))
  638. && !strpos($_SERVER['REQUEST_URI'],'http'))
  639. $_SERVER['OUTPUT_MODE']='ATOM1.0';
  640. // TODO: we can probably safely dispense with atom0.3
  641. if ((strpos($_SERVER['REQUEST_URI'],'/atom0.3')
  642. && !strpos($_SERVER['REQUEST_URI'],'http')))
  643. $_SERVER['OUTPUT_MODE']='ATOM0.3';
  644. // most ajax returns have their own code path, but some of them
  645. // just use the same path as the regular request with "/ajax" at the end.
  646. // this takes care of those.
  647. if ((strpos($_SERVER['REQUEST_URI'],'/ajax')
  648. && !strpos($_SERVER['REQUEST_URI'],'http')
  649. && !strpos($_SERVER['REQUEST_URI'],'ajax.js')))
  650. $_SERVER['OUTPUT_MODE']='AJAX';
  651. // sets up for mobile output.
  652. if (stristr($_SERVER['HTTP_HOST'],'iphone')
  653. || stristr($_SERVER['HTTP_HOST'],'m.')
  654. || ($_SERVER['HTTP_HOST']=="planwatch.org" && is_mobile() && $_COOKIE['forceview']!="desktop")
  655. || ($_SERVER['HTTP_HOST']=="www.planwatch.org" && is_mobile() && $_COOKIE['forceview']!="desktop")
  656. || $_COOKIE['forceview']=="mobile")
  657. $_SERVER['OUTPUT_MODE']='IPHONE';
  658. // yes, i know non-iphones are being used.
  659. // this will eventually change to "MOBILE" once
  660. // i get around to changing it everywhere.
  661. // sets up for beta mobile output
  662. if (stristr($_SERVER['HTTP_HOST'],'m2.'))
  663. $_SERVER['OUTPUT_MODE']='IPHONE';
  664. // sets up for desktop view on mobile device
  665. if (stristr($_SERVER['HTTP_HOST'],'d.pl')
  666. || $_COOKIE['forceview']=="desktop")
  667. $_SERVER['OUTPUT_MODE']='HTML';
  668. // if we're being read from a blackberry, be very agressive
  669. // about cache-clearing
  670. // this may belong somewhere else
  671. if (stristr($_SERVER['HTTP_USER_AGENT'],'blackberry'))
  672. {
  673. header('Cache-Control: max-age=0'); // must-revalidate
  674. header('Expires: '.gmdate('D, d M Y H:i:s', time()).' GMT');
  675. header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
  676. header('ETag: ' . md5(rand(0,10000)));
  677. }
  678. return $_SERVER['OUTPUT_MODE'];
  679. }
  680. ?>