summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.htaccess5
-rw-r--r--CHANGELOG2
-rw-r--r--export.php (renamed from export)4
-rw-r--r--modules/aggregator.module (renamed from modules/syndication.module)89
-rw-r--r--modules/aggregator/aggregator.module275
-rw-r--r--modules/backend.class154
-rw-r--r--modules/export.module87
-rw-r--r--modules/headline.module326
-rw-r--r--modules/import.module275
9 files changed, 693 insertions, 524 deletions
diff --git a/.htaccess b/.htaccess
index 7e563745c..473a5ec3d 100644
--- a/.htaccess
+++ b/.htaccess
@@ -8,11 +8,6 @@
deny from all
</Files>
-# Syndicate content:
-<Files export>
- ForceType application/x-httpd-php
-</Files>
-
# Customized server error messages:
ErrorDocument 400 /error.php
ErrorDocument 402 /error.php
diff --git a/CHANGELOG b/CHANGELOG
index c416ffc41..164a321be 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,8 @@ drupal x.xx, xx/xx/xxxx (CVS, unstable)
- removed ban module and integrated it into account.module as "access control":
* access control is based on much more powerful regular expressions (regex) now rather than on MySQL pattern matching.
- rewrote watchdog and submission throttle
+- rewrote headline code and renamed it to import.module and export.module
+ * added a various new features compared with the old headline code.
- rewrote section code and renamed it to structure.module:
* supports both "categories" and "topics" (cfr. Scoop, SlashCode). Topics can be nested to create a multi-level hierarchy.
* added "auto-post new submissions" feature versus "moderate new submissions".
diff --git a/export b/export.php
index c11073879..5b2142a15 100644
--- a/export
+++ b/export.php
@@ -2,6 +2,8 @@
include_once "includes/common.inc";
-foreach (module_list() as $module) module_invoke($module, "export", explode("/", $REQUEST_URI));
+$uri = parse_url($REQUEST_URI);
+
+foreach (module_list() as $module) module_invoke($module, "export", $uri["query"]);
?> \ No newline at end of file
diff --git a/modules/syndication.module b/modules/aggregator.module
index 952088fcb..a4b85041e 100644
--- a/modules/syndication.module
+++ b/modules/aggregator.module
@@ -2,30 +2,30 @@
include_once "modules/backend.class";
-function syndication_help() {
+function import_help() {
?>
<P>TODO - anyone?</P>
<?php
}
-function syndication_cron() {
+function import_cron() {
$result = db_query("SELECT * FROM feed");
while ($feed = db_fetch_array($result)) {
// remove expired items:
db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp - ". time() ." > $feed[uncache]");
// update feeds:
- if ($feed[timestamp] + $feed[refresh] < time()) syndication_update($feed);
+ if ($feed[timestamp] + $feed[refresh] < time()) import_update($feed);
}
}
-function syndication_bundle($attribute) {
+function import_bundle($attribute, $limit = 100) {
if ($attribute) {
// compose query:
$keys = explode(",", $attribute);
foreach ($keys as $key) $where[] = "attribute LIKE '%". trim($key) ."%'";
- $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY timestamp DESC");
+ $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY timestamp DESC LIMIT $limit");
while ($item = db_fetch_object($result)) {
$output .= "<LI><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A></LI>";
@@ -35,15 +35,26 @@ function syndication_bundle($attribute) {
}
}
-function syndication_view_bundle() {
+function import_view_bundle() {
$result = db_query("SELECT * FROM bundle ORDER BY title");
while ($bundle = db_fetch_object($result)) {
- $output .= "<B>$bundle->title</B><UL>". syndication_bundle($bundle->attribute) ."</UL>";
+ $output .= "<B>$bundle->title</B><UL>". import_bundle($bundle->attribute) ."</UL>";
}
return $output;
}
-function syndication_update($feed) {
+function import_block() {
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+ while ($bundle = db_fetch_object($result)) {
+ $i++;
+ $blocks[$i][subject] = $bundle->title;
+ $blocks[$i][content] = import_bundle($bundle->attribute, 10);
+ $blocks[$i][info] = "$bundle->title bundle";
+ }
+ return $blocks;
+}
+
+function import_update($feed) {
// open socket:
$url = parse_url($feed[link]);
@@ -65,7 +76,7 @@ function syndication_update($feed) {
$d = eregi("<description>(.*)</description>", $item, $description);
if ($l || $t || $a || $d) {
- syndication_save_item(array(fid => $feed[fid], title => $title[0], link => $link[0], author => $author[0], description => $description[0], attribute => $feed[attribute]));
+ import_save_item(array(fid => $feed[fid], title => $title[0], link => $link[0], author => $author[0], description => $description[0], attribute => $feed[attribute]));
}
}
@@ -77,7 +88,7 @@ function syndication_update($feed) {
}
}
-function syndication_save_item($edit) {
+function import_save_item($edit) {
if ($edit[iid] && $edit[title]) {
db_query("UPDATE item SET title = '". check_input($edit[title]) ."', link = '". check_input($edit[link]) ."', author = '". check_input($edit[author]) ."', description = '". check_input($edit[description]) ."', attribute = '". check_input($edit[attribute]) ."' WHERE iid = '$edit[iid]'");
}
@@ -91,7 +102,7 @@ function syndication_save_item($edit) {
}
}
-function syndication_form_bundle($edit = array()) {
+function import_form_bundle($edit = array()) {
global $REQUEST_URI;
$form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the bundle.");
@@ -107,7 +118,7 @@ function syndication_form_bundle($edit = array()) {
return form($REQUEST_URI, $form);
}
-function syndication_save_bundle($edit) {
+function import_save_bundle($edit) {
if ($edit[bid] && $edit[title]) {
db_query("UPDATE bundle SET title = '". check_input($edit[title]) ."', attribute = '". check_input($edit[attribute]) ."' WHERE bid = '". check_input($edit[bid]) ."'");
}
@@ -117,9 +128,11 @@ function syndication_save_bundle($edit) {
else {
db_query("INSERT INTO bundle (title, attribute) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[attribute]) ."')");
}
+
+ module_rehash_blocks("import");
}
-function syndication_form_feed($edit = array()) {
+function import_form_feed($edit = array()) {
global $REQUEST_URI;
$period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200));
@@ -140,7 +153,7 @@ function syndication_form_feed($edit = array()) {
return form($REQUEST_URI, $form);
}
-function syndication_save_feed($edit) {
+function import_save_feed($edit) {
if ($edit[fid] && $edit[title]) {
db_query("UPDATE feed SET title = '". check_input($edit[title]) ."', link = '". check_input($edit[link]) ."', attribute = '". check_input($edit[attribute]) ."', refresh = '". check_input($edit[refresh]) ."', uncache = '". check_input($edit[uncache]) ."' WHERE fid = '". check_input($edit[fid]) ."'");
db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'");
@@ -154,29 +167,29 @@ function syndication_save_feed($edit) {
}
}
-function syndication_save_attributes($edit) {
+function import_save_attributes($edit) {
foreach($edit as $iid => $value) {
db_query("UPDATE item SET attribute = '". check_input($value) ."' WHERE iid = '". check_input($iid) ."'");
}
return "attributes has been saved";
}
-function syndication_get_feed($fid) {
+function import_get_feed($fid) {
return db_fetch_array(db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"));
}
-function syndication_get_bundle($bid) {
+function import_get_bundle($bid) {
return db_fetch_array(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'"));
}
-function syndication_view_feed() {
+function import_view_feed() {
$result = db_query("SELECT f.*, COUNT(i.iid) AS items FROM feed f LEFT JOIN item i ON f.fid = i.fid GROUP BY f.fid ORDER BY f.title");
$output .= "<H3>Feed overview</H3>";
$output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
$output .= " <TR><TH>title</TH><TH>attributes</TH><TH>items</TH><TH>last update</TH><TH>next update</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
while ($feed = db_fetch_object($result)) {
- $output .= " <TR><TD>". check_output($feed->title) ."</TD><TD>". check_output($feed->attribute) ."</TD><TD>". format_plural($feed->items, "item", "items") ."</TD><TD>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</TD><TD>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</TD><TD><A HREF=\"admin.php?mod=syndication&type=feed&op=edit&id=$feed->fid\">edit feed</A></TD><TD><A HREF=\"admin.php?mod=syndication&type=feed&op=update&id=$feed->fid\">update items</A></TD></TR>\n";
+ $output .= " <TR><TD>". check_output($feed->title) ."</TD><TD>". check_output($feed->attribute) ."</TD><TD>". format_plural($feed->items, "item", "items") ."</TD><TD>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</TD><TD>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</TD><TD><A HREF=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</A></TD><TD><A HREF=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</A></TD></TR>\n";
}
$output .= "</TABLE>\n";
@@ -186,14 +199,14 @@ function syndication_view_feed() {
$output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
$output .= " <TR><TH>title</TH><TH>attributes</TH><TH>operations</TH></TR>\n";
while ($bundle = db_fetch_object($result)) {
- $output .= " <TR><TD>". check_output($bundle->title) ."</TD><TD>". check_output($bundle->attribute) ."</TD><TD><A HREF=\"admin.php?mod=syndication&type=bundle&op=edit&id=$bundle->bid\">edit bundle</A></TD></TR>\n";
+ $output .= " <TR><TD>". check_output($bundle->title) ."</TD><TD>". check_output($bundle->attribute) ."</TD><TD><A HREF=\"admin.php?mod=import&type=bundle&op=edit&id=$bundle->bid\">edit bundle</A></TD></TR>\n";
}
$output .= "</TABLE>\n";
return $output;
}
-function syndication_view_item() {
+function import_view_item() {
global $REQUEST_URI;
$result = db_query("SELECT i.*, f.title AS feed FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.timestamp DESC LIMIT 50");
@@ -202,7 +215,7 @@ function syndication_view_item() {
$output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
$output .= " <TR><TH>time</TH><TH>feed</TH><TH>item</TH></TR>\n";
while ($item = db_fetch_object($result)) {
- $output .= " <TR><TD VALIGN=\"top\" NOWRAP>". format_date($item->timestamp, "custom", "m/d/y") ."<BR>".format_date($item->timestamp, "custom", "H:i") ."</TD><TD ALIGN=\"center\" VALIGN=\"top\" NOWRAP><A HREF=\"admin.php?mod=syndication&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</A></TD><TD><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A>". ($item->description ? "<BR><SMALL><I>". check_output($item->description) ."</I></SMALL>" : "") ."<BR><INPUT TYPE=\"text\" NAME=\"edit[$item->iid]\" VALUE=\"". check_form($item->attribute) ."\" SIZE=\"50\"></TD></TR>\n";
+ $output .= " <TR><TD VALIGN=\"top\" NOWRAP>". format_date($item->timestamp, "custom", "m/d/y") ."<BR>".format_date($item->timestamp, "custom", "H:i") ."</TD><TD ALIGN=\"center\" VALIGN=\"top\" NOWRAP><A HREF=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</A></TD><TD><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A>". ($item->description ? "<BR><SMALL><I>". check_output($item->description) ."</I></SMALL>" : "") ."<BR><INPUT TYPE=\"text\" NAME=\"edit[$item->iid]\" VALUE=\"". check_form($item->attribute) ."\" SIZE=\"50\"></TD></TR>\n";
}
$output .= "</TABLE>\n";
$output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Save attributes\">\n";
@@ -211,51 +224,51 @@ function syndication_view_item() {
return $output;
}
-function syndication_admin() {
+function import_admin() {
global $op, $id, $type, $edit;
- print "<SMALL><A HREF=\"admin.php?mod=syndication&type=bundle&op=add\">add new bundle</A> | <A HREF=\"admin.php?mod=syndication&type=feed&op=add\">add new feed</A> | <A HREF=\"admin.php?mod=syndication&type=bundle&op=view\">available bundles</A> | <A HREF=\"admin.php?mod=syndication&type=item&op=view\">available items</A> | <A HREF=\"admin.php?mod=syndication&op=view\">overview</A> | <A HREF=\"admin.php?mod=syndication&op=help\">help</A></SMALL><HR>";
+ print "<SMALL><A HREF=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</A> | <A HREF=\"admin.php?mod=import&type=feed&op=add\">add new feed</A> | <A HREF=\"admin.php?mod=import&type=bundle&op=view\">available bundles</A> | <A HREF=\"admin.php?mod=import&type=item&op=view\">available items</A> | <A HREF=\"admin.php?mod=import&op=view\">overview</A> | <A HREF=\"admin.php?mod=import&op=help\">help</A></SMALL><HR>";
switch($op) {
case "help":
- print syndication_help();
+ print import_help();
break;
case "add":
if ($type == "bundle")
- print syndication_form_bundle();
+ print import_form_bundle();
else
- print syndication_form_feed();
+ print import_form_feed();
break;
case "edit":
if ($type == "bundle")
- print syndication_form_bundle(syndication_get_bundle($id));
+ print import_form_bundle(import_get_bundle($id));
else
- print syndication_form_feed(syndication_get_feed($id));
+ print import_form_feed(import_get_feed($id));
break;
case "update":
- print syndication_update(syndication_get_feed($id));
- print syndication_view_feed();
+ print import_update(import_get_feed($id));
+ print import_view_feed();
break;
case "Save attributes":
- print status(syndication_save_attributes($edit));
- print syndication_view_item();
+ print status(import_save_attributes($edit));
+ print import_view_item();
break;
case "Delete":
$edit[title] = 0;
// fall through:
case "Submit":
if ($type == "bundle")
- print status(syndication_save_bundle($edit));
+ print status(import_save_bundle($edit));
else
- print status(syndication_save_feed($edit));
+ print status(import_save_feed($edit));
// fall through:
default:
if ($type == "bundle")
- print syndication_view_bundle();
+ print import_view_bundle();
else if ($type == "item")
- print syndication_view_item();
+ print import_view_item();
else
- print syndication_view_feed();
+ print import_view_feed();
}
}
diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module
new file mode 100644
index 000000000..a4b85041e
--- /dev/null
+++ b/modules/aggregator/aggregator.module
@@ -0,0 +1,275 @@
+<?php
+
+include_once "modules/backend.class";
+
+function import_help() {
+ ?>
+ <P>TODO - anyone?</P>
+ <?php
+}
+
+function import_cron() {
+ $result = db_query("SELECT * FROM feed");
+ while ($feed = db_fetch_array($result)) {
+ // remove expired items:
+ db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp - ". time() ." > $feed[uncache]");
+
+ // update feeds:
+ if ($feed[timestamp] + $feed[refresh] < time()) import_update($feed);
+ }
+}
+
+function import_bundle($attribute, $limit = 100) {
+ if ($attribute) {
+ // compose query:
+ $keys = explode(",", $attribute);
+ foreach ($keys as $key) $where[] = "attribute LIKE '%". trim($key) ."%'";
+
+ $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY timestamp DESC LIMIT $limit");
+
+ while ($item = db_fetch_object($result)) {
+ $output .= "<LI><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A></LI>";
+ }
+
+ return "$output";
+ }
+}
+
+function import_view_bundle() {
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+ while ($bundle = db_fetch_object($result)) {
+ $output .= "<B>$bundle->title</B><UL>". import_bundle($bundle->attribute) ."</UL>";
+ }
+ return $output;
+}
+
+function import_block() {
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+ while ($bundle = db_fetch_object($result)) {
+ $i++;
+ $blocks[$i][subject] = $bundle->title;
+ $blocks[$i][content] = import_bundle($bundle->attribute, 10);
+ $blocks[$i][info] = "$bundle->title bundle";
+ }
+ return $blocks;
+}
+
+function import_update($feed) {
+
+ // open socket:
+ $url = parse_url($feed[link]);
+ $fp = fsockopen($url[host], ($url[port] ? $url[port] : 80), $errno, $errstr, 15);
+
+ if ($fp) {
+ // fetch data:
+ fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get(site_name, "drupal") ."\nHost: $url[host]\nAccept: */*\n\n");
+ while(!feof($fp)) $data .= fgets($fp, 128);
+
+ if (strstr($data, "200 OK")) {
+
+ eregi("<item(.*)</item>", $data, $data);
+
+ foreach (explode("</item>", $data[0]) as $item) {
+ $l = eregi("<link>(.*)</link>", $item, $link);
+ $t = eregi("<title>(.*)</title>", $item, $title);
+ $a = eregi("<author>(.*)</author>", $item, $author);
+ $d = eregi("<description>(.*)</description>", $item, $description);
+
+ if ($l || $t || $a || $d) {
+ import_save_item(array(fid => $feed[fid], title => $title[0], link => $link[0], author => $author[0], description => $description[0], attribute => $feed[attribute]));
+ }
+ }
+
+ db_query("UPDATE feed SET timestamp = '". time() ."' WHERE fid = '". $feed[fid] ."'");
+ }
+ else {
+ watchdog("error", "failed to syndicate from '$feed[title]'");
+ }
+ }
+}
+
+function import_save_item($edit) {
+ if ($edit[iid] && $edit[title]) {
+ db_query("UPDATE item SET title = '". check_input($edit[title]) ."', link = '". check_input($edit[link]) ."', author = '". check_input($edit[author]) ."', description = '". check_input($edit[description]) ."', attribute = '". check_input($edit[attribute]) ."' WHERE iid = '$edit[iid]'");
+ }
+ else if ($edit[iid]) {
+ db_query("DELETE FROM item WHERE iid = '". check_input($edit[iid]) ."'");
+ }
+ else {
+ if (!db_fetch_object(db_query("SELECT iid FROM item WHERE link = '". check_input($edit[link]) ."'"))) {
+ db_query("INSERT INTO item (fid, title, link, author, description, attribute, timestamp) VALUES ('". check_input($edit[fid]) ."', '". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[author]) ."', '". check_input($edit[description]) ."', '". check_input($edit[attribute]) ."', '". time() ."')");
+ }
+ }
+}
+
+function import_form_bundle($edit = array()) {
+ global $REQUEST_URI;
+
+ $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the bundle.");
+ $form .= form_textfield("Attributes", "attribute", $edit[attribute], 50, 128, "A comma-seperated list of keywords describing the bundle.");
+
+ $form .= form_submit("Submit");
+
+ if ($edit[bid]) {
+ $form .= form_submit(t("Delete"));
+ $form .= form_hidden("bid", $edit[bid]);
+ }
+
+ return form($REQUEST_URI, $form);
+}
+
+function import_save_bundle($edit) {
+ if ($edit[bid] && $edit[title]) {
+ db_query("UPDATE bundle SET title = '". check_input($edit[title]) ."', attribute = '". check_input($edit[attribute]) ."' WHERE bid = '". check_input($edit[bid]) ."'");
+ }
+ else if ($edit[bid]) {
+ db_query("DELETE FROM bundle WHERE bid = '". check_input($edit[bid]) ."'");
+ }
+ else {
+ db_query("INSERT INTO bundle (title, attribute) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[attribute]) ."')");
+ }
+
+ module_rehash_blocks("import");
+}
+
+function import_form_feed($edit = array()) {
+ global $REQUEST_URI;
+
+ $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200));
+
+ $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the feed; typically the name of the website you syndicate content from.");
+ $form .= form_textfield("Link", "link", $edit[link], 50, 64, "The fully-qualified URL of the feed.");
+ $form .= form_textfield("Attributes", "attribute", $edit[attribute], 50, 128, "A comma-seperated list of keywords describing the feed.");
+ $form .= form_select("Update interval", "refresh", $edit[refresh], $period, "The refresh interval indicating how often you want to update this feed. Requires crontab.");
+ $form .= form_select("Expiration time", "uncache", $edit[uncache], $period, "The time cached items should be kept. Older items will be automatically discarded. Requires crontab.");
+
+ $form .= form_submit("Submit");
+
+ if ($edit[fid]) {
+ $form .= form_submit(t("Delete"));
+ $form .= form_hidden("fid", $edit[fid]);
+ }
+
+ return form($REQUEST_URI, $form);
+}
+
+function import_save_feed($edit) {
+ if ($edit[fid] && $edit[title]) {
+ db_query("UPDATE feed SET title = '". check_input($edit[title]) ."', link = '". check_input($edit[link]) ."', attribute = '". check_input($edit[attribute]) ."', refresh = '". check_input($edit[refresh]) ."', uncache = '". check_input($edit[uncache]) ."' WHERE fid = '". check_input($edit[fid]) ."'");
+ db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'");
+ }
+ else if ($edit[fid]) {
+ db_query("DELETE FROM feed WHERE fid = '". check_input($edit[fid]) ."'");
+ db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'");
+ }
+ else {
+ db_query("INSERT INTO feed (title, link, attribute, refresh, uncache) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[attribute]) ."', '". check_input($edit[refresh]) ."', '". check_input($edit[uncache]) ."')");
+ }
+}
+
+function import_save_attributes($edit) {
+ foreach($edit as $iid => $value) {
+ db_query("UPDATE item SET attribute = '". check_input($value) ."' WHERE iid = '". check_input($iid) ."'");
+ }
+ return "attributes has been saved";
+}
+
+function import_get_feed($fid) {
+ return db_fetch_array(db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"));
+}
+
+function import_get_bundle($bid) {
+ return db_fetch_array(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'"));
+}
+
+function import_view_feed() {
+ $result = db_query("SELECT f.*, COUNT(i.iid) AS items FROM feed f LEFT JOIN item i ON f.fid = i.fid GROUP BY f.fid ORDER BY f.title");
+
+ $output .= "<H3>Feed overview</H3>";
+ $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
+ $output .= " <TR><TH>title</TH><TH>attributes</TH><TH>items</TH><TH>last update</TH><TH>next update</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
+ while ($feed = db_fetch_object($result)) {
+ $output .= " <TR><TD>". check_output($feed->title) ."</TD><TD>". check_output($feed->attribute) ."</TD><TD>". format_plural($feed->items, "item", "items") ."</TD><TD>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</TD><TD>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</TD><TD><A HREF=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</A></TD><TD><A HREF=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</A></TD></TR>\n";
+ }
+ $output .= "</TABLE>\n";
+
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+
+ $output .= "<H3>Bundle overview</H3>";
+ $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
+ $output .= " <TR><TH>title</TH><TH>attributes</TH><TH>operations</TH></TR>\n";
+ while ($bundle = db_fetch_object($result)) {
+ $output .= " <TR><TD>". check_output($bundle->title) ."</TD><TD>". check_output($bundle->attribute) ."</TD><TD><A HREF=\"admin.php?mod=import&type=bundle&op=edit&id=$bundle->bid\">edit bundle</A></TD></TR>\n";
+ }
+ $output .= "</TABLE>\n";
+
+ return $output;
+}
+
+function import_view_item() {
+ global $REQUEST_URI;
+
+ $result = db_query("SELECT i.*, f.title AS feed FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.timestamp DESC LIMIT 50");
+
+ $output .= "<FORM ACTION=\"$REQUEST_URI\" METHOD=\"post\">\n";
+ $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
+ $output .= " <TR><TH>time</TH><TH>feed</TH><TH>item</TH></TR>\n";
+ while ($item = db_fetch_object($result)) {
+ $output .= " <TR><TD VALIGN=\"top\" NOWRAP>". format_date($item->timestamp, "custom", "m/d/y") ."<BR>".format_date($item->timestamp, "custom", "H:i") ."</TD><TD ALIGN=\"center\" VALIGN=\"top\" NOWRAP><A HREF=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</A></TD><TD><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A>". ($item->description ? "<BR><SMALL><I>". check_output($item->description) ."</I></SMALL>" : "") ."<BR><INPUT TYPE=\"text\" NAME=\"edit[$item->iid]\" VALUE=\"". check_form($item->attribute) ."\" SIZE=\"50\"></TD></TR>\n";
+ }
+ $output .= "</TABLE>\n";
+ $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Save attributes\">\n";
+ $output .= "</FORM>\n";
+
+ return $output;
+}
+
+function import_admin() {
+ global $op, $id, $type, $edit;
+
+ print "<SMALL><A HREF=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</A> | <A HREF=\"admin.php?mod=import&type=feed&op=add\">add new feed</A> | <A HREF=\"admin.php?mod=import&type=bundle&op=view\">available bundles</A> | <A HREF=\"admin.php?mod=import&type=item&op=view\">available items</A> | <A HREF=\"admin.php?mod=import&op=view\">overview</A> | <A HREF=\"admin.php?mod=import&op=help\">help</A></SMALL><HR>";
+
+ switch($op) {
+ case "help":
+ print import_help();
+ break;
+ case "add":
+ if ($type == "bundle")
+ print import_form_bundle();
+ else
+ print import_form_feed();
+ break;
+ case "edit":
+ if ($type == "bundle")
+ print import_form_bundle(import_get_bundle($id));
+ else
+ print import_form_feed(import_get_feed($id));
+ break;
+ case "update":
+ print import_update(import_get_feed($id));
+ print import_view_feed();
+ break;
+ case "Save attributes":
+ print status(import_save_attributes($edit));
+ print import_view_item();
+ break;
+ case "Delete":
+ $edit[title] = 0;
+ // fall through:
+ case "Submit":
+ if ($type == "bundle")
+ print status(import_save_bundle($edit));
+ else
+ print status(import_save_feed($edit));
+ // fall through:
+ default:
+ if ($type == "bundle")
+ print import_view_bundle();
+ else if ($type == "item")
+ print import_view_item();
+ else
+ print import_view_feed();
+ }
+}
+
+?>
diff --git a/modules/backend.class b/modules/backend.class
deleted file mode 100644
index c77418e03..000000000
--- a/modules/backend.class
+++ /dev/null
@@ -1,154 +0,0 @@
-<?php
-class backend {
-
- // Channel properties:
- var $id;
- var $url;
- var $site;
- var $file;
- var $contact;
- var $timestamp;
-
- // Contains the raw rdf/rss/xml file:
- var $data;
-
- // Contains the parsed rdf/rss/xml file:
- var $headlines = array(); // latest headlines
-
- function backend($id, $site = "", $url = "", $file = "", $contact = "", $timout = 10800) {
- // Get channel info:
- $result = db_query("SELECT * FROM channel WHERE id = '$id' OR site = '$site'");
-
- if ($channel = db_fetch_object($result)) {
- // Initialize internal variables:
- $this->id = $channel->id;
- $this->site = $channel->site;
- $this->file = $channel->file;
- $this->url = $channel->url;
- $this->contact = $channel->contact;
- $this->timestamp = $channel->timestamp;
-
- // Check to see whether we have to update our headlines first:
- if (time() - $this->timestamp > $timout) $this->url2sql();
-
- // Read headlines:
- $result = db_query("SELECT * FROM headlines WHERE id = '$this->id' ORDER BY number");
- while ($headline = db_fetch_object($result)) {
- array_push($this->headlines, "<A HREF=\"$headline->link\">$headline->title</A>");
- }
- }
- else {
- $this->site = $site;
- $this->url = $url;
- $this->file = $file;
- $this->contact = $contact;
- }
- }
-
- function url2sql($timout = 10) {
- if ($this->file) {
- // Decode URL:
- $url = parse_url($this->file);
-
- // Retrieve data from website:
- $fp = fsockopen($url[host], ($url[port] ? $url[port] : 80), $errno, $errstr, $timout);
-
- if ($fp) {
- // Request data via URL:
- fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get(site_name, "drupal") ."\nHost: $url[host]\nAccept: */*\n\n");
-
- // Read data from socket:
- while(!feof($fp)) $data .= fgets($fp, 128);
-
- if (strstr($data, "200 OK")) {
-
- // Remove existing entries:
- $result = db_query("DELETE FROM headlines WHERE id = '$this->id'");
-
- // Strip all 'junk':
- $data = ereg_replace("<?phpxml.*/image>", "", $data);
- $data = ereg_replace("</rdf.*", "", $data);
- $data = chop($data);
-
- // Iterating through our data processing each entry/item:
- $items = explode("</item>", $data);
- $number = 0;
-
- for (reset($items); $item = current($items); next($items)) {
- // Extract data:
- $link = ereg_replace(".*<link>", "", $item);
- $link = ereg_replace("</link>.*", "", $link);
- $title = ereg_replace(".*<title>", "", $item);
- $title = ereg_replace("</title>.*", "", $title);
-
- // Increase the number of headlines:
- $number += 1;
-
- // Insert item in database:
- $result = db_query("INSERT INTO headlines (id, title, link, number) VALUES('". check_input($this->id) ."', '". check_input($title) ."', '". check_input($link) ."', '". check_input($number) ."')");
- }
-
- // Mark channels as being updated:
- $result = db_query("UPDATE channel SET timestamp = '". time() ."' WHERE id = '$this->id'");
- $this->timestamp = time();
- }
- else {
- watchdog("error", "failed to grab headlines from '$this->site': <PRE>$data</PRE>");
- }
- }
- }
- }
-
- function displayHeadlines($timout = 1800) {
- global $theme;
-
- // Get channel info:
- $result = db_query("SELECT * FROM channel WHERE site = '$this->site'");
-
- if ($this->id) {
-
- // Check to see whether we have to update our headlines first:
- if (time() - $this->timestamp > $timout) $this->url2sql();
-
- // Grab headlines from database:
- $result = db_query("SELECT * FROM headlines WHERE id = '$this->id' ORDER BY number");
- while ($headline = db_fetch_object($result)) {
- $content .= "<LI><A HREF=\"$headline->link\">$headline->title</A></LI>";
- }
- // Add timestamp:
- $update = round((time() - $this->timestamp) / 60);
-
- // Display box:
- $theme->box($this->site, $content);
- }
- else print "<P>Warning: something funky happened: specified channel could not be found in database.</P>";
- }
-
- function add() {
- // Add channel:
- $result = db_query("INSERT INTO channel (site, file, url, contact, timestamp) VALUES ('". check_input($this->site) ."', '". check_input($this->file) ."', '". check_input($this->url) ."', '". check_input($this->contact) ."', 1)");
- }
-
- function save() {
- // Save channel:
- $result = db_query("UPDATE channel SET site='". check_input($this->site) ."', file='". check_input($this->file) ."', url='". check_input($this->url) ."', contact='". check_input($this->contact) ."' WHERE id='". check_input($this->id) ."'");
- }
-
- function delete() {
- // Delete channel:
- $result = db_query("DELETE FROM channel WHERE id = '$this->id'");
-
- // Delete headlines:
- $result = db_query("DELETE FROM headlines WHERE id = '$this->id'");
- }
-
- function refresh() {
- // Delete headlines:
- $result = db_query("DELETE FROM headlines WHERE id = '$this->id'");
-
- // Mark channel as invalid to enforce an update:
- $result = db_query("UPDATE channel SET timestamp = 1 WHERE id = '$this->id'");
- }
-}
-
-?>
diff --git a/modules/export.module b/modules/export.module
new file mode 100644
index 000000000..b65fa569b
--- /dev/null
+++ b/modules/export.module
@@ -0,0 +1,87 @@
+<?php
+
+function export_export_rdf() {
+ global $status;
+
+ header("Content-Type: text/plain");
+
+ print "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
+ print "<rdf:RDF\n";
+ print " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
+ print " xmlns=\"http://my.netscape.com/rdf/simple/0.9/\">\n";
+
+ print "<channel>\n";
+ print " <title>". variable_get(site_name, "drupal") ."</title>\n";
+ print " <link>". path_uri() ."</link>\n";
+ print " <description>". variable_get(site_name, "drupal") ."</description>\n";
+ print "</channel>\n";
+
+ $result = db_query("SELECT * FROM node WHERE promote = '1' AND status = '$status[posted]' ORDER BY timestamp DESC LIMIT 10");
+
+ while ($node = db_fetch_object($result)) {
+ print "<item>\n";
+ print " <title>". check_export($node->title) ."</title>\n";
+ print " <link>". path_uri() ."node.php?id=$node->nid</link>\n";
+ print "</item>\n";
+ }
+
+ print "</rdf:RDF>\n";
+}
+
+function export_export_rss() {
+ global $status;
+
+ header("Content-Type: text/plain");
+
+ print "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
+ print "<rdf:RDF\n";
+
+ print "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
+ print "xmlns=\"http://purl.org/rss/1.0/\">\n\n";
+
+ print "<channel rdf:about=\"". path_uri() ."export/exportsRSS10.rdf\">\n";
+ print " <title>". variable_get(site_name, "drupal") ."</title>\n";
+ print " <link>". path_uri() ."</link>\n";
+ print " <description>". variable_get(site_name, "drupal") ."</description>\n";
+
+ print " <items>\n";
+ print " <rdf:Seq>\n";
+
+ $result = db_query("SELECT * FROM node WHERE promote = '1' AND status = '$status[posted]' ORDER BY timestamp DESC LIMIT 10");
+
+ while ($node = db_fetch_object($result)) {
+ print " <rdf:li resource=\"". path_uri() ."node.php?id=$node->nid\" />\n";
+ }
+
+ print " </rdf:Seq>\n";
+ print " </items>\n";
+ print "</channel>\n\n";
+
+ $result = db_query("SELECT * FROM node WHERE promote = '1' AND status = '$status[posted]' ORDER BY timestamp DESC LIMIT 10");
+
+ while ($node = db_fetch_object($result)) {
+ print "<item rdf:about=\"". path_uri() ."node.php?id=$node->nid\">\n";
+ print " <title>". check_export($node->title) ."</title>\n";
+ print " <link>". path_uri() ."node.php?id=$node->nid</link>\n";
+
+ if ($node->abstract) print " <description>". check_output($node->abstract, 1) ."</description>\n";
+ if ($node->body) print " <description>". check_output($node->body, 1) ."</description>\n";
+
+ print "</item>\n";
+ }
+
+ print "</rdf:RDF>\n";
+}
+
+function export_export($query) {
+ switch ($query) {
+ case "headlines.rss":
+ export_export_rss();
+ break;
+ case "headlines.rdf":
+ case "default":
+ export_export_rdf();
+ }
+}
+
+?>
diff --git a/modules/headline.module b/modules/headline.module
deleted file mode 100644
index 7d30bae50..000000000
--- a/modules/headline.module
+++ /dev/null
@@ -1,326 +0,0 @@
-<?php
-
-include_once "modules/backend.class";
-
-function headline_help() {
- ?>
- <P>Drupal's headline module both imports and exports RDF/RSS headlines.</P>
- <P>A lot of news-oriented websites are now publishing news (headlines) and making their content available through XML, RSS and RDF backend files. They syndicate free content and allow retrieval and further transmission, aggregation, and online publication. In its current state, drupal's headline module supports RDF and RSS backends.</P>
- <P>RSS was originally developed by Netscape to allow adding news channels to "My Netscape" sites, but it has since become adopted as the <I>de facto</I> net standard for distributing headlines and brief dynamic texts.</P>
- <P>The headline module goes out to a list of configured news sites once an hour or so (driven by cron), downloads new RSS/RDF data and makes it available to your visitors. In addition, your headlines are exported as well and can be retrieved by other sites from <CODE><?php echo path_uri(); ?>export/headlines.rdf</CODE>.</P>
- <?php
-}
-
-function headline_conf_options() {
- $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 1000000000 => t("Never"));
- $output .= form_select(t("Update interval"), "headline_cron_time" , variable_get("headline_cron_time", 86400), $period, t("The update interval indicating how often you want to update your headline channels. Requires crontab."));
- return $output;
-}
-
-
-function headline_cron() {
- if (time() - variable_get("headline_cron_last", 0) > variable_get("headline_cron_time", time())) {
- variable_set("headline_cron_last", time());
-
- $result = db_query("SELECT * FROM channel");
- while ($channel = db_fetch_object($result)) {
- $backend = new Backend($channel->id);
- }
- }
-}
-
-function headline_blocks() {
- global $theme;
-
- // Get channel info:
- $result = db_query("SELECT * FROM channel ORDER BY id");
-
- $theme->header();
-
- print "<TABLE BORDER=\"0\">\n";
- while ($channel = db_fetch_object($result)) {
- if ($state % 3 == 0) print " <TR>\n";
-
- print " <TD ALIGN=\"center\" VALIGN=\"top\" WIDTH=\"33%\">\n";
-
- // Load backend from database:
- $backend = new backend($channel->id);
-
- if ($backend->headlines) {
- unset($content);
- foreach ($backend->headlines as $headline) $content .= "<LI>$headline</LI>\n";
- }
- else {
- $content = "no headlines available\n";
- }
-
- // Print backend box to screen:
- $theme->box($backend->site, $content);
- print " </TD>\n";
-
- if ($state % 3 == 2) print " </TR>\n";
-
- $state += 1;
- }
- print "</TABLE>\n";
-
- $theme->footer();
-}
-
-function headline_page() {
- global $type;
-
- switch($type) {
- case "rdf":
- headline_rdf();
- break;
- default:
- headline_blocks();
- }
-}
-
-
-function headline_block() {
- $result = db_query("SELECT * FROM channel");
- while ($channel = db_fetch_object($result)) {
- $backend = new Backend($channel->id);
-
- if ($backend->headlines) {
- unset($content);
- foreach ($backend->headlines as $headline) {
- $content .= "<LI>$headline</LI>\n";
- }
- }
- else {
- $content = "no headlines available";
- }
-
- $blocks[$channel->id]["subject"] = $backend->site;
- $blocks[$channel->id]["content"] = $content;
- $blocks[$channel->id]["info"] = "$backend->site headlines";
- $blocks[$channel->id]["link"] = $backend->url;
- }
- return $blocks;
-}
-
-function headline_admin_display() {
- global $theme;
-
- // Get channel info:
- $result = db_query("SELECT * FROM channel ORDER BY id");
-
- $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
- $output .= " <TH>site</TH><TH>contact</TH><TH>last update</TH><TH COLSPAN=\"3\">operations</TH></TR>\n";
-
- while ($channel = db_fetch_object($result)) {
- // Load backend from database:
- $backend = new backend($channel->id);
-
- $output .= "<TR>\n";
- $output .= " <TD>". format_url($backend->url, $backend->site) ."</TD>\n";
- $output .= " <TD>". format_email($backend->contact) ."</TD>\n";
- $output .= " <TD ALIGN=\"center\">". ($backend->timestamp == 1 ? "failed" : format_interval(time() - $backend->timestamp) ." ago") ."</TD>\n";
- $output .= " <TD ALIGN=\"center\"><A HREF=\"admin.php?mod=headline&op=refresh&id=$backend->id\">refresh</A></TD>\n";
- $output .= " <TD ALIGN=\"center\"><A HREF=\"admin.php?mod=headline&op=edit&id=$backend->id\">edit</A></TD>\n";
- $output .= " <TD ALIGN=\"center\"><A HREF=\"admin.php?mod=headline&op=delete&id=$backend->id\">delete</A></TD>\n";
- $output .= "</TR>\n";
- }
-
- $output .= "</TABLE>\n";
-
- print $output;
-}
-
-function headline_admin_add() {
- $output .= " <FORM ACTION=\"admin.php?mod=headline\" METHOD=\"post\">\n";
- $output .= " <P>\n";
- $output .= " <B>Site name:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"site\" SIZE=\"50\">\n";
- $output .= " </P>\n";
- $output .= " <P>\n";
- $output .= " <B>URL:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"url\" SIZE=\"50\">\n";
- $output .= " </P>\n";
- $output .= " <P>\n";
- $output .= " <B>Backend file:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"backend\" SIZE=\"50\">\n";
- $output .= " </P>\n";
- $output .= " <P>\n";
- $output .= " <B>Contact information:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"contact\" SIZE=\"50\">\n";
- $output .= " </P>\n";
- $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Add backend\">\n";
- $output .= " </FORM>\n";
-
- print $output;
-}
-
-function headline_admin_edit($id) {
- $result = db_query("SELECT * FROM channel WHERE id='$id' ORDER BY id");
-
- if ($channel = db_fetch_object($result)) {
- $output .= " <FORM ACTION=\"admin.php?mod=headline\" METHOD=\"post\">\n";
- $output .= " <INPUT TYPE=\"hidden\" NAME=\"id\" VALUE=\"$id\">\n";
- $output .= " <P>\n";
- $output .= " <B>Site name:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"site\" SIZE=\"50\" VALUE=\"$channel->site\">\n";
- $output .= " </P>\n";
- $output .= " <P>\n";
- $output .= " <B>URL:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"url\" SIZE=\"50\" VALUE=\"$channel->url\">\n";
- $output .= " </P>\n";
- $output .= " <P>\n";
- $output .= " <B>Backend file:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"backend\" SIZE=\"50\" VALUE=\"$channel->file\">\n";
- $output .= " </P>\n";
- $output .= " <P>\n";
- $output .= " <B>Contact information:</B><BR>\n";
- $output .= " <INPUT TYPE=\"text\" NAME=\"contact\" SIZE=\"50\" VALUE=\"$channel->contact\">\n";
- $output .= " </P>\n";
- $output .= " <INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Save backend\">\n";
- $output .= " </FORM>\n";
- } else {
- $output .= "Invalid Channel ID.\n";
- }
- print $output;
-}
-
-function headline_admin_rehash() {
- module_rehash_blocks("headline");
-}
-
-function headline_admin() {
- global $op, $id, $site, $url, $backend, $contact;
-
- print "<SMALL><A HREF=\"admin.php?mod=headline&op=add\">add new channel</A> | <A HREF=\"admin.php?mod=headline\">overview</A> | <A HREF=\"admin.php?mod=headline&op=help\">help</A></SMALL><HR>";
-
- switch($op) {
- case "add":
- headline_admin_add();
- break;
- case "edit":
- headline_admin_edit(check_input($id));
- break;
- case "delete":
- $channel = new backend($id);
- $channel->delete();
- headline_admin_rehash();
- headline_admin_display();
- break;
- case "help":
- headline_help();
- break;
- case "refresh":
- $channel = new backend($id);
- $channel->refresh();
- headline_admin_display();
- break;
- case "Add backend":
- $channel = new backend(check_input($id), check_input($site), check_input($url), check_input($backend), check_input($contact));
- $channel->add();
- headline_admin_rehash();
- headline_admin_display();
- break;
- case "Save backend":
- $channel = new backend(check_input($id));
- $channel->site = $site;
- $channel->url = $url;
- $channel->file = $backend;
- $channel->contact = $contact;
- $channel->save();
- headline_admin_rehash();
- // fall through:
- default:
- headline_admin_display();
- }
-}
-
-function headline_export_rdf() {
- global $status;
-
- $uri = substr(path_uri(), 0, strlen(path_uri()) - strlen("export/"));
-
- header("Content-Type: text/plain");
-
- print "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
- print "<rdf:RDF\n";
- print " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
- print " xmlns=\"http://my.netscape.com/rdf/simple/0.9/\">\n";
-
- print "<channel>\n";
- print " <title>". variable_get(site_name, "drupal") ."</title>\n";
- print " <link>". $uri ."</link>\n";
- print " <description>". variable_get(site_name, "drupal") ."</description>\n";
- print "</channel>\n";
-
- $result = db_query("SELECT * FROM node WHERE promote = '1' AND status = '$status[posted]' ORDER BY timestamp DESC LIMIT 10");
-
- while ($node = db_fetch_object($result)) {
- print "<item>\n";
- print " <title>". check_export($node->title) ."</title>\n";
- print " <link>". $uri ."node.php?id=$node->nid</link>\n";
- print "</item>\n";
- }
-
- print "</rdf:RDF>\n";
-}
-
-function headline_export_rss() {
- global $status;
-
- $uri = substr(path_uri(), 0, strlen(path_uri()) - strlen("export/"));
-
- header("Content-Type: text/plain");
-
- print "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
- print "<rdf:RDF\n";
-
- print "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
- print "xmlns=\"http://purl.org/rss/1.0/\">\n\n";
-
- print "<channel rdf:about=\"". $uri ."export/headlinesRSS10.rdf\">\n";
- print " <title>". variable_get(site_name, "drupal") ."</title>\n";
- print " <link>". $uri ."</link>\n";
- print " <description>". variable_get(site_name, "drupal") ."</description>\n";
-
- print " <items>\n";
- print " <rdf:Seq>\n";
-
- $result = db_query("SELECT * FROM node WHERE promote = '1' AND status = '$status[posted]' ORDER BY timestamp DESC LIMIT 10");
-
- while ($node = db_fetch_object($result)) {
- print " <rdf:li resource=\"". $uri ."node.php?id=$node->nid\" />\n";
- }
-
- print " </rdf:Seq>\n";
- print " </items>\n";
- print "</channel>\n\n";
-
- $result = db_query("SELECT * FROM node WHERE promote = '1' AND status = '$status[posted]' ORDER BY timestamp DESC LIMIT 10");
-
- while ($node = db_fetch_object($result)) {
- print "<item rdf:about=\"". $uri ."node.php?id=$node->nid\">\n";
- print " <title>". check_export($node->title) ."</title>\n";
- print " <link>". $uri ."node.php?id=$node->nid</link>\n";
-
- if ($node->abstract) print " <description>". check_output($node->abstract, 1) ."</description>\n";
- if ($node->body) print " <description>". check_output($node->body, 1) ."</description>\n";
-
- print "</item>\n";
- }
-
- print "</rdf:RDF>\n";
-}
-
-function headline_export($uri) {
- switch ($uri[2]) {
- case "headlines.rss":
- headline_export_rss();
- break;
- case "headlines.rdf":
- case "default":
- headline_export_rdf();
- }
-}
-
-?>
diff --git a/modules/import.module b/modules/import.module
new file mode 100644
index 000000000..a4b85041e
--- /dev/null
+++ b/modules/import.module
@@ -0,0 +1,275 @@
+<?php
+
+include_once "modules/backend.class";
+
+function import_help() {
+ ?>
+ <P>TODO - anyone?</P>
+ <?php
+}
+
+function import_cron() {
+ $result = db_query("SELECT * FROM feed");
+ while ($feed = db_fetch_array($result)) {
+ // remove expired items:
+ db_query("DELETE FROM item WHERE fid = '$feed[fid]' AND timestamp - ". time() ." > $feed[uncache]");
+
+ // update feeds:
+ if ($feed[timestamp] + $feed[refresh] < time()) import_update($feed);
+ }
+}
+
+function import_bundle($attribute, $limit = 100) {
+ if ($attribute) {
+ // compose query:
+ $keys = explode(",", $attribute);
+ foreach ($keys as $key) $where[] = "attribute LIKE '%". trim($key) ."%'";
+
+ $result = db_query("SELECT * FROM item WHERE ". implode(" OR ", $where) ." ORDER BY timestamp DESC LIMIT $limit");
+
+ while ($item = db_fetch_object($result)) {
+ $output .= "<LI><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A></LI>";
+ }
+
+ return "$output";
+ }
+}
+
+function import_view_bundle() {
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+ while ($bundle = db_fetch_object($result)) {
+ $output .= "<B>$bundle->title</B><UL>". import_bundle($bundle->attribute) ."</UL>";
+ }
+ return $output;
+}
+
+function import_block() {
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+ while ($bundle = db_fetch_object($result)) {
+ $i++;
+ $blocks[$i][subject] = $bundle->title;
+ $blocks[$i][content] = import_bundle($bundle->attribute, 10);
+ $blocks[$i][info] = "$bundle->title bundle";
+ }
+ return $blocks;
+}
+
+function import_update($feed) {
+
+ // open socket:
+ $url = parse_url($feed[link]);
+ $fp = fsockopen($url[host], ($url[port] ? $url[port] : 80), $errno, $errstr, 15);
+
+ if ($fp) {
+ // fetch data:
+ fputs($fp, "GET $url[path]?$url[query] HTTP/1.0\nUser-Agent: ". variable_get(site_name, "drupal") ."\nHost: $url[host]\nAccept: */*\n\n");
+ while(!feof($fp)) $data .= fgets($fp, 128);
+
+ if (strstr($data, "200 OK")) {
+
+ eregi("<item(.*)</item>", $data, $data);
+
+ foreach (explode("</item>", $data[0]) as $item) {
+ $l = eregi("<link>(.*)</link>", $item, $link);
+ $t = eregi("<title>(.*)</title>", $item, $title);
+ $a = eregi("<author>(.*)</author>", $item, $author);
+ $d = eregi("<description>(.*)</description>", $item, $description);
+
+ if ($l || $t || $a || $d) {
+ import_save_item(array(fid => $feed[fid], title => $title[0], link => $link[0], author => $author[0], description => $description[0], attribute => $feed[attribute]));
+ }
+ }
+
+ db_query("UPDATE feed SET timestamp = '". time() ."' WHERE fid = '". $feed[fid] ."'");
+ }
+ else {
+ watchdog("error", "failed to syndicate from '$feed[title]'");
+ }
+ }
+}
+
+function import_save_item($edit) {
+ if ($edit[iid] && $edit[title]) {
+ db_query("UPDATE item SET title = '". check_input($edit[title]) ."', link = '". check_input($edit[link]) ."', author = '". check_input($edit[author]) ."', description = '". check_input($edit[description]) ."', attribute = '". check_input($edit[attribute]) ."' WHERE iid = '$edit[iid]'");
+ }
+ else if ($edit[iid]) {
+ db_query("DELETE FROM item WHERE iid = '". check_input($edit[iid]) ."'");
+ }
+ else {
+ if (!db_fetch_object(db_query("SELECT iid FROM item WHERE link = '". check_input($edit[link]) ."'"))) {
+ db_query("INSERT INTO item (fid, title, link, author, description, attribute, timestamp) VALUES ('". check_input($edit[fid]) ."', '". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[author]) ."', '". check_input($edit[description]) ."', '". check_input($edit[attribute]) ."', '". time() ."')");
+ }
+ }
+}
+
+function import_form_bundle($edit = array()) {
+ global $REQUEST_URI;
+
+ $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the bundle.");
+ $form .= form_textfield("Attributes", "attribute", $edit[attribute], 50, 128, "A comma-seperated list of keywords describing the bundle.");
+
+ $form .= form_submit("Submit");
+
+ if ($edit[bid]) {
+ $form .= form_submit(t("Delete"));
+ $form .= form_hidden("bid", $edit[bid]);
+ }
+
+ return form($REQUEST_URI, $form);
+}
+
+function import_save_bundle($edit) {
+ if ($edit[bid] && $edit[title]) {
+ db_query("UPDATE bundle SET title = '". check_input($edit[title]) ."', attribute = '". check_input($edit[attribute]) ."' WHERE bid = '". check_input($edit[bid]) ."'");
+ }
+ else if ($edit[bid]) {
+ db_query("DELETE FROM bundle WHERE bid = '". check_input($edit[bid]) ."'");
+ }
+ else {
+ db_query("INSERT INTO bundle (title, attribute) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[attribute]) ."')");
+ }
+
+ module_rehash_blocks("import");
+}
+
+function import_form_feed($edit = array()) {
+ global $REQUEST_URI;
+
+ $period = array(900 => format_interval(900), 1800 => format_interval(1800), 3600 => format_interval(3600), 7200 => format_interval(7200), 10800 => format_interval(10800), 21600 => format_interval(21600), 32400 => format_interval(32400), 43200 => format_interval(43200), 64800 => format_interval(64800), 86400 => format_interval(86400), 172800 => format_interval(172800), 259200 => format_interval(259200), 604800 => format_interval(604800), 1209600 => format_interval(1209600), 2419200 => format_interval(2419200));
+
+ $form .= form_textfield("Title", "title", $edit[title], 50, 64, "The name of the feed; typically the name of the website you syndicate content from.");
+ $form .= form_textfield("Link", "link", $edit[link], 50, 64, "The fully-qualified URL of the feed.");
+ $form .= form_textfield("Attributes", "attribute", $edit[attribute], 50, 128, "A comma-seperated list of keywords describing the feed.");
+ $form .= form_select("Update interval", "refresh", $edit[refresh], $period, "The refresh interval indicating how often you want to update this feed. Requires crontab.");
+ $form .= form_select("Expiration time", "uncache", $edit[uncache], $period, "The time cached items should be kept. Older items will be automatically discarded. Requires crontab.");
+
+ $form .= form_submit("Submit");
+
+ if ($edit[fid]) {
+ $form .= form_submit(t("Delete"));
+ $form .= form_hidden("fid", $edit[fid]);
+ }
+
+ return form($REQUEST_URI, $form);
+}
+
+function import_save_feed($edit) {
+ if ($edit[fid] && $edit[title]) {
+ db_query("UPDATE feed SET title = '". check_input($edit[title]) ."', link = '". check_input($edit[link]) ."', attribute = '". check_input($edit[attribute]) ."', refresh = '". check_input($edit[refresh]) ."', uncache = '". check_input($edit[uncache]) ."' WHERE fid = '". check_input($edit[fid]) ."'");
+ db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'");
+ }
+ else if ($edit[fid]) {
+ db_query("DELETE FROM feed WHERE fid = '". check_input($edit[fid]) ."'");
+ db_query("DELETE FROM item WHERE fid = '". check_input($edit[fid]) ."'");
+ }
+ else {
+ db_query("INSERT INTO feed (title, link, attribute, refresh, uncache) VALUES ('". check_input($edit[title]) ."', '". check_input($edit[link]) ."', '". check_input($edit[attribute]) ."', '". check_input($edit[refresh]) ."', '". check_input($edit[uncache]) ."')");
+ }
+}
+
+function import_save_attributes($edit) {
+ foreach($edit as $iid => $value) {
+ db_query("UPDATE item SET attribute = '". check_input($value) ."' WHERE iid = '". check_input($iid) ."'");
+ }
+ return "attributes has been saved";
+}
+
+function import_get_feed($fid) {
+ return db_fetch_array(db_query("SELECT * FROM feed WHERE fid = '". check_input($fid) ."'"));
+}
+
+function import_get_bundle($bid) {
+ return db_fetch_array(db_query("SELECT * FROM bundle WHERE bid = '". check_input($bid) ."'"));
+}
+
+function import_view_feed() {
+ $result = db_query("SELECT f.*, COUNT(i.iid) AS items FROM feed f LEFT JOIN item i ON f.fid = i.fid GROUP BY f.fid ORDER BY f.title");
+
+ $output .= "<H3>Feed overview</H3>";
+ $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
+ $output .= " <TR><TH>title</TH><TH>attributes</TH><TH>items</TH><TH>last update</TH><TH>next update</TH><TH COLSPAN=\"2\">operations</TH></TR>\n";
+ while ($feed = db_fetch_object($result)) {
+ $output .= " <TR><TD>". check_output($feed->title) ."</TD><TD>". check_output($feed->attribute) ."</TD><TD>". format_plural($feed->items, "item", "items") ."</TD><TD>". ($feed->timestamp ? format_interval(time() - $feed->timestamp) ." ago" : "never") ."</TD><TD>". ($feed->timestamp ? format_interval($feed->timestamp + $feed->refresh - time()) ." left" : "never") ."</TD><TD><A HREF=\"admin.php?mod=import&type=feed&op=edit&id=$feed->fid\">edit feed</A></TD><TD><A HREF=\"admin.php?mod=import&type=feed&op=update&id=$feed->fid\">update items</A></TD></TR>\n";
+ }
+ $output .= "</TABLE>\n";
+
+ $result = db_query("SELECT * FROM bundle ORDER BY title");
+
+ $output .= "<H3>Bundle overview</H3>";
+ $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
+ $output .= " <TR><TH>title</TH><TH>attributes</TH><TH>operations</TH></TR>\n";
+ while ($bundle = db_fetch_object($result)) {
+ $output .= " <TR><TD>". check_output($bundle->title) ."</TD><TD>". check_output($bundle->attribute) ."</TD><TD><A HREF=\"admin.php?mod=import&type=bundle&op=edit&id=$bundle->bid\">edit bundle</A></TD></TR>\n";
+ }
+ $output .= "</TABLE>\n";
+
+ return $output;
+}
+
+function import_view_item() {
+ global $REQUEST_URI;
+
+ $result = db_query("SELECT i.*, f.title AS feed FROM item i LEFT JOIN feed f ON i.fid = f.fid ORDER BY i.timestamp DESC LIMIT 50");
+
+ $output .= "<FORM ACTION=\"$REQUEST_URI\" METHOD=\"post\">\n";
+ $output .= "<TABLE BORDER=\"1\" CELLSPADDING=\"2\" CELLSPACING=\"2\">\n";
+ $output .= " <TR><TH>time</TH><TH>feed</TH><TH>item</TH></TR>\n";
+ while ($item = db_fetch_object($result)) {
+ $output .= " <TR><TD VALIGN=\"top\" NOWRAP>". format_date($item->timestamp, "custom", "m/d/y") ."<BR>".format_date($item->timestamp, "custom", "H:i") ."</TD><TD ALIGN=\"center\" VALIGN=\"top\" NOWRAP><A HREF=\"admin.php?mod=import&type=feed&op=edit&id=$item->fid\">". check_output($item->feed) ."</A></TD><TD><A HREF=\"". check_output($item->link) ."\">". check_output($item->title) ."</A>". ($item->description ? "<BR><SMALL><I>". check_output($item->description) ."</I></SMALL>" : "") ."<BR><INPUT TYPE=\"text\" NAME=\"edit[$item->iid]\" VALUE=\"". check_form($item->attribute) ."\" SIZE=\"50\"></TD></TR>\n";
+ }
+ $output .= "</TABLE>\n";
+ $output .= "<INPUT TYPE=\"submit\" NAME=\"op\" VALUE=\"Save attributes\">\n";
+ $output .= "</FORM>\n";
+
+ return $output;
+}
+
+function import_admin() {
+ global $op, $id, $type, $edit;
+
+ print "<SMALL><A HREF=\"admin.php?mod=import&type=bundle&op=add\">add new bundle</A> | <A HREF=\"admin.php?mod=import&type=feed&op=add\">add new feed</A> | <A HREF=\"admin.php?mod=import&type=bundle&op=view\">available bundles</A> | <A HREF=\"admin.php?mod=import&type=item&op=view\">available items</A> | <A HREF=\"admin.php?mod=import&op=view\">overview</A> | <A HREF=\"admin.php?mod=import&op=help\">help</A></SMALL><HR>";
+
+ switch($op) {
+ case "help":
+ print import_help();
+ break;
+ case "add":
+ if ($type == "bundle")
+ print import_form_bundle();
+ else
+ print import_form_feed();
+ break;
+ case "edit":
+ if ($type == "bundle")
+ print import_form_bundle(import_get_bundle($id));
+ else
+ print import_form_feed(import_get_feed($id));
+ break;
+ case "update":
+ print import_update(import_get_feed($id));
+ print import_view_feed();
+ break;
+ case "Save attributes":
+ print status(import_save_attributes($edit));
+ print import_view_item();
+ break;
+ case "Delete":
+ $edit[title] = 0;
+ // fall through:
+ case "Submit":
+ if ($type == "bundle")
+ print status(import_save_bundle($edit));
+ else
+ print status(import_save_feed($edit));
+ // fall through:
+ default:
+ if ($type == "bundle")
+ print import_view_bundle();
+ else if ($type == "item")
+ print import_view_item();
+ else
+ print import_view_feed();
+ }
+}
+
+?>