<?
/* sips -- the simple, integrated publishing system
* Copyright (C) 2000 Haakon Nilsen <hide@address.com>
*
* $Id: stories.inc.php,v 1.4 2001/02/10 18:59:27 haakon Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
include $config["sipssys"] ."/code/timezones.inc.php";
function getStoryIDs($numberofstories) {
global $config;
$returnedStories = 0;
$handle = opendir($config["sipssys"] ."/stories");
while ($file = readdir($handle)) {
if (($file != ".") && ($file != "..") && ($file != "topics") && ($file != "count") && ($file != "CVS")) { // the "CVS" test is just for local testing
$years[] = $file;
}
}
closedir($handle);
if (count($years) > 0) rsort($years);
$yearno = 0;
while (($returnedStories < $numberofstories) && ($yearno < count($years))) {
$monthno = 0;
$yearhandle = opendir($config["sipssys"] ."/stories/" .$years[$yearno]);
while ($file = readdir($yearhandle)) {
if (($file != ".") && ($file != "..")) {
$months[] = (int)$file;
}
}
closedir($yearhandle);
rsort($months);
while (($monthno < count($months)) && ($returnedStories < $numberofstories)) {
$dayno = 0;
$monthhandle = opendir($config["sipssys"] ."/stories/" .$years[$yearno] ."/" .$months[$monthno]);
while ($file = readdir($monthhandle)) {
if (($file != ".") && ($file != "..")) {
$days[] = (int)$file;
}
}
closedir($monthhandle);
rsort($days);
while (($dayno < count($days)) && ($returnedStories < $numberofstories)) {
$dayhandle = opendir($config["sipssys"] ."/stories/" .$years[$yearno] ."/" .$months[$monthno] ."/" .$days[$dayno]);
while ($file = readdir($dayhandle)) {
if (($file != ".") && ($file != "..")) {
$ar[] = (int)$file;
}
}
closedir($dayhandle);
rsort($ar);
for ($i = 0; (($i < count($ar)) && ($returnedStories < $numberofstories)); $i++) {
$arts[] = $years[$yearno] ."/" .$months[$monthno] ."/" .$days[$dayno] ."/" .$ar[$i];
$returnedStories++;
}
unset($ar);
$dayno++;
}
unset($days);
$monthno++;
}
unset($months);
$yearno++;
}
return $arts;
}
function getStoryIDsBefore($storiesbefore, $numberofstories) {
global $config;
$returnedStories = 0;
$before = explode("/", $storiesbefore);
$art = (int)$before[count($before)-1];
$day = (int)$before[count($before)-2];
$month = (int)$before[count($before)-3];
$year = (int)$before[count($before)-4];
while ($returnedStories < $numberofstories) {
$handle = opendir($config["sipssys"] ."/stories/$year/$month/$day");
while ($file = readdir($handle)) {
if (($file != ".") && ($file != "..")) {
$fno[] = (int)$file;
}
}
closedir($handle);
rsort($fno);
for ($i = 0; (($i < count($fno)) && ($returnedStories < $numberofstories)); $i++) {
if ($fno[$i] < $art) {
$arts[] = "$year/$month/$day/" .$fno[$i];
$returnedStories++;
}
}
unset($fno);
if ($returnedStories < $numberofstories) {
$day--;
while ((!file_exists($config["sipssys"] ."/stories/$year/$month/$day")) && (file_exists($config["sipssys"] ."/stories/$year"))) {
$day--;
if ($day <= 0) {
$day = 31;
$month--;
if ($month == 0) {
$year--;
$month = 12;
}
}
}
if (!file_exists($config["sipssys"] ."/stories/$year")) {
$returnedStories = $numberofstories; // causes end of while
}
}
}
return $arts;
}
function getStoryWithID($id) {
global $config;
if (file_exists($config["sipssys"] ."/stories/$id/story")) {
$lines = file($config["sipssys"] ."/stories/$id/story");
for ($i=0; $i<=count($lines); $i++) {
$list = split("::", $lines[$i]);
$story[$list[0]] = chop($list[1]);
}
return $story;
}
}
function writeRSSHeader($fp, $title, $desc) {
global $config;
fwrite($fp, "<?xml version=\"1.0\"?>\n<!DOCTYPE rss PUBLIC \"-//Netscape Communications//DTD RSS 0.91//EN\"\n\"http://my.netscape.com/publish/formats/rss-0.91.dtd\">\n<rss version=\"0.91\">\n\n");
fwrite($fp, "<channel>\n<title>$title</title>\n<link>" .$config["httpbase"] ."</link>\n<description>$desc</description>\n<language>en-us</language>\n\n");
}
function writeRSSItem($fp, $title, $artid, $desc) {
global $config;
fwrite($fp, "<item>\n<title>$title</title>\n<link>" .$config["httpbase"] ."/story.php?storyid=$artid</link>\n<description>$desc</description>\n</item>\n\n");
}
function writeRSSFooter($fp) {
global $config;
fwrite($fp, "<lastBuildDate>" .date("Y-m-d H:i:s") ."</lastBuildDate>\n<webMaster>" .$config["siteadmin"] ."</webMaster>\n</channel>\n</rss>\n");
}
function rebuildXML() {
global $config;
if ($config["export-rss"] == 1) {
$arts = getStoryIDs($config["maxstories"]);
$fp = fopen($config["sipsbase"] ."/backend.rss", "w");
writeRSSHeader($fp, $config["sitename"], $config["sitedescription"]);
for ($i = 0; $i < count($arts); $i++) {
$a = getStoryWithID($arts[$i]);
writeRSSItem($fp, $a["Title"], $arts[$i], $a["Topic"]);
}
writeRSSFooter($fp);
fclose($fp);
}
if ($config["enable-recent-rss"] == 1) {
$fp = fopen($config["sipsbase"] ."/recent.rss", "w");
writeRSSHeader($fp, $config["sitename"], i18n("Recent Stories"), i18n("Older but recent stories from #1#", $config["sitename"]));
$max_items = $config["maxstories"] * 2;
$arts = getStoryIDs($max_items);
$i = $config["maxstories"];
while (($i <= $max_items) && ($i <= count($arts)-1)) {
$a = getStoryWithID($arts[$i]);
writeRSSItem($fp, $a["Title"], $arts[$i], $a["Topic"]);
$i++;
}
if ($i == $config["maxstories"]) { // no older recent stories exist, writing the last we have
$artid = $arts[count($arts)-1];
$a = getStoryWithID($artid);
writeRSSItem($fp, $a["Title"], $artid, $a["Topic"]);
}
writeRSSFooter($fp);
fclose($fp);
}
}
function saveStory($id, $story) {
global $config;
$fp = fopen($config["sipssys"] ."/stories/$id/story", "w");
fwrite($fp, "Title::" .$story["Title"] ."\n");
fwrite($fp, "Time::" .$story["Time"] ."\n");
if (strlen($story["Keyword"]) > 0) {
fwrite($fp, "Keyword::" .$story["Keyword"] ."\n");
}
fwrite($fp, "Topic::" .$story["Topic"] ."\n");
fwrite($fp, "PostedByUser::" .$story["PostedByUser"] ."\n");
if (strlen($story["PostedByEmail"]) > 0) {
fwrite($fp, "PostedByEmail::" .$story["PostedByEmail"] ."\n");
}
fwrite($fp, "Summary::" .$story["Summary"] ."\n");
if (strlen($story["Body"]) > 0) {
fwrite($fp, "Body::" .$story["Body"] ."\n");
}
fclose($fp);
rebuildXML();
}
function constructStory($title, $topic, $keyword, $summary, $body) {
$a["Title"] = stripslashes($title);
$a["Keyword"] = stripslashes($keyword);
$a["Topic"] = stripslashes($topic);
$a["Summary"] = str_replace("\r\n", "<br>", stripslashes(chop($summary)));
$a["Body"] = str_replace("\r\n", "<br>", stripslashes(chop($body)));
return $a;
}
function makeStoryDir($dirname) {
global $config;
$dirname = $config["sipssys"] ."/stories/$dirname";
if (!file_exists($dirname)) {
if (!mkdir($dirname, 0777)) {
die("There was a problem creating the directory $dirname. Please check the permissions.");
}
}
}
function publishStory($title, $keyword, $topic, $summary, $body) {
// posts a new story
global $HTTP_COOKIE_VARS;
$cnt = readCounter();
writeCounter(++$cnt);
$gmtstamp = getCurrentGMT();
$time = getdate($gmtstamp);
$id = $time["year"];
makeStoryDir($id);
$id .= "/" .$time["mon"];
makeStoryDir($id);
$id .= "/" .$time["mday"];
makeStoryDir($id);
$id .= "/$cnt";
makeStoryDir($id);
$a = constructStory($title, $topic, $keyword, $summary, $body);
$a["Time"] = $gmtstamp;
$auth = explode(":", $HTTP_COOKIE_VARS["user"]);
$a["PostedByUser"] = $auth[0];
$a["PostedByEmail"] = getUserValue($auth[0], "Email");
saveStory($id, $a);
}
function printStoryHeader($story, $storytemplate = "default") {
global $config, $usr;
$h = implode("", file($config["sipssys"] ."/themes/" .$usr["Theme"] ."/stories/$storytemplate"));
$h = str_replace("#TITLE#", $story["Title"], $h);
if ($story["PostedByEmail"] != "") $author .= "<a href=\"mailto:" .$story["PostedByEmail"] ."\">" .$story["PostedByUser"] ."</a>";
else $author .= $story["PostedByUser"];
$h = str_replace("#AUTHOR#", $author, $h);
$localizedtime = gmtToLocal($story["Time"], $usr["Timezone"]);
$posteddate = strftime($config["date-format"], $localizedtime);
$h = str_replace("#DATE#", $posteddate, $h);
$postedtime = date("H:i", $localizedtime);
$h = str_replace("#TIME#", $postedtime, $h);
$topiclink = "<a href=\"" .$config["httpbase"] ."/search.php?topic=" .$story["Topic"] ."\">";
if (strstr($h, "#TOPICICON#") != false) { //eregi
$iconbase = "/gfx/topics/" .$story["Topic"];
if (file_exists($config["sipsbase"] ."$iconbase.gif")) $icon = "$iconbase.gif";
else if (file_exists($config["sipsbase"] ."$iconbase.png")) $icon = "$iconbase.png";
else $icon = "$iconbase.jpg";
$imagesize = getImageSize($config["sipsbase"] .$icon);
$topicicon = "$topiclink<img src=\"" .$config["httpbase"] ."$icon\" alt=\"" .$story["Topic"] ."\" $imagesize[3] border=\"0\"></a>";
$h = str_replace("#TOPICICON#", $topicicon, $h);
}
$topictext = $topiclink .$story["Topic"] ."</a>";
$h = str_replace("#TOPICTEXT#", $topictext, $h);
return $h;
}
function printShortStory($fp, $story, $aid, $storytemplate = "default") {
global $config;
$a = printStoryHeader($story, $storytemplate);
$a = str_replace("#STORYTEXT#", $story["Summary"], $a);
$links = "( ";
if ($story["Body"] != "") $links .= "<a href=\"" .$config["httpbase"] ."/story.php?storyid=$aid\">" .i18n("Full Story") ."</a> | ";
$links .= "<a href=\"" .$config["httpbase"] ."/search.php?topic=" .$story["Topic"] ."\">" .i18n("Related Stories") ."</a>";
if (($story["Keyword"] != "") && ($config["enablesearch"]))
$links .= " | <a href=\"" .$config["httpbase"] ."/search/search.php?text=" .$story["Keyword"] ."\">" .i18n("Related Sites") ."</a>";
$links .= " )";
$a = str_replace("#LINKS#", $links, $a);
$a = eregi_replace("</?LINKS>", "", $a); // remove <LINKS> and </LINKS>
if ($fp == "")
print($a);
else
fwrite($fp, $a);
}
function printLongStory($story, $storytemplate = "default") {
$a = printStoryHeader($story, $storytemplate);
$a = str_replace("#STORYTEXT#", $story["Summary"] ."<p>" .$story["Body"], $a);
$a = eregi_replace("<LINKS>(.|\n)*</LINKS>", "", $a); // stripping the <links></links> section which isn't needed when viewing full stories
print($a);
}
function preview($time) {
global $title, $keyword, $topic, $summary, $body, $postedbyuser, $postedbyemail, $usr;
$a = constructStory($title, $topic, $keyword, $summary, $body);
$a["PostedByUser"] = $postedbyuser;
$a["PostedByEmail"] = $postedbyemail;
$a["Time"] = $time;
if (strlen($body) > 0)
printLongStory($a);
else
printShortStory("", $a, "");
print("\n<hr>\n");
}
function printFilledSubmitForm($storyid, $action, $title, $keyword, $topic, $summary, $body, $extrafields) {
global $config;
print("<form action=\"" .$action ."\" method=\"POST\">\n");
$title = ereg_replace("\"", """, $title);
print("<p><b>" .i18n("Title") ."</b>: <input type=\"text\" name=\"title\" size=50 maxlength=80 value=\"" .stripslashes($title) ."\"> (<b>" .i18n("Required") ."</b>)<br>\n");
print("<p>" .i18n("One single #B#keyword#/B#") .": <input type=\"text\" name=\"keyword\" size=20 maxlength=30 value=\"" .stripslashes($keyword) ."\"> (" .i18n("Optional") .")<br>\n");
$alltopics = getTopics();
if (count($alltopics) > 1) {
print("<p><b>" .i18n("Topic Subject") ."</b>:\n");
printTopicsInSelect($alltopics, $topic);
print("(<b>" .i18n("Required") ."</b>)<br>\n");
print("<small>(" .i18n("If your story does not seem to fit into any of the pre-defined categories, use 'General', and contact #1# with your topic proposal!", "<a href=\"mailto:" .$config["siteadmin"] ."\">" .$config["siteadmin"] ."</a>") .")</small><br>");
} else {
print("\n<input type=\"hidden\" name=\"topic\" value=\"general\">\n");
}
print("<p>" .i18n("#B#Lead Summary#/B# of message") .": (<b>" .i18n("Required") ."</b>)<br>\n");
print("<textarea name=\"summary\" cols=\"60\" rows=\"7\" wrap=\"virtual\">" .str_replace("<br>", "\n", stripslashes($summary)) ."</textarea><br>\n");
print("<small>(" .i18n("This is the text displayed in the main page. If there are more than 3 or 4 paragraphs, put the rest into the body.") .")</small>");
print("<p>" .i18n("#B#Main Body#/B# of message") .": (" .i18n("Optional") .")<br>\n");
print("<textarea name=\"body\" cols=\"60\" rows=\"7\" wrap=\"virtual\">" .str_replace("<br>", "\n", stripslashes($body)) ."</textarea><br>\n");
print("<small>(" .i18n("This can be as long as you like.") .")</small>");
print("<br>\n<input type=\"hidden\" name=\"storyid\" value=\"$storyid\">");
print("\n$extrafields");
print("\n</form>");
}
function printTopicsInSelect($alltopics, $selected) {
print("<select name=\"topic\">\n");
sort($alltopics);
for ($i = 0; $i < count($alltopics); $i++) {
print("<option value=\"" .$alltopics[$i] ."\"");
if ($selected == $alltopics[$i]) { print(" selected"); }
print(">" .ucfirst($alltopics[$i]) ."</option>\n");
}
print("</select>");
}
function getTopics() {
global $config;
$filename = $config["sipssys"] ."/stories/topics";
if (file_exists($filename)) {
$c = file($filename);
for ($i = 0; $i<count($c); $i++) {
$c[$i] = chop($c[$i]);
}
}
$c[] = "general"; // there has to be at least one topic
return $c;
}
function readCounter() {
global $config;
$counterfile = $config["sipssys"] ."/stories/count";
if (!file_exists($counterfile)) {
$fp = fopen($counterfile, "w");
fwrite($fp, "1");
}
$i = file($counterfile);
return $i[0];
}
function writeCounter($c) {
global $config;
$fp = fopen($config["sipssys"] ."/stories/count", "w");
fwrite($fp, $c);
fclose($fp);
}
function searchStoriesForText($s, $before) {
global $config;
$art = ($before == "0"? getStoryIDs($config["maxhits"]) : getStoryIDsBefore($before, $config["maxhits"]));
$regexp = "( |\>)$s( |\.|,)";
while ((count($art) > 0) && (count($hitlist) < $config["maxhits"])) {
for ($c = 0; ($c <= count($art) && (count($hitlist) < $config["maxhits"])); $c++) {
$a = getStoryWithID($art[$c]);
if ((eregi($regexp, $a["Summary"])) ||
(eregi($regexp, $a["Title"])) ||
(eregi($regexp, $a["Body"])) ||
(eregi($regexp, $a["Keyword"])))
$hitlist[] = $art[$c];
}
$aprev = $art[count($art)-1];
$art = getStoryIDsBefore($aprev, 5);
}
if (count($hitlist) == 0)
return false;
else
return $hitlist;
}
function searchStoriesForTopic($s) {
$s = strtolower($s);
$art = getStoryIDs(10);
while (count($art) > 0) {
for ($c = 0; $c <= count($art); $c++) {
$a = getStoryWithID($art[$c]);
if ($a["Topic"] == $s) {
$hitlist[] = $art[$c];
}
}
$aprev = $art[count($art)-1];
$art = getStoryIDsBefore($aprev, 5);
}
if (count($hitlist) == 0) {
return false;
} else {
return $hitlist;
}
}
?>