-
-{{ endif }}
diff --git a/mailstream/view/settings.tpl b/mailstream/view/settings.tpl
deleted file mode 100644
index 982bc40f..00000000
--- a/mailstream/view/settings.tpl
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
Mail Stream Settings
-
-
diff --git a/mathjax.tgz b/mathjax.tgz
index da8409f8..c639f90f 100644
Binary files a/mathjax.tgz and b/mathjax.tgz differ
diff --git a/mathjax/view/smarty3/admin.tpl b/mathjax/templates/admin.tpl
similarity index 100%
rename from mathjax/view/smarty3/admin.tpl
rename to mathjax/templates/admin.tpl
diff --git a/mathjax/view/admin.tpl b/mathjax/view/admin.tpl
deleted file mode 100644
index 1c723cdd..00000000
--- a/mathjax/view/admin.tpl
+++ /dev/null
@@ -1,2 +0,0 @@
-{{ inc field_input.tpl with $field=$baseurl }}{{endinc }}
-
diff --git a/membersince.tgz b/membersince.tgz
index ec19fddc..d62be961 100755
Binary files a/membersince.tgz and b/membersince.tgz differ
diff --git a/morechoice.tgz b/morechoice.tgz
index 4065a2b7..6352e401 100644
Binary files a/morechoice.tgz and b/morechoice.tgz differ
diff --git a/morepokes.tgz b/morepokes.tgz
index 0e6a3a2d..a5d78a55 100644
Binary files a/morepokes.tgz and b/morepokes.tgz differ
diff --git a/namethingy.tgz b/namethingy.tgz
index 9642e384..af13e8df 100644
Binary files a/namethingy.tgz and b/namethingy.tgz differ
diff --git a/notimeline.tgz b/notimeline.tgz
index d42c5026..ebe1851b 100644
Binary files a/notimeline.tgz and b/notimeline.tgz differ
diff --git a/nsfw.tgz b/nsfw.tgz
index 740132ea..c402fb99 100755
Binary files a/nsfw.tgz and b/nsfw.tgz differ
diff --git a/numfriends.tgz b/numfriends.tgz
index dcb81aa4..1958a74f 100644
Binary files a/numfriends.tgz and b/numfriends.tgz differ
diff --git a/openstreetmap.tgz b/openstreetmap.tgz
index a2d2d259..621dd9e2 100644
Binary files a/openstreetmap.tgz and b/openstreetmap.tgz differ
diff --git a/openstreetmap/view/smarty3/admin.tpl b/openstreetmap/templates/admin.tpl
similarity index 100%
rename from openstreetmap/view/smarty3/admin.tpl
rename to openstreetmap/templates/admin.tpl
diff --git a/openstreetmap/view/admin.tpl b/openstreetmap/view/admin.tpl
deleted file mode 100644
index 75db9cd7..00000000
--- a/openstreetmap/view/admin.tpl
+++ /dev/null
@@ -1,3 +0,0 @@
-{{ inc field_input.tpl with $field=$tmsserver }}{{ endinc }}
-{{ inc field_input.tpl with $field=$zoom }}{{ endinc }}
-
diff --git a/page.tgz b/page.tgz
index 26d5d66c..9a2896fe 100644
Binary files a/page.tgz and b/page.tgz differ
diff --git a/piwik.tgz b/piwik.tgz
index 3232352a..c2922924 100755
Binary files a/piwik.tgz and b/piwik.tgz differ
diff --git a/piwik/view/smarty3/admin.tpl b/piwik/templates/admin.tpl
similarity index 100%
rename from piwik/view/smarty3/admin.tpl
rename to piwik/templates/admin.tpl
diff --git a/piwik/view/admin.tpl b/piwik/view/admin.tpl
deleted file mode 100644
index e57758a9..00000000
--- a/piwik/view/admin.tpl
+++ /dev/null
@@ -1,5 +0,0 @@
-{{ inc field_input.tpl with $field=$baseurl }}{{ endinc }}
-{{ inc field_input.tpl with $field=$siteid }}{{ endinc }}
-{{ inc field_checkbox.tpl with $field=$optout }}{{ endinc }}
-{{ inc field_checkbox.tpl with $field=$async }}{{ endinc }}
-
diff --git a/planets.tgz b/planets.tgz
index 2c744adf..a545f429 100644
Binary files a/planets.tgz and b/planets.tgz differ
diff --git a/poormancron.tgz b/poormancron.tgz
index 8eda6264..432236f0 100755
Binary files a/poormancron.tgz and b/poormancron.tgz differ
diff --git a/posterous.tgz b/posterous.tgz
index a3955e84..446dc66e 100644
Binary files a/posterous.tgz and b/posterous.tgz differ
diff --git a/privacy_image_cache.tgz b/privacy_image_cache.tgz
index bbf962c6..9fd080dc 100644
Binary files a/privacy_image_cache.tgz and b/privacy_image_cache.tgz differ
diff --git a/procrunner.tgz b/procrunner.tgz
index fec9dfa7..cdb0e98c 100644
Binary files a/procrunner.tgz and b/procrunner.tgz differ
diff --git a/public_server.tgz b/public_server.tgz
index 7d6beb7d..8fcf6108 100755
Binary files a/public_server.tgz and b/public_server.tgz differ
diff --git a/qcomment.tgz b/qcomment.tgz
index 3d38facd..ba0b2456 100644
Binary files a/qcomment.tgz and b/qcomment.tgz differ
diff --git a/randplace.tgz b/randplace.tgz
index 9dbab84e..c1ab0b2a 100755
Binary files a/randplace.tgz and b/randplace.tgz differ
diff --git a/remote_permissions.tgz b/remote_permissions.tgz
index d50c66c6..2cc7b0fb 100644
Binary files a/remote_permissions.tgz and b/remote_permissions.tgz differ
diff --git a/remote_permissions/view/smarty3/admin.tpl b/remote_permissions/templates/admin.tpl
similarity index 100%
rename from remote_permissions/view/smarty3/admin.tpl
rename to remote_permissions/templates/admin.tpl
diff --git a/remote_permissions/view/smarty3/settings.tpl b/remote_permissions/templates/settings.tpl
similarity index 100%
rename from remote_permissions/view/smarty3/settings.tpl
rename to remote_permissions/templates/settings.tpl
diff --git a/remote_permissions/view/admin.tpl b/remote_permissions/view/admin.tpl
deleted file mode 100644
index 60558808..00000000
--- a/remote_permissions/view/admin.tpl
+++ /dev/null
@@ -1,3 +0,0 @@
-{{ inc field_radio.tpl with $field=$global }}{{ endinc }}
-{{ inc field_radio.tpl with $field=$individual }}{{ endinc }}
-
diff --git a/remote_permissions/view/settings.tpl b/remote_permissions/view/settings.tpl
deleted file mode 100644
index 9fd98957..00000000
--- a/remote_permissions/view/settings.tpl
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
$remote_perms_title
-
- $remote_perms_label
-
-
-
-
diff --git a/rendertime.tgz b/rendertime.tgz
index b8ae8086..59f9e47b 100644
Binary files a/rendertime.tgz and b/rendertime.tgz differ
diff --git a/retriever.tgz b/retriever.tgz
new file mode 100644
index 00000000..cd87d58a
Binary files /dev/null and b/retriever.tgz differ
diff --git a/retriever/database.sql b/retriever/database.sql
new file mode 100644
index 00000000..2513dd28
--- /dev/null
+++ b/retriever/database.sql
@@ -0,0 +1,35 @@
+CREATE TABLE IF NOT EXISTS `retriever_rule` (
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `uid` int(11) NOT NULL,
+ `contact-id` int(11) NOT NULL,
+ `data` mediumtext NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `uid` (`uid`),
+ KEY `contact-id` (`contact-id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+CREATE TABLE IF NOT EXISTS `retriever_item` (
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `item-uri` varchar(800) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
+ `item-uid` int(10) unsigned NOT NULL DEFAULT '0',
+ `contact-id` int(10) unsigned NOT NULL DEFAULT '0',
+ `resource` int(11) NOT NULL,
+ `parent` int(11) NOT NULL,
+ `finished` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ KEY `resource` (`resource`),
+ KEY `all` (`item-uri`, `item-uid`, `contact-id`),
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+CREATE TABLE IF NOT EXISTS `retriever_resource` (
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+ `type` char(255) NOT NULL,
+ `binary` int(1) NOT NULL DEFAULT 0,
+ `url` varchar(800) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
+ `created` timestamp NOT NULL DEFAULT now(),
+ `completed` timestamp NULL DEFAULT NULL,
+ `last-try` timestamp NULL DEFAULT NULL,
+ `num-tries` int(11) NOT NULL DEFAULT 0,
+ `data` mediumtext NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
diff --git a/retriever/retriever.php b/retriever/retriever.php
new file mode 100644
index 00000000..e96324ca
--- /dev/null
+++ b/retriever/retriever.php
@@ -0,0 +1,736 @@
+
+ */
+
+function retriever_install() {
+ register_hook('plugin_settings', 'addon/retriever/retriever.php', 'retriever_plugin_settings');
+ register_hook('plugin_settings_post', 'addon/retriever/retriever.php', 'retriever_plugin_settings_post');
+ register_hook('post_remote', 'addon/retriever/retriever.php', 'retriever_post_remote_hook');
+ register_hook('contact_photo_menu', 'addon/retriever/retriever.php', 'retriever_contact_photo_menu');
+ register_hook('cron', 'addon/retriever/retriever.php', 'retriever_cron');
+
+ $schema = file_get_contents(dirname(__file__).'/database.sql');
+ $arr = explode(';', $schema);
+ foreach ($arr as $a) {
+ $r = q($a);
+ }
+
+ $r = q("SELECT `id` FROM `pconfig` WHERE `cat` LIKE 'retriever_%%'");
+ if (count($r) || (get_config('retriever', 'dbversion') == '0.1')) {
+ $retrievers = array();
+ $r = q("SELECT SUBSTRING(`cat`, 10) AS `contact`, `k`, `v` FROM `pconfig` WHERE `cat` LIKE 'retriever%%'");
+ foreach ($r as $rr) {
+ $retrievers[$rr['contact']][$rr['k']] = $rr['v'];
+ }
+ foreach ($retrievers as $k => $v) {
+ $rr = q("SELECT `uid` FROM `contact` WHERE `id` = %d", intval($k));
+ $uid = $rr[0]['uid'];
+ $v['images'] = 'on';
+ q("INSERT INTO `retriever_rule` (`uid`, `contact-id`, `data`) VALUES (%d, %d, '%s')",
+ intval($uid), intval($k), dbesc(json_encode($v)));
+ }
+ q("DELETE FROM `pconfig` WHERE `cat` LIKE 'retriever%%'");
+ }
+ if (get_config('retriever', 'dbversion') == '0.2') {
+ q("ALTER TABLE `retriever_resource` DROP COLUMN `retriever`");
+ }
+ if (get_config('retriever', 'dbversion') == '0.3') {
+ q("ALTER TABLE `retriever_item` MODIFY COLUMN `item-uri` varchar(800) CHARACTER SET ascii NOT NULL");
+ q("ALTER TABLE `retriever_resource` MODIFY COLUMN `url` varchar(800) CHARACTER SET ascii NOT NULL");
+ }
+ if (get_config('retriever', 'dbversion') == '0.4') {
+ q("ALTER TABLE `retriever_item` ADD COLUMN `finished` tinyint(1) unsigned NOT NULL DEFAULT '0'");
+ }
+ if (get_config('retriever', 'dbversion') == '0.5') {
+ q('ALTER TABLE `retriever_resource` CHANGE `created` `created` timestamp NOT NULL DEFAULT now()');
+ q('ALTER TABLE `retriever_resource` CHANGE `completed` `completed` timestamp NULL DEFAULT NULL');
+ q('ALTER TABLE `retriever_resource` CHANGE `last-try` `last-try` timestamp NULL DEFAULT NULL');
+ q('ALTER TABLE `retriever_item` DROP KEY `all`');
+ q('ALTER TABLE `retriever_item` ADD KEY `all` (`item-uri`, `item-uid`, `contact-id`)');
+ }
+ if (get_config('retriever', 'dbversion') == '0.6') {
+ q('ALTER TABLE `retriever_item` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin');
+ q('ALTER TABLE `retriever_item` CHANGE `item-uri` `item-uri` varchar(800) CHARACTER SET ascii COLLATE ascii_bin NOT NULL');
+ q('ALTER TABLE `retriever_resource` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin');
+ q('ALTER TABLE `retriever_resource` CHANGE `url` `url` varchar(800) CHARACTER SET ascii COLLATE ascii_bin NOT NULL');
+ q('ALTER TABLE `retriever_rule` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin');
+ }
+ if (get_config('retriever', 'dbversion') == '0.7') {
+ $r = q("SELECT `id`, `data` FROM `retriever_rule`");
+ foreach ($r as $rr) {
+ logger('retriever_install: retriever ' . $rr['id'] . ' old config ' . $rr['data'], LOGGER_DATA);
+ $data = json_decode($rr['data'], true);
+ if ($data['pattern']) {
+ $matches = array();
+ if (preg_match("/\/(.*)\//", $data['pattern'], $matches)) {
+ $data['pattern'] = $matches[1];
+ }
+ }
+ if ($data['match']) {
+ $include = array();
+ foreach (explode('|', $data['match']) as $component) {
+ $matches = array();
+ if (preg_match("/([A-Za-z][A-Za-z0-9]*)\[@([A-Za-z][a-z0-9]*)='([^']*)'\]/", $component, $matches)) {
+ $include[] = array(
+ 'element' => $matches[1],
+ 'attribute' => $matches[2],
+ 'value' => $matches[3]);
+ }
+ if (preg_match("/([A-Za-z][A-Za-z0-9]*)\[contains(concat(' ',normalize-space(@class),' '),' ([^ ']+) ')]/", $component, $matches)) {
+ $include[] = array(
+ 'element' => $matches[1],
+ 'attribute' => $matches[2],
+ 'value' => $matches[3]);
+ }
+ }
+ $data['include'] = $include;
+ unset($data['match']);
+ }
+ if ($data['remove']) {
+ $exclude = array();
+ foreach (explode('|', $data['remove']) as $component) {
+ $matches = array();
+ if (preg_match("/([A-Za-z][A-Za-z0-9]*)\[@([A-Za-z][a-z0-9]*)='([^']*)'\]/", $component, $matches)) {
+ $exclude[] = array(
+ 'element' => $matches[1],
+ 'attribute' => $matches[2],
+ 'value' => $matches[3]);
+ }
+ if (preg_match("/([A-Za-z][A-Za-z0-9]*)\[contains(concat(' ',normalize-space(@class),' '),' ([^ ']+) ')]/", $component, $matches)) {
+ $exclude[] = array(
+ 'element' => $matches[1],
+ 'attribute' => $matches[2],
+ 'value' => $matches[3]);
+ }
+ }
+ $data['exclude'] = $exclude;
+ unset($data['remove']);
+ }
+ $r = q('UPDATE `retriever_rule` SET `data` = "%s" WHERE `id` = %d', dbesc(json_encode($data)), $rr['id']);
+ logger('retriever_install: retriever ' . $rr['id'] . ' new config ' . json_encode($data), LOGGER_DATA);
+ }
+ }
+ set_config('retriever', 'dbversion', '0.8');
+}
+
+function retriever_uninstall() {
+ unregister_hook('plugin_settings', 'addon/retriever/retriever.php', 'retriever_plugin_settings');
+ unregister_hook('plugin_settings_post', 'addon/retriever/retriever.php', 'retriever_plugin_settings_post');
+ unregister_hook('post_remote', 'addon/retriever/retriever.php', 'retriever_post_remote_hook');
+ unregister_hook('plugin_settings', 'addon/retriever/retriever.php', 'retriever_plugin_settings');
+ unregister_hook('plugin_settings_post', 'addon/retriever/retriever.php', 'retriever_plugin_settings_post');
+ unregister_hook('contact_photo_menu', 'addon/retriever/retriever.php', 'retriever_contact_photo_menu');
+ unregister_hook('cron', 'addon/retriever/retriever.php', 'retriever_cron');
+}
+
+function retriever_module() {}
+
+function retriever_cron($a, $b) {
+ // 100 is a nice sane number. Maybe this should be configurable.
+ retriever_retrieve_items(100);
+ retriever_tidy();
+}
+
+$retriever_item_count = 0;
+
+function retriever_retrieve_items($max_items) {
+ global $retriever_item_count;
+
+ $retriever_schedule = array(array(1,'minute'),
+ array(10,'minute'),
+ array(1,'hour'),
+ array(1,'day'),
+ array(2,'day'),
+ array(1,'week'),
+ array(1,'month'));
+
+ $schedule_clauses = array();
+ for ($i = 0; $i < count($retriever_schedule); $i++) {
+ $num = $retriever_schedule[$i][0];
+ $unit = $retriever_schedule[$i][1];
+ array_push($schedule_clauses,
+ '(`num-tries` = ' . $i . ' AND TIMESTAMPADD(' . dbesc($unit) .
+ ', ' . intval($num) . ', `last-try`) < now())');
+ }
+
+ $retrieve_items = $max_items - $retriever_item_count;
+ do {
+ $r = q("SELECT * FROM `retriever_resource` WHERE `completed` IS NULL AND (`last-try` IS NULL OR %s) ORDER BY `last-try` ASC LIMIT %d",
+ dbesc(implode($schedule_clauses, ' OR ')),
+ intval($retrieve_items));
+ if (count($r) == 0) {
+ break;
+ }
+ foreach ($r as $rr) {
+ retrieve_resource($rr);
+ $retriever_item_count++;
+ }
+ $retrieve_items = $max_items - $retriever_item_count;
+ }
+ while ($retrieve_items > 0);
+
+ /* Look for items that are waiting even though the resource has
+ * completed. This usually happens because we've been asked to
+ * retrospectively apply a config change. It could also happen
+ * due to a cron job dying or something. */
+ $r = q("SELECT retriever_resource.`id` as resource, retriever_item.`id` as item FROM retriever_resource, retriever_item, retriever_rule WHERE retriever_item.`finished` = 0 AND retriever_item.`resource` = retriever_resource.`id` AND retriever_resource.`completed` IS NOT NULL AND retriever_item.`contact-id` = retriever_rule.`contact-id` AND retriever_item.`item-uid` = retriever_rule.`uid` LIMIT %d",
+ intval($retrieve_items));
+ if (!$r) {
+ $r = array();
+ }
+ foreach ($r as $rr) {
+ $resource = q("SELECT * FROM retriever_resource WHERE `id` = %d", $rr['resource']);
+ $retriever_item = retriever_get_retriever_item($rr['item']);
+ if (!$retriever_item) {
+ logger('retriever_retrieve_items: no retriever item with id ' . $rr['item']);
+ continue;
+ }
+ $item = retriever_get_item($retriever_item);
+ if (!$item) {
+ logger('retriever_retrieve_items: no item ' . $retriever_item['item-uri']);
+ continue;
+ }
+ $retriever = get_retriever($item['contact-id'], $item['uid']);
+ if (!$retriever) {
+ logger('retriever_retrieve_items: no retriever for item ' .
+ $retriever_item['item-uri'] . ' ' . $retriever_item['uid'] . ' ' . $item['contact-id']);
+ continue;
+ }
+ retriever_apply_completed_resource_to_item($retriever, $item, $resource[0]);
+ q("UPDATE `retriever_item` SET `finished` = 1 WHERE id = %d",
+ intval($retriever_item['id']));
+ retriever_check_item_completed($item);
+ }
+}
+
+function retriever_tidy() {
+ q("DELETE FROM retriever_resource WHERE completed IS NOT NULL AND completed < DATE_SUB(now(), INTERVAL 1 WEEK)");
+ q("DELETE FROM retriever_resource WHERE completed IS NULL AND created < DATE_SUB(now(), INTERVAL 3 MONTH)");
+
+ $r = q("SELECT retriever_item.id FROM retriever_item LEFT OUTER JOIN retriever_resource ON (retriever_item.resource = retriever_resource.id) WHERE retriever_resource.id is null");
+ foreach ($r as $rr) {
+ q('DELETE FROM retriever_item WHERE id = %d', intval($rr['id']));
+ }
+}
+
+function retrieve_resource($resource) {
+ logger('retrieve_resource: ' . ($resource['num-tries'] + 1) .
+ ' attempt at resource ' . $resource['id'] . ' ' . $resource['url'], LOGGER_DEBUG);
+ q("UPDATE `retriever_resource` SET `last-try` = now(), `num-tries` = `num-tries` + 1 WHERE id = %d",
+ intval($resource['id']));
+ $data = fetch_url($resource['url'], $resource['binary'], $resource['type']);
+ $resource['type'] = get_app()->get_curl_content_type();
+ if ($data) {
+ $resource['data'] = $data;
+ q("UPDATE `retriever_resource` SET `completed` = now(), `data` = '%s', `type` = '%s' WHERE id = %d",
+ dbesc($data), dbesc($resource['type']), intval($resource['id']));
+ retriever_resource_completed($resource);
+ }
+}
+
+function get_retriever($contact_id, $uid, $create = false) {
+ $r = q("SELECT * FROM `retriever_rule` WHERE `contact-id` = %d AND `uid` = %d",
+ intval($contact_id), intval($uid));
+ if (count($r)) {
+ $r[0]['data'] = json_decode($r[0]['data'], true);
+ return $r[0];
+ }
+ if ($create) {
+ q("INSERT INTO `retriever_rule` (`uid`, `contact-id`) VALUES (%d, %d)",
+ intval($uid), intval($contact_id));
+ $r = q("SELECT * FROM `retriever_rule` WHERE `contact-id` = %d AND `uid` = %d",
+ intval($contact_id), intval($uid));
+ return $r[0];
+ }
+}
+
+function retriever_get_retriever_item($id) {
+ $retriever_items = q("SELECT * FROM `retriever_item` WHERE id = %d", intval($id));
+ if (count($retriever_items) != 1) {
+ logger('retriever_get_retriever_item: unable to find retriever_item ' . $id, LOGGER_NORMAL);
+ return;
+ }
+ return $retriever_items[0];
+}
+
+function retriever_get_item($retriever_item) {
+ $items = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `contact-id` = %d",
+ dbesc($retriever_item['item-uri']),
+ intval($retriever_item['item-uid']),
+ intval($retriever_item['contact-id']));
+ if (count($items) != 1) {
+ logger('retriever_get_item: unexpected number of results ' .
+ count($items) . " when searching for item $uri $uid $cid", LOGGER_NORMAL);
+ return;
+ }
+ return $items[0];
+}
+
+function retriever_item_completed($retriever_item_id, $resource) {
+ logger('retriever_item_completed: id ' . $retriever_item_id . ' url ' . $resource['url'], LOGGER_DEBUG);
+
+ $retriever_item = retriever_get_retriever_item($retriever_item_id);
+ if (!$retriever_item) {
+ return;
+ }
+ // Note: the retriever might be null. Doesn't matter.
+ $retriever = get_retriever($retriever_item['contact-id'], $retriever_item['item-uid']);
+ $item = retriever_get_item($retriever_item);
+ if (!$item) {
+ return;
+ }
+
+ retriever_apply_completed_resource_to_item($retriever, $item, $resource);
+
+ q("UPDATE `retriever_item` SET `finished` = 1 WHERE id = %d",
+ intval($retriever_item['id']));
+ retriever_check_item_completed($item);
+}
+
+function retriever_resource_completed($resource) {
+ logger('retriever_resource_completed: id ' . $resource['id'] . ' url ' . $resource['url'], LOGGER_DEBUG);
+ $r = q("SELECT `id` FROM `retriever_item` WHERE `resource` = %d", $resource['id']);
+ foreach ($r as $rr) {
+ retriever_item_completed($rr['id'], $resource);
+ }
+}
+
+function apply_retrospective($retriever, $num) {
+ $r = q("SELECT * FROM `item` WHERE `contact-id` = %d ORDER BY `received` DESC LIMIT %d",
+ intval($retriever['contact-id']), intval($num));
+ foreach ($r as $item) {
+ q('UPDATE `item` SET `visible` = 0 WHERE `id` = %d', $item['id']);
+ retriever_on_item_insert($retriever, $item);
+ }
+}
+
+function retriever_on_item_insert($retriever, &$item) {
+ if (!$retriever || !$retriever['id']) {
+ logger('retriever_on_item_insert: No retriever supplied', LOGGER_NORMAL);
+ return;
+ }
+ if (!$retriever["data"]['enable'] == "on") {
+ return;
+ }
+ if ($retriever["data"]['pattern']) {
+ $url = preg_replace('/' . $retriever["data"]['pattern'] . '/', $retriever["data"]['replace'], $item['plink']);
+ logger('retriever_on_item_insert: Changed ' . $item['plink'] . ' to ' . $url, LOGGER_DATA);
+ }
+ else {
+ $url = $item['plink'];
+ }
+
+ $resource = add_retriever_resource($url);
+ $retriever_item_id = add_retriever_item($item, $resource);
+}
+
+function add_retriever_resource($url, $binary = false) {
+ logger('add_retriever_resource: ' . $url, LOGGER_DEBUG);
+ $r = q("SELECT * FROM `retriever_resource` WHERE `url` = '%s'", dbesc($url));
+ $resource = $r[0];
+ if (count($r)) {
+ logger('add_retriever_resource: Resource ' . $url . ' already requested', LOGGER_DEBUG);
+ return $r[0];
+ }
+ else {
+ q("INSERT INTO `retriever_resource` (`binary`, `url`) " .
+ "VALUES (%d, '%s')", intval($binary ? 1 : 0), dbesc($url));
+ $r = q("SELECT * FROM `retriever_resource` WHERE `url` = '%s'", dbesc($url));
+ return $r[0];
+ }
+}
+
+function add_retriever_item(&$item, $resource) {
+ logger('add_retriever_item: ' . $resource['url'] . ' for ' . $item['uri'] . ' ' . $item['uid'] . ' ' . $item['contact-id'], LOGGER_DEBUG);
+
+ q("INSERT INTO `retriever_item` (`item-uri`, `item-uid`, `contact-id`, `resource`) " .
+ "VALUES ('%s', %d, %d, %d)",
+ dbesc($item['uri']), intval($item['uid']), intval($item['contact-id']), intval($resource["id"]));
+ $r = q("SELECT id FROM `retriever_item` WHERE " .
+ "`item-uri` = '%s' AND `item-uid` = %d AND `contact-id` = %d AND `resource` = %d ORDER BY id DESC",
+ dbesc($item['uri']), intval($item['uid']), intval($item['contact-id']), intval($resource['id']));
+ if (!count($r)) {
+ logger("add_retriever_item: couldn't create retriever item for " .
+ $item['uri'] . ' ' . $item['uid'] . ' ' . $item['contact-id'],
+ LOGGER_NORMAL);
+ return;
+ }
+ logger('add_retriever_item: created retriever_item ' . $r[0]['id'] . ' for item ' . $item['uri'] . ' ' . $item['uid'] . ' ' . $item['contact-id'], LOGGER_DEBUG);
+ return $r[0]['id'];
+}
+
+function retriever_get_encoding($resource) {
+ $matches = array();
+ if (preg_match('/charset=(.*)/', $resource['type'], $matches)) {
+ return trim(array_pop($matches));
+ }
+ return 'utf-8';
+}
+
+function retriever_construct_xpath($spec) {
+ if (gettype($spec) != "array") {
+ return;
+ }
+ $components = array();
+ foreach ($spec as $clause) {
+ if (!$clause['attribute']) {
+ $components[] = $clause['element'];
+ continue;
+ }
+ if ($clause['attribute'] === 'class') {
+ $components[] =
+ $clause['element'] .
+ "[contains(concat(' ', normalize-space(@class), ' '), ' " .
+ $clause['value'] . " ')]";
+ }
+ else {
+ $components[] =
+ $clause['element'] . '[@' .
+ $clause['attribute'] . "='" .
+ $clause['value'] . "']";
+ }
+ }
+ // It would be better to do this in smarty3 in extract.tpl
+ return implode('|', $components);
+}
+
+function retriever_apply_dom_filter($retriever, &$item, $resource) {
+ logger('retriever_apply_dom_filter: applying XSLT to ' . $item['id'] . ' ' . $item['plink'], LOGGER_DEBUG);
+ require_once('include/html2bbcode.php');
+
+ if (!$retriever['data']['include']) {
+ return;
+ }
+ if (!$resource['data']) {
+ logger('retriever_apply_dom_filter: no text to work with', LOGGER_NORMAL);
+ return;
+ }
+
+ $encoding = retriever_get_encoding($resource);
+ logger('@@@ item type ' . $resource['type'] . ' encoding ' . $encoding);
+ $extracter_template = get_markup_template('extract.tpl', 'addon/retriever/');
+ $doc = new DOMDocument('1.0', 'utf-8');
+ if (strpos($resource['type'], 'html') !== false) {
+ @$doc->loadHTML($resource['data']);
+ }
+ else {
+ $doc->loadXML($resource['data']);
+ }
+ logger('@@@ actual encoding of document is ' . $doc->encoding);
+
+ $components = parse_url($item['plink']);
+ $rooturl = $components['scheme'] . "://" . $components['host'];
+ $dirurl = $rooturl . dirname($components['path']) . "/";
+
+ $params = array('$include' => retriever_construct_xpath($retriever['data']['include']),
+ '$exclude' => retriever_construct_xpath($retriever['data']['exclude']),
+ '$pageurl' => $item['plink'],
+ '$dirurl' => $dirurl,
+ '$rooturl' => $rooturl);
+ $xslt = replace_macros($extracter_template, $params);
+ $xmldoc = new DOMDocument();
+ $xmldoc->loadXML($xslt);
+ $xp = new XsltProcessor();
+ $xp->importStylesheet($xmldoc);
+ $transformed = $xp->transformToXML($doc);
+ $item['body'] = html2bbcode($transformed);
+ if (!strlen($item['body'])) {
+ logger('retriever_apply_dom_filter retriever ' . $retriever['id'] . ' item ' . $item['id'] . ': output was empty', LOGGER_NORMAL);
+ return;
+ }
+ $item['body'] .= "\n\n" . t('Retrieved') . ' ' . date("Y-m-d") . ': [url=';
+ $item['body'] .= $item['plink'];
+ $item['body'] .= ']' . $item['plink'] . '[/url]';
+ q("UPDATE `item` SET `body` = '%s', `edited` = '%s' WHERE `id` = %d",
+ dbesc($item['body']), dbesc(datetime_convert('UTC', 'UTC')), intval($item['id']));
+}
+
+function retrieve_images(&$item) {
+ $matches1 = array();
+ preg_match_all("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", $item["body"], $matches1);
+ $matches2 = array();
+ preg_match_all("/\[img\](.*?)\[\/img\]/ism", $item["body"], $matches2);
+ $matches = array_merge($matches1[3], $matches2[1]);
+ logger('retrieve_images: found ' . count($matches) . ' images for item ' . $item['uri'] . ' ' . $item['uid'] . ' ' . $item['contact-id'], LOGGER_DEBUG);
+ foreach ($matches as $url) {
+ if (strpos($url, get_app()->get_baseurl()) === FALSE) {
+ $resource = add_retriever_resource($url, true);
+ if (!$resource['completed']) {
+ add_retriever_item($item, $resource);
+ }
+ else {
+ retriever_transform_images($item, $resource);
+ }
+ }
+ }
+}
+
+function retriever_check_item_completed(&$item)
+{
+ $r = q('SELECT count(*) FROM retriever_item WHERE `item-uri` = "%s" ' .
+ 'AND `item-uid` = %d AND `contact-id` = %d AND `finished` = 0',
+ dbesc($item['uri']), intval($item['uid']),
+ intval($item['contact-id']));
+ $waiting = $r[0]['count(*)'];
+ logger('retriever_check_item_completed: item ' . $item['uri'] . ' ' . $item['uid']
+ . ' '. $item['contact-id'] . ' waiting for ' . $waiting . ' resources', LOGGER_DEBUG);
+ $old_visible = $item['visible'];
+ $item['visible'] = $waiting ? 0 : 1;
+ if (($item['id'] > 0) && ($old_visible != $item['visible'])) {
+ logger('retriever_check_item_completed: changing visible flag to ' . $item['visible'] . ' and invoking notifier ("edit_post", ' . $item['id'] . ')', LOGGER_DEBUG);
+ q("UPDATE `item` SET `visible` = %d, `edited` = '%s' WHERE `id` = %d",
+ intval($item['visible']),
+ dbesc(datetime_convert('UTC', 'UTC')),
+ intval($item['id']));
+ proc_run('php', "include/notifier.php", 'edit_post', $item['id']);
+ }
+}
+
+function retriever_apply_completed_resource_to_item($retriever, &$item, $resource) {
+ logger('retriever_apply_completed_resource_to_item: retriever ' .
+ ($retriever ? $retriever['id'] : 'none') .
+ ' resource ' . $resource['url'] . ' plink ' . $item['plink'], LOGGER_DEBUG);
+ if (strpos($resource['type'], 'image') !== false) {
+ retriever_transform_images($item, $resource);
+ }
+ if (!$retriever) {
+ return;
+ }
+ if ((strpos($resource['type'], 'html') !== false) ||
+ (strpos($resource['type'], 'xml') !== false)) {
+ retriever_apply_dom_filter($retriever, $item, $resource);
+ if ($retriever["data"]['images'] ) {
+ retrieve_images($item);
+ }
+ }
+}
+
+function retriever_store_photo($item, &$resource) {
+ $hash = photo_new_resource();
+
+ if (class_exists('Imagick')) {
+ try {
+ $image = new Imagick();
+ $image->readImageBlob($resource['data']);
+ $resource['width'] = $image->getImageWidth();
+ $resource['height'] = $image->getImageHeight();
+ }
+ catch (Exception $e) {
+ logger("ImageMagick couldn't process image " . $resource['id'] . " " . $resource['url'] . ' length ' . strlen($resource['data']) . ': ' . $e->getMessage(), LOGGER_DEBUG);
+ return false;
+ }
+ }
+ if (!array_key_exists('width', $resource)) {
+ $image = @imagecreatefromstring($resource['data']);
+ if ($image === false) {
+ logger("Couldn't process image " . $resource['id'] . " " . $resource['url'], LOGGER_DEBUG);
+ return false;
+ }
+ $resource['width'] = imagesx($image);
+ $resource['height'] = imagesy($image);
+ imagedestroy($image);
+ }
+
+ $url_components = parse_url($resource['url']);
+ $filename = basename($url_components['path']);
+ if (!strlen($filename)) {
+ $filename = 'image';
+ }
+ $r = q("INSERT INTO `photo`
+ ( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, `type`, `album`, `height`, `width`, `datasize`, `data` )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s' )",
+ intval($item['item-uid']),
+ intval($item['contact-id']),
+ dbesc(get_guid()),
+ dbesc($hash),
+ dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
+ dbesc($filename),
+ dbesc($resource['type']),
+ dbesc('Retrieved Images'),
+ intval($resource['height']),
+ intval($resource['width']),
+ intval(strlen($resource['data'])),
+ dbesc($resource['data'])
+ );
+
+ return $hash;
+}
+
+function retriever_transform_images(&$item, $resource) {
+ require_once('include/Photo.php');
+
+ if (!$resource["data"]) {
+ logger('retriever_transform_images: no data available for '
+ . $resource['id'] . ' ' . $resource['url'], LOGGER_NORMAL);
+ return;
+ }
+
+ $hash = retriever_store_photo($item, $resource);
+ if ($hash === false) {
+ logger('retriever_transform_images: unable to store photo '
+ . $resource['id'] . ' ' . $resource['url'], LOGGER_NORMAL);
+ return;
+ }
+
+ $new_url = get_app()->get_baseurl() . '/photo/' . $hash;
+ logger('retriever_transform_images: replacing ' . $resource['url'] . ' with ' .
+ $new_url . ' in item ' . $item['plink'], LOGGER_DEBUG);
+ $transformed = str_replace($resource["url"], $new_url, $item['body']);
+ if ($transformed === $item['body']) {
+ return;
+ }
+
+ $item['body'] = $transformed;
+ q("UPDATE `item` SET `edited` = '%s', `body` = '%s' WHERE `plink` = '%s' AND `uid` = %d AND `contact-id` = %d",
+ dbesc(datetime_convert('UTC', 'UTC')),
+ dbesc($item['body']),
+ dbesc($item['plink']),
+ intval($item['uid']),
+ intval($item['contact-id']));
+}
+
+function retriever_content($a) {
+ if (!local_user()) {
+ $a->page['content'] .= "
Please log in
";
+ return;
+ }
+ if ($a->argv[1] === 'help') {
+ $feeds = q("SELECT `id`, `name`, `thumb` FROM contact WHERE `uid` = %d AND `network` = 'feed'",
+ local_user());
+ foreach ($feeds as $k=>$v) {
+ $feeds[$k]['url'] = $a->get_baseurl() . '/retriever/' . $v['id'];
+ }
+ $template = get_markup_template('/help.tpl', 'addon/retriever/');
+ $a->page['content'] .= replace_macros($template, array(
+ '$config' => $a->get_baseurl() . '/settings/addon',
+ '$feeds' => $feeds));
+ return;
+ }
+ if ($a->argv[1]) {
+ $retriever = get_retriever($a->argv[1], local_user(), false);
+
+ if (x($_POST["id"])) {
+ $retriever = get_retriever($a->argv[1], local_user(), true);
+ $retriever["data"] = array();
+ foreach (array('pattern', 'replace', 'enable', 'images') as $setting) {
+ if (x($_POST['retriever_' . $setting])) {
+ $retriever["data"][$setting] = $_POST['retriever_' . $setting];
+ }
+ }
+ foreach ($_POST as $k=>$v) {
+ if (preg_match("/retriever-(include|exclude)-(\d+)-(element|attribute|value)/", $k, $matches)) {
+ $retriever['data'][$matches[1]][intval($matches[2])][$matches[3]] = $v;
+ }
+ }
+ // You've gotta have an element, even if it's just "*"
+ foreach ($retriever['data']['include'] as $k=>$clause) {
+ if (!$clause['element']) {
+ unset($retriever['data']['include'][$k]);
+ }
+ }
+ foreach ($retriever['data']['exclude'] as $k=>$clause) {
+ if (!$clause['element']) {
+ unset($retriever['data']['exclude'][$k]);
+ }
+ }
+ q("UPDATE `retriever_rule` SET `data`='%s' WHERE `id` = %d",
+ dbesc(json_encode($retriever["data"])), intval($retriever["id"]));
+ $a->page['content'] .= "
Settings Updated";
+ if (x($_POST["retriever_retrospective"])) {
+ apply_retrospective($retriever, $_POST["retriever_retrospective"]);
+ $a->page['content'] .= " and retrospectively applied to " . $_POST["apply"] . " posts";
+ }
+ $a->page['content'] .= ".
";
+ }
+
+ $template = get_markup_template('/rule-config.tpl', 'addon/retriever/');
+ $a->page['content'] .= replace_macros($template, array(
+ '$enable' => array(
+ 'retriever_enable',
+ t('Enabled'),
+ $retriever['data']['enable']),
+ '$pattern' => array(
+ 'retriever_pattern',
+ t('URL Pattern'),
+ $retriever["data"]['pattern'],
+ t('Regular expression matching part of the URL to replace')),
+ '$replace' => array(
+ 'retriever_replace',
+ t('URL Replace'),
+ $retriever["data"]['replace'],
+ t('Text to replace matching part of above regular expression')),
+ '$images' => array(
+ 'retriever_images',
+ t('Download Images'),
+ $retriever['data']['images']),
+ '$retrospective' => array(
+ 'retriever_retrospective',
+ t('Retrospectively Apply'),
+ '0',
+ t('Reapply the rules to this number of posts')),
+ '$title' => t('Retrieve Feed Content'),
+ '$help' => $a->get_baseurl() . '/retriever/help',
+ '$submit' => t('Submit'),
+ '$id' => ($retriever["id"] ? $retriever["id"] : "create"),
+ '$tag_t' => t('Tag'),
+ '$attribute_t' => t('Attribute'),
+ '$value_t' => t('Value'),
+ '$add_t' => t('Add'),
+ '$remove_t' => t('Remove'),
+ '$include_t' => t('Include'),
+ '$include' => $retriever['data']['include'],
+ '$exclude_t' => t('Exclude'),
+ '$exclude' => $retriever["data"]['exclude']));
+ return;
+ }
+}
+
+function retriever_contact_photo_menu($a, &$args) {
+ if (!$args) {
+ return;
+ }
+ if ($args["contact"]["network"] == "feed") {
+ $args["menu"][ 'retriever' ] = array(t('Retriever'), $a->get_baseurl() . '/retriever/' . $args["contact"]['id']);
+ }
+}
+
+function retriever_post_remote_hook(&$a, &$item) {
+ logger('retriever_post_remote_hook: ' . $item['uri'] . ' ' . $item['uid'] . ' ' . $item['contact-id'], LOGGER_DEBUG);
+
+ $retriever = get_retriever($item['contact-id'], $item["uid"], false);
+ if ($retriever) {
+ retriever_on_item_insert($retriever, $item);
+ }
+ else {
+ if (get_pconfig($item["uid"], 'retriever', 'all_photos')) {
+ retrieve_images($item, null);
+ }
+ }
+ retriever_check_item_completed($item);
+}
+
+function retriever_plugin_settings(&$a,&$s) {
+ $all_photos = get_pconfig(local_user(), 'retriever', 'all_photos');
+ $all_photos_mu = ($all_photos == 'on') ? ' checked="true"' : '';
+ $template = get_markup_template('/settings.tpl', 'addon/retriever/');
+ $s .= replace_macros($template, array(
+ '$submit' => t('Submit'),
+ '$title' => t('Retriever Settings'),
+ '$help' => $a->get_baseurl() . '/retriever/help',
+ '$all_photos' => $all_photos_mu,
+ '$all_photos_t' => t('All Photos')));
+}
+
+function retriever_plugin_settings_post($a,$post) {
+ if ($_POST['all_photos']) {
+ set_pconfig(local_user(), 'retriever', 'all_photos', $_POST['all_photos']);
+ }
+ else {
+ del_pconfig(local_user(), 'retriever', 'all_photos');
+ }
+}
diff --git a/retriever/templates/extract.tpl b/retriever/templates/extract.tpl
new file mode 100644
index 00000000..36b91813
--- /dev/null
+++ b/retriever/templates/extract.tpl
@@ -0,0 +1,41 @@
+{{*
+ * AUTOMATICALLY GENERATED TEMPLATE
+ * DO NOT EDIT THIS FILE, CHANGES WILL BE OVERWRITTEN
+ *
+ *}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{{if $exclude}}
+
+{{/if}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/retriever/templates/help.tpl b/retriever/templates/help.tpl
new file mode 100644
index 00000000..23ae297b
--- /dev/null
+++ b/retriever/templates/help.tpl
@@ -0,0 +1,153 @@
+{{*
+ * AUTOMATICALLY GENERATED TEMPLATE
+ * DO NOT EDIT THIS FILE, CHANGES WILL BE OVERWRITTEN
+ *
+ *}}
+
Retriever Plugin Help
+
+This plugin replaces the short excerpts you normally get in RSS feeds
+with the full content of the article from the source website. You
+specify which part of the page you're interested in with a set of
+rules. When each item arrives, the plugin downloads the full page
+from the website, extracts content using the rules, and replaces the
+original article.
+
+
+There's a few reasons you may want to do this. The source website
+might be slow or overloaded. The source website might be
+untrustworthy, in which case using Friendica to scrub the HTML is a
+good idea. You might be on a LAN that blacklists certain websites.
+It also works neatly with the mailstream plugin, allowing you to read
+a news stream comfortably without needing continuous Internet
+connectivity.
+
+
+However, setting up retriever can be quite tricky since it depends on
+the internal design of the website. That was designed to make life
+easy for the website's developers, not for you. You'll need to have
+some familiarity with HTML, and be willing to adapt when the website
+suddenly changes everything without notice.
+
+
Configuring Retriever for a feed
+
+To set up retriever for an RSS feed, go to the "Contacts" page and
+find your feed. Then click on the drop-down menu on the contact.
+Select "Retriever" to get to the retriever configuration.
+
+
+The "Include" configuration section specifies parts of the page to
+include in the article. Each row has three components:
+
+
+An HTML tag (e.g. "div", "span", "p")
+An attribute (usually "class" or "id")
+A value for the attribute
+
+
+A simple case is when the article is wrapped in a "div" element:
+
+
+ ...
+ <div class="ArticleWrapper">
+ <h2>Man Bites Dog</h2>
+ <img src="mbd.jpg">
+ <p>
+ Residents of the sleepy community of Nowheresville were
+ shocked yesterday by the sight of creepy local weirdo Jim
+ McOddman assaulting innocent local dog Snufflekins with his
+ false teeth.
+ </p>
+ ...
+ </div>
+ ...
+
+
+You then specify the tag "div", attribute "class", and value
+"ArticleWrapper". Everything else in the page, such as navigation
+panels and menus and footers and so on, will be discarded. If there
+is more than one section of the page you want to include, specify each
+one on a separate row. If the matching section contains some sections
+you want to remove, specify those in the "Exclude" section in the same
+way.
+
+
+Once you've got a configuration that you think will work, you can try
+it out on some existing articles. Type a number into the
+"Retrospectively Apply" box and click "Submit". After a while
+(exactly how long depends on your system's cron configuration) the new
+articles should be available.
+
+
Techniques
+
+You can leave the attribute and value blank to include all the
+corresponding elements with the specified tag name. You can also use
+a tag name of just an asterisk ("*"), which will match any element type with the
+specified attribute regardless of the tag.
+
+
+Note that the "class" attribute is a special case. Many web page
+templates will put multiple different classes in the same element,
+separated by spaces. If you specify an attribute of "class" it will
+match an element if any of its classes matches the specified value.
+For example:
+
+
+ <div class="article breaking-news">
+
+
+In this case you can specify a value of "article", or "breaking-news".
+You can also specify "article breaking-news", but that won't match if
+the website suddenly changes to "breaking-news article", so that's not
+recommended.
+
+
+One useful trick you can try is using the website's "print" pages.
+Many news sites have print versions of all their articles. These are
+usually drastically simplified compared to the live website page.
+Sometimes this is a good way to get the whole article when it's
+normally split across multiple pages.
+
+
+Hopefully the URL for the print page is a predictable variant of the
+normal article URL. For example, an article URL like:
+
+
+ http://www.newssite.com/article-8636.html
+
+
+...might have a print version at:
+
+
+ http://www.newssite.com/print/article-8636.html
+
+
+To change the URL used to retrieve the page, use the "URL Pattern" and
+"URL Replace" fields. The pattern is a regular expression matching
+part of the URL to replace. In this case, you might use a pattern of
+"/article" and a replace string of "/print/article". A common pattern
+is simply a dollar sign ("$"), used to add the replace string to the end of the URL.
+
+
Background Processing
+
+Note that retrieving and processing the articles can take some time,
+so it's done in the background. Incoming articles will be marked as
+invisible while they're in the process of being downloaded. If a URL
+fails, the plugin will keep trying at progressively longer intervals
+for up to a month, in case the website is temporarily overloaded or
+the network is down.
+
+
Retrieving Images
+
+Retriever can also optionally download images and store them in the
+local Friendica instance. Just check the "Download Images" box. You
+can also download images in every item from your network, whether it's
+an RSS feed or not. Go to the "Settings" page and
+click "Plugin settings" . Then check the "All
+Photos" box in the "Retriever Settings" section and click "Submit".
+
+
Configure Feeds:
+
+{{ for $feeds as $feed }}
+{{ inc contact_template.tpl with $contact=$feed }}{{ endinc }}
+{{ endfor }}
+
diff --git a/retriever/templates/rule-config.tpl b/retriever/templates/rule-config.tpl
new file mode 100644
index 00000000..79add59a
--- /dev/null
+++ b/retriever/templates/rule-config.tpl
@@ -0,0 +1,116 @@
+{{*
+ * AUTOMATICALLY GENERATED TEMPLATE
+ * DO NOT EDIT THIS FILE, CHANGES WILL BE OVERWRITTEN
+ *
+ *}}
+
diff --git a/mailstream/view/smarty3/settings.tpl b/retriever/templates/settings.tpl
similarity index 50%
rename from mailstream/view/smarty3/settings.tpl
rename to retriever/templates/settings.tpl
index 79e7c2c8..3bc71559 100644
--- a/mailstream/view/smarty3/settings.tpl
+++ b/retriever/templates/settings.tpl
@@ -4,16 +4,15 @@
*
*}}
-
Mail Stream Settings
+
{{$title}}
+
+ Get Help
+
- {{$enabled_caption}}
-
-
-
- {{$address_caption}}
-
+ {{$all_photos_t}}:
+
diff --git a/showmore.tgz b/showmore.tgz
index 623c56d5..981749f9 100644
Binary files a/showmore.tgz and b/showmore.tgz differ
diff --git a/smiley_pack.tgz b/smiley_pack.tgz
index 2efe6332..e7ade9ed 100644
Binary files a/smiley_pack.tgz and b/smiley_pack.tgz differ
diff --git a/smilies_adult.tgz b/smilies_adult.tgz
index 95f12161..642583eb 100644
Binary files a/smilies_adult.tgz and b/smilies_adult.tgz differ
diff --git a/snautofollow.tgz b/snautofollow.tgz
index 0c12e6a7..97c52077 100644
Binary files a/snautofollow.tgz and b/snautofollow.tgz differ
diff --git a/sniper.tgz b/sniper.tgz
index fba75c15..229acb0c 100755
Binary files a/sniper.tgz and b/sniper.tgz differ
diff --git a/startpage.tgz b/startpage.tgz
index ab731799..22d3b60a 100644
Binary files a/startpage.tgz and b/startpage.tgz differ
diff --git a/statusnet.tgz b/statusnet.tgz
index 4b283e2a..0dc3e0c8 100755
Binary files a/statusnet.tgz and b/statusnet.tgz differ
diff --git a/statusnet/statusnet.php b/statusnet/statusnet.php
index 91f25f42..ca0b17da 100755
--- a/statusnet/statusnet.php
+++ b/statusnet/statusnet.php
@@ -4,6 +4,7 @@
* Description: Relay public postings to a connected StatusNet account
* Version: 1.0.5
* Author: Tobias Diekershoff
+ * Author: Michael Vogel
*/
/* StatusNet Plugin for Friendica
@@ -658,7 +659,7 @@ function statusnet_post_hook(&$a,&$b) {
// ok, all the links we want to send out are save, now strip
// away the remaining bbcode
//$msg = strip_tags(bbcode($tmp, false, false));
- $msg = bbcode($tmp, false, false);
+ $msg = bbcode($tmp, false, false, true);
$msg = str_replace(array(' ',' '),"\n",$msg);
$msg = strip_tags($msg);
diff --git a/statusnet/view/smarty3/admin.tpl b/statusnet/templates/admin.tpl
similarity index 100%
rename from statusnet/view/smarty3/admin.tpl
rename to statusnet/templates/admin.tpl
diff --git a/statusnet/view/admin.tpl b/statusnet/view/admin.tpl
deleted file mode 100644
index 686a4c79..00000000
--- a/statusnet/view/admin.tpl
+++ /dev/null
@@ -1,17 +0,0 @@
-{{ for $sites as $s }}
- {{ inc field_input.tpl with $field=$s.sitename }}{{ endinc }}
- {{ inc field_input.tpl with $field=$s.apiurl }}{{ endinc }}
- {{ inc field_input.tpl with $field=$s.secret }}{{ endinc }}
- {{ inc field_input.tpl with $field=$s.key }}{{ endinc }}
- {{ inc field_input.tpl with $field=$s.applicationname }}{{ endinc }}
- {{ if $s.delete }}
- {{ inc field_checkbox.tpl with $field=$s.delete }}{{ endinc }}
-
- {{ else }}
- Fill this form to add a new site
- {{ endif }}
-
-{{ endfor }}
-
-
-
diff --git a/superblock.tgz b/superblock.tgz
new file mode 100644
index 00000000..ba5849fc
Binary files /dev/null and b/superblock.tgz differ
diff --git a/superblock/lang/C/messages.po b/superblock/lang/C/messages.po
new file mode 100644
index 00000000..8089438b
--- /dev/null
+++ b/superblock/lang/C/messages.po
@@ -0,0 +1,51 @@
+# ADDON blockem
+# Copyright (C)
+# This file is distributed under the same license as the Friendica blockem addon package.
+#
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-02-27 05:01-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: blockem.php:51
+msgid "\"Blockem\" Settings"
+msgstr ""
+
+#: blockem.php:53
+msgid "Comma separated profile URLS to block"
+msgstr ""
+
+#: blockem.php:57
+msgid "Submit"
+msgstr ""
+
+#: blockem.php:70
+msgid "BLOCKEM Settings saved."
+msgstr ""
+
+#: blockem.php:105
+#, php-format
+msgid "Blocked %s - Click to open/close"
+msgstr ""
+
+#: blockem.php:160
+msgid "Unblock Author"
+msgstr ""
+
+#: blockem.php:162
+msgid "Block Author"
+msgstr ""
+
+#: blockem.php:194
+msgid "blockem settings updated"
+msgstr ""
diff --git a/superblock/lang/ca/strings.php b/superblock/lang/ca/strings.php
new file mode 100644
index 00000000..5587acd2
--- /dev/null
+++ b/superblock/lang/ca/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "Configuració de \"Bloqueig\"";
+$a->strings["Comma separated profile URLS to block"] = "URLS dels perfils a bloquejar, separats per comes";
+$a->strings["Submit"] = "Enviar";
+$a->strings["BLOCKEM Settings saved."] = "Guardada la configuració de BLOQUEIG.";
+$a->strings["Blocked %s - Click to open/close"] = "Bloquejar %s - Clica per obrir/tancar";
+$a->strings["Unblock Author"] = "Desbloquejar Autor";
+$a->strings["Block Author"] = "Bloquejar Autor";
+$a->strings["blockem settings updated"] = "Actualitzar la Configuració de bloqueig";
diff --git a/superblock/lang/cs/strings.php b/superblock/lang/cs/strings.php
new file mode 100644
index 00000000..174abc63
--- /dev/null
+++ b/superblock/lang/cs/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "\"Blockem\" Nastavení";
+$a->strings["Comma separated profile URLS to block"] = "Čárkou oddělené URL adresy profilů určených k ignorování";
+$a->strings["Submit"] = "Odeslat";
+$a->strings["BLOCKEM Settings saved."] = "BLOCKEM nastavení uloženo.";
+$a->strings["Blocked %s - Click to open/close"] = "Blokován %s - Klikněte pro otevření/zavření";
+$a->strings["Unblock Author"] = "Odblokovat autora";
+$a->strings["Block Author"] = "Zablokovat autora";
+$a->strings["blockem settings updated"] = "blockem nastavení aktualizováno";
diff --git a/superblock/lang/de/strings.php b/superblock/lang/de/strings.php
new file mode 100644
index 00000000..132b68a2
--- /dev/null
+++ b/superblock/lang/de/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "\"Blockem\"-Einstellungen";
+$a->strings["Comma separated profile URLS to block"] = "Profil-URLs, die blockiert werden sollen (durch Kommas getrennt)";
+$a->strings["Submit"] = "Senden";
+$a->strings["BLOCKEM Settings saved."] = "BLOCKEM-Einstellungen gesichert.";
+$a->strings["Blocked %s - Click to open/close"] = "%s blockiert - Zum Öffnen/Schließen klicken";
+$a->strings["Unblock Author"] = "Autor freischalten";
+$a->strings["Block Author"] = "Autor blockieren";
+$a->strings["blockem settings updated"] = "blockem Einstellungen aktualisiert";
diff --git a/superblock/lang/eo/strings.php b/superblock/lang/eo/strings.php
new file mode 100644
index 00000000..b6116507
--- /dev/null
+++ b/superblock/lang/eo/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "\"Blockem\" Agordoj";
+$a->strings["Comma separated profile URLS to block"] = "Blokotaj URL adresoj, disigita per komo";
+$a->strings["Submit"] = "Sendi";
+$a->strings["BLOCKEM Settings saved."] = "Konservis Agordojn de BLOCKEM.";
+$a->strings["Blocked %s - Click to open/close"] = "%s blokita - Klaku por malfermi/fermi";
+$a->strings["Unblock Author"] = "Malbloki Aŭtoron";
+$a->strings["Block Author"] = "Bloki Aŭtoron";
+$a->strings["blockem settings updated"] = "Ĝisdatigis la blockem agordojn";
diff --git a/superblock/lang/es/strings.php b/superblock/lang/es/strings.php
new file mode 100644
index 00000000..874d6d7f
--- /dev/null
+++ b/superblock/lang/es/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "Configuración de \"Blockem\"";
+$a->strings["Comma separated profile URLS to block"] = "Direcciones separadas por coma de los perfiles a bloquear";
+$a->strings["Submit"] = "Envíar";
+$a->strings["BLOCKEM Settings saved."] = "Configuracion Blockem guardada.";
+$a->strings["Blocked %s - Click to open/close"] = "%s bloqueado. Pulsa aquí para mostrar/ocultar";
+$a->strings["Unblock Author"] = "Desbloquear Autor";
+$a->strings["Block Author"] = "Bloquear Autor";
+$a->strings["blockem settings updated"] = "Configuración de Blockem actualizada";
diff --git a/superblock/lang/fr/strings.php b/superblock/lang/fr/strings.php
new file mode 100644
index 00000000..b9f31180
--- /dev/null
+++ b/superblock/lang/fr/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "Réglages de Blockem";
+$a->strings["Comma separated profile URLS to block"] = "Liste d'URLS de profils à bloquer, séparés par des virgules";
+$a->strings["Submit"] = "Envoyer";
+$a->strings["BLOCKEM Settings saved."] = "Réglages Blockem sauvés.";
+$a->strings["Blocked %s - Click to open/close"] = "Bloqué %s - Cliquez pour ouvrir/fermer";
+$a->strings["Unblock Author"] = "Débloquer l'auteur";
+$a->strings["Block Author"] = "Bloquer l'auteur";
+$a->strings["blockem settings updated"] = "Réglages blockem sauvés";
diff --git a/superblock/lang/is/strings.php b/superblock/lang/is/strings.php
new file mode 100644
index 00000000..3075c457
--- /dev/null
+++ b/superblock/lang/is/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "\"Blockem\" stillingar";
+$a->strings["Comma separated profile URLS to block"] = "Banna lista af forsíðum (komma á milli)";
+$a->strings["Submit"] = "Senda inn";
+$a->strings["BLOCKEM Settings saved."] = "BLOCKEM stillingar vistaðar.";
+$a->strings["Blocked %s - Click to open/close"] = "%s sett í straff - Smella til að taka úr/setja á";
+$a->strings["Unblock Author"] = "Leyfa notanda";
+$a->strings["Block Author"] = "Banna notanda";
+$a->strings["blockem settings updated"] = "";
diff --git a/superblock/lang/it/strings.php b/superblock/lang/it/strings.php
new file mode 100644
index 00000000..bcee9d0a
--- /dev/null
+++ b/superblock/lang/it/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "Impostazioni \"Blockem\"";
+$a->strings["Comma separated profile URLS to block"] = "Lista, separata da virgola, di indirizzi da bloccare";
+$a->strings["Submit"] = "Invia";
+$a->strings["BLOCKEM Settings saved."] = "Impostazioni salvate.";
+$a->strings["Blocked %s - Click to open/close"] = "%s bloccato - Clicca per aprire/chiudere";
+$a->strings["Unblock Author"] = "Sblocca autore";
+$a->strings["Block Author"] = "Blocca autore";
+$a->strings["blockem settings updated"] = "Impostazioni 'blockem' aggiornate.";
diff --git a/superblock/lang/nb-no/strings.php b/superblock/lang/nb-no/strings.php
new file mode 100644
index 00000000..0dd6660d
--- /dev/null
+++ b/superblock/lang/nb-no/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "";
+$a->strings["Comma separated profile URLS to block"] = "";
+$a->strings["Submit"] = "Lagre";
+$a->strings["BLOCKEM Settings saved."] = "";
+$a->strings["Blocked %s - Click to open/close"] = "";
+$a->strings["Unblock Author"] = "";
+$a->strings["Block Author"] = "";
+$a->strings["blockem settings updated"] = "";
diff --git a/superblock/lang/pl/strings.php b/superblock/lang/pl/strings.php
new file mode 100644
index 00000000..6d7bcf19
--- /dev/null
+++ b/superblock/lang/pl/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "";
+$a->strings["Comma separated profile URLS to block"] = "";
+$a->strings["Submit"] = "Potwierdź";
+$a->strings["BLOCKEM Settings saved."] = "";
+$a->strings["Blocked %s - Click to open/close"] = "";
+$a->strings["Unblock Author"] = "Odblokuj autora";
+$a->strings["Block Author"] = "Zablokuj autora";
+$a->strings["blockem settings updated"] = "";
diff --git a/superblock/lang/pt-br/strings.php b/superblock/lang/pt-br/strings.php
new file mode 100644
index 00000000..49f69cc3
--- /dev/null
+++ b/superblock/lang/pt-br/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "Configurações \"Blockem\"";
+$a->strings["Comma separated profile URLS to block"] = "URLS de perfis separados por vírgulas a serem bloqueados";
+$a->strings["Submit"] = "Enviar";
+$a->strings["BLOCKEM Settings saved."] = "Configurações BLOCKEM armazenadas.";
+$a->strings["Blocked %s - Click to open/close"] = "Bloqueado %s - Clique para abrir/fechar";
+$a->strings["Unblock Author"] = "Desbloqueie Autor";
+$a->strings["Block Author"] = "Bloqueie Autor";
+$a->strings["blockem settings updated"] = "configurações blockem atualizadas";
diff --git a/superblock/lang/ru/strings.php b/superblock/lang/ru/strings.php
new file mode 100644
index 00000000..7617b865
--- /dev/null
+++ b/superblock/lang/ru/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "\"Blockem\" настройки";
+$a->strings["Comma separated profile URLS to block"] = "URLS, которые заблокировать (список через запятую)";
+$a->strings["Submit"] = "Подтвердить";
+$a->strings["BLOCKEM Settings saved."] = "BLOCKEM-Настройки сохранены.";
+$a->strings["Blocked %s - Click to open/close"] = "Заблокированные %s - Нажмите, чтобы открыть/закрыть";
+$a->strings["Unblock Author"] = "";
+$a->strings["Block Author"] = "Блокировать Автора";
+$a->strings["blockem settings updated"] = "\"Blockem\" настройки обновлены";
diff --git a/superblock/lang/sv/strings.php b/superblock/lang/sv/strings.php
new file mode 100644
index 00000000..3ec569a7
--- /dev/null
+++ b/superblock/lang/sv/strings.php
@@ -0,0 +1,3 @@
+strings["Submit"] = "Spara";
diff --git a/superblock/lang/zh-cn/strings.php b/superblock/lang/zh-cn/strings.php
new file mode 100644
index 00000000..3a3dfaeb
--- /dev/null
+++ b/superblock/lang/zh-cn/strings.php
@@ -0,0 +1,10 @@
+strings["\"Blockem\" Settings"] = "「Blockem」配置";
+$a->strings["Comma separated profile URLS to block"] = "逗号分简介URL为栏";
+$a->strings["Submit"] = "提交";
+$a->strings["BLOCKEM Settings saved."] = "「Blockem」配置保存了。";
+$a->strings["Blocked %s - Click to open/close"] = "%s拦了-点击为开关";
+$a->strings["Unblock Author"] = "不拦作家";
+$a->strings["Block Author"] = "拦作家";
+$a->strings["blockem settings updated"] = "blockem设置更新了";
diff --git a/superblock/superblock.css b/superblock/superblock.css
new file mode 100755
index 00000000..368355bd
--- /dev/null
+++ b/superblock/superblock.css
@@ -0,0 +1,18 @@
+
+#superblock-label {
+ float: left;
+ width: 300px;
+ margin-top: 10px;
+}
+
+#superblock-words {
+ float: left;
+ margin-top: 10px;
+ width: 400px;
+ height: 150px;
+}
+
+#superblock-submit {
+ margin-top: 15px;
+}
+
diff --git a/superblock/superblock.php b/superblock/superblock.php
new file mode 100755
index 00000000..7363c139
--- /dev/null
+++ b/superblock/superblock.php
@@ -0,0 +1,165 @@
+
+ *
+ */
+
+function superblock_install() {
+
+ register_hook('plugin_settings', 'addon/superblock/superblock.php', 'superblock_addon_settings');
+ register_hook('plugin_settings_post', 'addon/superblock/superblock.php', 'superblock_addon_settings_post');
+ register_hook('conversation_start', 'addon/superblock/superblock.php', 'superblock_conversation_start');
+ register_hook('item_photo_menu', 'addon/superblock/superblock.php', 'superblock_item_photo_menu');
+ register_hook('enotify_store', 'addon/superblock/superblock.php', 'superblock_enotify_store');
+
+}
+
+
+function superblock_uninstall() {
+
+ unregister_hook('plugin_settings', 'addon/superblock/superblock.php', 'superblock_addon_settings');
+ unregister_hook('plugin_settings_post', 'addon/superblock/superblock.php', 'superblock_addon_settings_post');
+ unregister_hook('conversation_start', 'addon/superblock/superblock.php', 'superblock_conversation_start');
+ unregister_hook('item_photo_menu', 'addon/superblock/superblock.php', 'superblock_item_photo_menu');
+ unregister_hook('enotify_store', 'addon/superblock/superblock.php', 'superblock_enotify_store');
+
+}
+
+
+
+
+
+function superblock_addon_settings(&$a,&$s) {
+
+ if(! local_user())
+ return;
+
+ /* Add our stylesheet to the page so we can make our settings look nice */
+
+ $a->page['htmlhead'] .= ' ' . "\r\n";
+
+
+ $words = get_pconfig(local_user(),'system','blocked');
+ if(! $words)
+ $words = '';
+
+ $s .= '';
+ $s .= '
' . t('"Superblock" Settings') . ' ';
+ $s .= '
';
+ $s .= '' . t('Comma separated profile URLS to block') . ' ';
+ $s .= '';
+ $s .= '
';
+
+ $s .= '
';
+
+ return;
+
+}
+
+function superblock_addon_settings_post(&$a,&$b) {
+
+ if(! local_user())
+ return;
+
+ if($_POST['superblock-submit']) {
+ set_pconfig(local_user(),'system','blocked',trim($_POST['superblock-words']));
+ info( t('SUPERBLOCK Settings saved.') . EOL);
+ }
+}
+
+function superblock_enotify_store(&$a,&$b) {
+
+ $words = get_pconfig($b['uid'],'system','blocked');
+ if($words) {
+ $arr = explode(',',$words);
+ }
+ else {
+ return;
+ }
+
+ $found = false;
+ if(count($arr)) {
+ foreach($arr as $word) {
+ if(! strlen(trim($word))) {
+ continue;
+ }
+
+ if(link_compare($b['url'],$word)) {
+ $found = true;
+ break;
+ }
+ }
+ }
+ if($found) {
+ $b['abort'] = true;
+ }
+}
+
+
+function superblock_conversation_start(&$a,&$b) {
+
+ if(! local_user())
+ return;
+
+ $words = get_pconfig(local_user(),'system','blocked');
+ if($words) {
+ $a->data['superblock'] = explode(',',$words);
+ }
+ $a->page['htmlhead'] .= <<< EOT
+
+
+
+EOT;
+
+}
+
+function superblock_item_photo_menu(&$a,&$b) {
+
+ if((! local_user()) || ($b['item']['self']))
+ return;
+
+ $blocked = false;
+ $author = $b['item']['author-link'];
+ if(is_array($a->data['superblock'])) {
+ foreach($a->data['superblock'] as $bloke) {
+ if(link_compare($bloke,$author)) {
+ $blocked = true;
+ break;
+ }
+ }
+ }
+
+ $b['menu'][ t('Block Completely')] = 'javascript:superblockBlock(\'' . $author . '\'); return false;';
+}
+
+function superblock_module() {}
+
+
+function superblock_init(&$a) {
+
+ if(! local_user())
+ return;
+
+ $words = get_pconfig(local_user(),'system','blocked');
+
+ if(array_key_exists('block',$_GET) && $_GET['block']) {
+ if(strlen($words))
+ $words .= ',';
+ $words .= trim($_GET['block']);
+ }
+
+ set_pconfig(local_user(),'system','blocked',$words);
+ info( t('superblock settings updated') . EOL );
+ killme();
+}
diff --git a/testdrive.tgz b/testdrive.tgz
index aeba4548..33a5207c 100755
Binary files a/testdrive.tgz and b/testdrive.tgz differ
diff --git a/tictac.tgz b/tictac.tgz
index 7b70687e..bcc339e0 100755
Binary files a/tictac.tgz and b/tictac.tgz differ
diff --git a/tumblr.tgz b/tumblr.tgz
index 53d00cdc..463fad7b 100755
Binary files a/tumblr.tgz and b/tumblr.tgz differ
diff --git a/twitter.tgz b/twitter.tgz
index 0b244677..5e814714 100755
Binary files a/twitter.tgz and b/twitter.tgz differ
diff --git a/twitter/view/smarty3/admin.tpl b/twitter/templates/admin.tpl
similarity index 100%
rename from twitter/view/smarty3/admin.tpl
rename to twitter/templates/admin.tpl
diff --git a/twitter/twitter.php b/twitter/twitter.php
index 8941508e..21dbc0ba 100755
--- a/twitter/twitter.php
+++ b/twitter/twitter.php
@@ -4,6 +4,7 @@
* Description: Relay public postings to a connected Twitter account
* Version: 1.0.4
* Author: Tobias Diekershoff
+ * Author: Michael Vogel
*/
@@ -285,7 +286,7 @@ function twitter_shortenmsg($b) {
require_once("include/bbcode.php");
require_once("include/html2plain.php");
- $max_char = 140;
+ $max_char = 130;
// Looking for the first image
$image = '';
@@ -511,7 +512,7 @@ function twitter_post_hook(&$a,&$b) {
// ok, all the links we want to send out are save, now strip
// away the remaining bbcode
//$msg = strip_tags(bbcode($tmp, false, false));
- $msg = bbcode($tmp, false, false);
+ $msg = bbcode($tmp, false, false, true);
$msg = str_replace(array(' ',' '),"\n",$msg);
$msg = strip_tags($msg);
diff --git a/twitter/view/admin.tpl b/twitter/view/admin.tpl
deleted file mode 100644
index b89f51b6..00000000
--- a/twitter/view/admin.tpl
+++ /dev/null
@@ -1,4 +0,0 @@
-{{ inc field_input.tpl with $field=$consumerkey }}{{ endinc }}
-{{ inc field_input.tpl with $field=$consumersecret }}{{ endinc }}
-{{ inc field_input.tpl with $field=$applicationname }}{{ endinc }}
-
diff --git a/uhremotestorage.tgz b/uhremotestorage.tgz
index 5bd47eb8..a12bc167 100755
Binary files a/uhremotestorage.tgz and b/uhremotestorage.tgz differ
diff --git a/uhremotestorage/view/smarty3/settings.tpl b/uhremotestorage/templates/settings.tpl
similarity index 100%
rename from uhremotestorage/view/smarty3/settings.tpl
rename to uhremotestorage/templates/settings.tpl
diff --git a/uhremotestorage/view/settings.tpl b/uhremotestorage/view/settings.tpl
deleted file mode 100644
index 22d7d608..00000000
--- a/uhremotestorage/view/settings.tpl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
$title
-
$desc
- {{ inc field_input.tpl with $field=$url }}{{ endinc }}
- {{ inc field_input.tpl with $field=$auth }}{{ endinc }}
- {{ inc field_select.tpl with $field=$api }}{{ endinc }}
-
-
-
diff --git a/viewsrc.tgz b/viewsrc.tgz
index 1d9fb2be..d24eccd2 100644
Binary files a/viewsrc.tgz and b/viewsrc.tgz differ
diff --git a/webrtc.tgz b/webrtc.tgz
new file mode 100644
index 00000000..01a67823
Binary files /dev/null and b/webrtc.tgz differ
diff --git a/webrtc/README b/webrtc/README
new file mode 100644
index 00000000..75797f18
--- /dev/null
+++ b/webrtc/README
@@ -0,0 +1,22 @@
+Webrtc Plugin
+====================
+
+This is a quick and dirty addon to add a webrtc website as an app. As webrtc
+advances so rapidly there is s a chance this plugin will be obsolete. Webrtc is
+a new video and audio conferencing tool that is browser to browser
+communication, no need to download specific software for just conferencing.
+There are many different webrtc instances and because of the technology it is
+really a person 2 person communication, using the server to only signal who
+wants to talk to who, the actual transfer of the audio and video is directly
+between the participants.
+
+If you would like to try this plugin please download one of the following
+either Chrome/Chromium 25 or higher or Firefox 21 or higher. Then test it by
+visiting a known webrtc instance (i.e. https://live.mayfirst.org) create a
+room, you should be asked to share your camera and microphone (firefox will let
+you choose one or the other, whereas chrome/chromium asks for both in one
+question).
+
+If the test is successful then proceed with copying the webrtc instance you
+would like to use and place it in the config window and save. Now when you
+opent he app it will load the webrtc instance for you to use.
diff --git a/webrtc/templates/admin.tpl b/webrtc/templates/admin.tpl
new file mode 100644
index 00000000..d56de10b
--- /dev/null
+++ b/webrtc/templates/admin.tpl
@@ -0,0 +1,2 @@
+{{include file="field_input.tpl" field=$webrtcurl}}
+
diff --git a/webrtc/webrtc.php b/webrtc/webrtc.php
new file mode 100644
index 00000000..7a4e8cf7
--- /dev/null
+++ b/webrtc/webrtc.php
@@ -0,0 +1,58 @@
+
+ * Author: Tobias Diekershoff
+ */
+
+function webrtc_install() {
+ register_hook('app_menu', 'addon/webrtc/webrtc.php', 'webrtc_app_menu');
+}
+
+function webrtc_uninstall() {
+ unregister_hook('app_menu', 'addon/webrtc/webrtc.php', 'webrtc_app_menu');
+
+}
+
+function webrtc_app_menu($a,&$b) {
+ $b['app_menu'][] = '';
+}
+
+function webrtc_plugin_admin (&$a, &$o) {
+ $t = get_markup_template( "admin.tpl", "addon/webrtc/" );
+ $o = replace_macros( $t, array(
+ '$submit' => t('Submit'),
+ '$webrtcurl' => array('webrtcurl', t('WebRTC Base URL'), get_config('webrtc','webrtcurl' ), t('Page your users will create a WebRTC chat room on. For example you could use https://live.mayfirst.org .')),
+ ));
+}
+function webrtc_plugin_admin_post (&$a) {
+ $url = ((x($_POST, 'webrtcurl')) ? notags(trim($_POST['webrtcurl'])) : '');
+ set_config('webrtc', 'webrtcurl', $url);
+ info( t('Settings updated.'). EOL);
+}
+
+function webrtc_module() {
+ return;
+}
+
+function webrtc_content(&$a) {
+ $o = '';
+
+ /* landingpage to create chatrooms */
+ $webrtcurl = get_config('webrtc','webrtcurl');
+
+ /* embedd the landing page in an iframe */
+ $o .= ''.t('Video Chat').' ';
+ $o .= ''.t('WebRTC is a video and audio conferencing tool that works with Firefox (version 21 and above) and Chrome/Chromium (version 25 and above). Just create a new chat room and send the link to someone you want to chat with.').'
';
+ if ($webrtcurl == '') {
+ $o .= ''.t('Please contact your friendica admin and send a reminder to configure the WebRTC addon.').'
';
+ } else {
+ $o .= '';
+ }
+
+
+ return $o;
+}
+?>
diff --git a/widgets.tgz b/widgets.tgz
index 88968541..6dcf96ac 100755
Binary files a/widgets.tgz and b/widgets.tgz differ
diff --git a/widgets/view/smarty3/settings.tpl b/widgets/templates/settings.tpl
similarity index 100%
rename from widgets/view/smarty3/settings.tpl
rename to widgets/templates/settings.tpl
diff --git a/widgets/view/smarty3/widget_like.tpl b/widgets/templates/widget_like.tpl
similarity index 100%
rename from widgets/view/smarty3/widget_like.tpl
rename to widgets/templates/widget_like.tpl
diff --git a/widgets/view/settings.tpl b/widgets/view/settings.tpl
deleted file mode 100755
index 9d0f21d2..00000000
--- a/widgets/view/settings.tpl
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
$title
-
- $label
- $key
-
-
-
-
-
-
-
$widgets_h
-
- {{ for $widgets as $w }}
- $w.1
- {{ endfor }}
-
-
-
diff --git a/widgets/view/widget_like.tpl b/widgets/view/widget_like.tpl
deleted file mode 100755
index 3c26d1da..00000000
--- a/widgets/view/widget_like.tpl
+++ /dev/null
@@ -1,3 +0,0 @@
-
-$like
-$dislike
diff --git a/wppost.tgz b/wppost.tgz
index 69f22c66..404ea134 100755
Binary files a/wppost.tgz and b/wppost.tgz differ
diff --git a/yourls.tgz b/yourls.tgz
index f0f04aae..036522b4 100755
Binary files a/yourls.tgz and b/yourls.tgz differ