]> git.mxchange.org Git - friendica.git/commitdiff
Merge pull request #2979 from annando/issue-2772
authorTobias Diekershoff <tobias.diekershoff@gmx.net>
Thu, 1 Dec 2016 07:51:04 +0000 (08:51 +0100)
committerGitHub <noreply@github.com>
Thu, 1 Dec 2016 07:51:04 +0000 (08:51 +0100)
Issue 2772: Pending contacts should now be displayed

56 files changed:
boot.php
doc/Home.md
doc/Message-Flow.md
doc/Protocol.md [new file with mode: 0644]
doc/de/Home.md
doc/de/Message-Flow.md
doc/htconfig.md
include/Contact.php
include/ParseUrl.php [new file with mode: 0644]
include/conversation.php
include/dfrn.php
include/html2bbcode.php
include/items.php
include/oembed.php
include/plaintext.php
include/poller.php
include/remove_contact.php [new file with mode: 0644]
include/xml.php
index.php
js/main.js
mod/dfrn_confirm.php
mod/dfrn_notify.php
mod/dfrn_request.php
mod/parse_url.php
mod/ping.php
mod/worker.php [new file with mode: 0644]
spec/dfrn2.odt
spec/dfrn2.pdf
spec/dfrn2_contact_confirmation.png [new file with mode: 0644]
spec/dfrn2_contact_confirmation.svg [new file with mode: 0644]
spec/dfrn2_contact_request.png [new file with mode: 0644]
spec/dfrn2_contact_request.svg [new file with mode: 0644]
util/daemon.php [new file with mode: 0644]
view/templates/wall_thread.tpl
view/theme/duepuntozero/style.css
view/theme/frio/css/style.css
view/theme/frio/js/modal.js
view/theme/frio/templates/search_item.tpl
view/theme/frio/templates/wall_thread.tpl
view/theme/frost-mobile/style.css
view/theme/frost-mobile/templates/wall_thread.tpl
view/theme/frost/style.css
view/theme/frost/templates/wall_thread.tpl
view/theme/quattro/dark/style.css
view/theme/quattro/green/style.css
view/theme/quattro/lilac/style.css
view/theme/quattro/quattro.less
view/theme/quattro/templates/photo_item.tpl
view/theme/quattro/templates/search_item.tpl
view/theme/quattro/templates/wall_thread.tpl
view/theme/smoothly/style.css
view/theme/smoothly/templates/wall_thread.tpl
view/theme/vier/style.css
view/theme/vier/templates/photo_item.tpl
view/theme/vier/templates/search_item.tpl
view/theme/vier/templates/wall_thread.tpl

index b44c063f8a6ee0c4c1ff3c5d24b7e32375eaf0cb..866e7165c744021c7ede2541a930725a4cc22706 100644 (file)
--- a/boot.php
+++ b/boot.php
@@ -1385,6 +1385,10 @@ class App {
 
        function proc_run($args) {
 
+               if (!function_exists("proc_open")) {
+                       return;
+               }
+
                // Add the php path if it is a php call
                if (count($args) && ($args[0] === 'php' OR !is_string($args[0]))) {
 
index d0f95d0766b7a2f8ea1817bdca50a16e4b7c0153..437486e02858e18fd5354463da77b4963d9b4a04 100644 (file)
@@ -7,11 +7,11 @@ Friendica Documentation and Resources
        * [Account Basics](help/Account-Basics)
        * [New User Quick Start](help/Quick-Start-guide)
        * [Creating posts](help/Text_editor)
-        * [BBCode tag reference](help/BBCode)
+       * [BBCode tag reference](help/BBCode)
        * [Comment, sort and delete posts](help/Text_comment)
        * [Profiles](help/Profiles)
        * [Accesskey reference](help/Accesskeys)
-    * [Events](help/events)
+       * [Events](help/events)
 * You and other users
        * [Connectors](help/Connectors)
        * [Making Friends](help/Making-Friends)
@@ -31,9 +31,7 @@ Friendica Documentation and Resources
 * [Settings & Admin Panel](help/Settings)
 * [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
 * [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd)
-* [Message Flow](help/Message-Flow)
 * [Using SSL with Friendica](help/SSL)
-* [Twitter/GNU Social API Functions](help/api)
 * [Config values that can only be set in .htconfig.php](help/htconfig)
 
 **Developer Manual**
@@ -46,9 +44,11 @@ Friendica Documentation and Resources
 * [Plugin Development](help/Plugins)
 * [Theme Development](help/themes)
 * [Smarty 3 Templates](help/smarty3-templates)
+* [Protocol Documentation](help/Protocol)
 * [Database schema documantation](help/database)
 * [Class Autoloading](help/autoloader)
 * [Code - Reference(Doxygen generated - sets cookies)](doc/html/)
+* [Twitter/GNU Social API Functions](help/api)
 
 
 **External Resources**
index ce0a4248ab1408a831029c7bfbe281e040505930..9a6785d5992f1eea85023d0fce62011b309055e9 100644 (file)
@@ -4,7 +4,7 @@ Friendica Message Flow
 This page documents some of the details of how messages get from one person to another in the Friendica network.
 There are multiple paths, using multiple protocols and message formats.
 
-Those attempting to understand these message flows should become familiar with (at the minimum) the [DFRN protocol document](http://dfrn.org/dfrn.pdf) and the message passing elements of the OStatus stack (salmon and Pubsubhubbub).
+Those attempting to understand these message flows should become familiar with (at the minimum) the [DFRN protocol document](https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf) and the message passing elements of the OStatus stack (salmon and Pubsubhubbub).
 
 Most message passing involves the file include/items.php, which has functions for several feed-related import/export activities. 
 
@@ -21,8 +21,8 @@ Push (pubsubhubbub) feeds arrive via mod/pubsub.php
 
 DFRN-poll feed imports arrive via include/poller.php as a scheduled task, this implements the local side of the DFRN-poll protocol.  
 
-Scenario #1. Bob posts a public status message
----
+### Scenario #1. Bob posts a public status message
+
 This is a public message with no conversation members so no private transport is used.
 There are two paths it can take - as a bbcode path to DFRN clients, and converted to HTML with the server's PuSH (pubsubhubbub) hubs notified.
 When a PuSH hub is operational, dfrn-poll clients prefer to receive their information through the PuSH channel.
@@ -30,31 +30,31 @@ They will fall back on a daily poll in case the hub has delivery issues (this is
 If there is no specified hub or hubs, DFRN clients will poll at a configurable (per-contact) rate at up to 5-minute intervals.
 Feeds retrieved via dfrn-poll are bbcode and may also contain private conversations which the poller has permissions to see. 
 
-Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network.
----
+### Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network.
+
 Jack uses dfrn-notify to send a direct reply to Bob.
 Bob then creates a feed of the conversation and sends it to everybody involved in the conversation using dfrn-notify.
 PuSH hubs are notified that new content is available.
 The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks). 
 
-Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network.
----
+### Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network.
+
 Mary uses dfrn-notify to send a direct reply to Bob.
 Bob then creates a feed of the conversation and sends it to everybody involved in the conversation (excluding himself, the conversation is now sent to both Jack and Mary).
 Messages are sent using dfrn-notify.
 Push hubs are also notified that new content is available.
 The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks).  
 
-Scenario #4. William replies to Bob's public message. William is on the OStatus network.
----
+### Scenario #4. William replies to Bob's public message. William is on the OStatus network.
+
 William uses salmon to notify Bob of the reply.
 Content is html embedded in salmon magic envelope.
 Bob then creates a feed of the conversation and sends it to all Friendica participants involved in the conversation using dfrn-notify (excluding himself, the conversation is sent to both Jack and Mary).
 Push hubs are notified that new content is available.
 The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks).  
 
-Scenario #5. Bob posts a private message to Mary and Jack.
----
+### Scenario #5. Bob posts a private message to Mary and Jack.
+
 Message is delivered immediately to Mary and Jack using dfrn_notify.
 Public hubs are not notified.
 Requeueing is attempted in case of timeout.
diff --git a/doc/Protocol.md b/doc/Protocol.md
new file mode 100644 (file)
index 0000000..86ed027
--- /dev/null
@@ -0,0 +1,40 @@
+Used Protocols
+===============
+
+Friendicas DFRN Protocol
+---
+
+* [Document with the DFRN specification](spec/dfrn2.pdf)
+* [Schema of the contact request process](spec/dfrn2_contact_request.png)
+* [Schema of the contact request confirmation](spec/dfrn2_contact_confirmation.png)
+* [Description of the message flow](help/Message-Flow)
+
+ActivityStreams
+---
+
+Friendica is using ActivityStreams in version 1.0 for its activities and object types.
+Additional types are used for non standard activities.
+
+* [Link to the specification](http://activitystrea.ms/head/activity-schema.html)
+* [List of used ActivityStreams verbs and object types.](https://github.com/friendica/friendica/wiki/ActivityStreams)
+
+Salmon
+---
+
+Salmon is used as a message exchange protocol for replies and mentions.
+
+* [Link to the protocol summary](http://www.salmon-protocol.org/salmon-protocol-summary)
+
+Portable Contacts
+---
+
+Portable Contacts is used for friends lists.
+
+* [Link to the specification](https://web.archive.org/web/20160426223008/http://portablecontacts.net/draft-spec.html) (Link to archive.org)
+
+pubsubhubbub
+---
+
+pubsubhubbub is used for OStatus.
+
+* [Link to the specification](https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html)
index 68c026e5c79ff1fe204c3ee883b0da9b38ccf226..6023e3cdc47eccd0caf5f91791779f4ec79b0e80 100644 (file)
@@ -26,32 +26,31 @@ Friendica - Dokumentation und Ressourcen
        * [Bugs und Probleme](help/Bugs-and-Issues)
        * [Häufig gestellte Fragen (FAQ)](help/FAQ)
        
-**Technische Dokumentation**
+**Dokumentation für Administratoren**
 
 * [Installation](help/Install)
 * [Konfigurationen & Admin-Panel](help/Settings)
 * [Plugins](help/Plugins)
 * [Konnektoren (Connectors) installieren (Twitter/GNU Social)](help/Installing-Connectors)
 * [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN)
-* [Nachrichtenfluss](help/Message-Flow)
 * [Betreibe deine Seite mit einem SSL-Zertifikat](help/SSL)
-* [Entwickler](help/Developers)
-* [Twitter/GNU Social API Functions](help/api) (EN)
-* [Translation of Friendica](help/translations) (EN)
 * [Konfigurationswerte, die nur in der .htconfig.php gesetzt werden können](help/htconfig) (EN)
 
-**Entwickler Dokumentation**
+**Dokumentation für Entwickler**
 
-* [Where to get started?](help/Developers-Intro)
+* [Entwickler](help/Developers)
+* [Where to get started?](help/Developers-Intro) (EN)
 * [Help on Github](help/Github)
 * [Help on Vagrant](help/Vagrant)
-* [How to translate Friendica](help/translations)
+* [How to translate Friendica](help/translations) (EN)
 * [Bugs and Issues](help/Bugs-and-Issues)
 * [Plugin Development](help/Plugins)
 * [Theme Development](help/themes)
 * [Smarty 3 Templates](help/smarty3-templates)
+* [Protokoll Dokumentation](help/Protocol) (EN)
 * [Datenbank-Schema](help/database)
 * [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/)
+* [Twitter/GNU Social API Functions](help/api) (EN)
 
 **Externe Ressourcen**
 
index 0694db13444028e0d654d293c446e77b96c53ce2..3d4c912ccfd8a4847449c6b84a2082cfe7f2e21a 100644 (file)
@@ -6,7 +6,7 @@ Friendica Nachrichtenfluss
 Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden. 
 Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen. 
 
-Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll (http://dfrn.org/dfrn.pdf) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub).
+Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll ([Dokument mit den DFRN Spezifikationen](https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf)) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub).
 
 Der Großteil der Nachrichtenverarbeitung nutzt die Datei include/items.php, welche Funktionen für verschiedene Feed-bezogene Import-/Exportaktivitäten liefert.
 
@@ -24,7 +24,7 @@ PuSh-Feeds (pubsubhubbub) kommen via mod/pubsub.php an.
 DFRN-poll Feed-Imports kommen via include/poller.php als geplanter Task an, das implementiert die lokale Bearbeitung (local side) des DFRN-Protokolls. 
 
 
-Szenario #1. Bob schreibt eine öffentliche Statusnachricht
+### Szenario #1. Bob schreibt eine öffentliche Statusnachricht
 
 Dies ist eine öffentliche Nachricht ohne begrenzte Nutzerfreigabe, so dass keine private Übertragung notwendig ist. 
 Es gibt zwei Wege, die genutzt werden können - als bbcode an DFRN-Clients oder als durch den Server konvertierten HTML-Code (mit PuSH; pubsubhubbub). 
@@ -33,13 +33,13 @@ Sie fallen zurück auf eine tägliche Abfrage, wenn der Hub Übertragungsschwier
 Wenn kein spezifizierter Hub oder Hubs ausgewählt sind, werden DFRN-Clients in einer pro Kontakt konfigurierbaren Rate mit bis zu 5-Minuten-Intervallen abfragen. 
 Feeds, die via DFRN-Poll abgerufen werden, sind bbcode und können auch private Unterhaltungen enthalten, die vom Poller auf ihre Zugriffsrechte hin geprüft werden.
 
-Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk.
+### Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk.
 
 Jack nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. 
 Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist und dfrn-notify nutzt. 
 Die PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen diese an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können).
 
-Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk.
+### Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk.
 
 Mary nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken. 
 Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist (mit Ausnahme von Bob selbst; die Unterhaltung wird nun an Jack und Mary geschickt). 
@@ -47,14 +47,14 @@ Die Nachrichten werden mit dfrn-notify übertragen.
 PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. 
 Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können).
 
-Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk.
+### Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk.
 
 William nutzt salmon, um Bob über seine Antwort zu benachrichtigen. 
 Der Inhalt ist HTML-Code, der in das Salmon Magic Envelope eingebettet ist. 
 Bob erstellt dann einen Feed der Unterhaltung und sendet es an alle Friendica-Nutzer, die an der Unterhaltung beteiligt sind und dfrn-notify nutzen (mit Ausnahme von William selbst; die Unterhaltung wird an Jack und Mary weitergeleitet). 
 PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können).
 
-Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack.
+### Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack.
 
 Die Nachricht wird sofort an Mary und Jack mit Hilfe von dfrn_notify geschickt. 
 Öffentliche Hubs werden nicht benachrichtigt. 
index b6f98b2ef08f585d61c863b65be3968664393a2e..dbdbf1503349677dcdd48a9f7d7b6b08daf2f2eb 100644 (file)
@@ -29,6 +29,8 @@ Example: To set the directory value please add this line to your .htconfig.php:
 * disable_email_validation (Boolean) - Disables the check if a mail address is in a valid format and can be resolved via DNS.
 * disable_url_validation (Boolean) - Disables the DNS lookup of an URL.
 * event_input_format - Default value is "ymd".
+* frontend_worker (Boolean) - Activates the frontend worker which acts as a replacement for running the poller via the command line.
+* frontend_worker_timeout - Value in minutes after we think that a frontend task was killed by the webserver. Default value is 10.
 * ignore_cache (Boolean) - For development only. Disables the item cache.
 * like_no_comment (Boolean) - Don't update the "commented" value of an item when it is liked.
 * local_block (Boolean) - Used in conjunction with "block_public".
index 949feb3564e695057a2313eff75fbbaa01b7d602..d0f4023447f1448962d7f1ffd0bbabfcff3e97ab 100644 (file)
@@ -22,6 +22,7 @@ function user_remove($uid) {
                $r[0]['nickname']
        );
 
+       /// @todo Should be done in a background job since this likely will run into a time out
        // don't delete yet, will be done later when contacts have deleted my stuff
        // q("DELETE FROM `contact` WHERE `uid` = %d", intval($uid));
        q("DELETE FROM `gcign` WHERE `uid` = %d", intval($uid));
@@ -74,25 +75,10 @@ function contact_remove($id) {
                return;
        }
 
-       q("DELETE FROM `contact` WHERE `id` = %d",
-               intval($id)
-       );
-       q("DELETE FROM `item` WHERE `contact-id` = %d ",
-               intval($id)
-       );
-       q("DELETE FROM `photo` WHERE `contact-id` = %d ",
-               intval($id)
-       );
-       q("DELETE FROM `mail` WHERE `contact-id` = %d ",
-               intval($id)
-       );
-       q("DELETE FROM `event` WHERE `cid` = %d ",
-               intval($id)
-       );
-       q("DELETE FROM `queue` WHERE `cid` = %d ",
-               intval($id)
-       );
+       q("DELETE FROM `contact` WHERE `id` = %d", intval($id));
 
+       // Delete the rest in the background
+       proc_run(PRIORITY_LOW, 'include/remove_contact.php', $id);
 }
 
 
diff --git a/include/ParseUrl.php b/include/ParseUrl.php
new file mode 100644 (file)
index 0000000..549d705
--- /dev/null
@@ -0,0 +1,552 @@
+<?php
+
+/**
+ * @file include/ParseUrl.php
+ * @brief Get informations about a given URL
+ */
+
+namespace Friendica;
+
+use \Friendica\Core\Config;
+
+require_once("include/network.php");
+require_once("include/Photo.php");
+require_once("include/oembed.php");
+require_once("include/xml.php");
+
+/**
+ * @brief Class with methods for extracting certain content from an url
+ */
+class ParseUrl {
+
+       /**
+        * @brief Search for chached embeddable data of an url otherwise fetch it
+        * 
+        * @param type $url The url of the page which should be scraped
+        * @param type $no_guessing If true the parse doens't search for
+        *    preview pictures
+        * @param type $do_oembed The false option is used by the function fetch_oembed()
+        *    to avoid endless loops
+        * 
+        * @return array which contains needed data for embedding
+        *    string 'url' => The url of the parsed page
+        *    string 'type' => Content type
+        *    string 'title' => The title of the content
+        *    string 'text' => The description for the content
+        *    string 'image' => A preview image of the content (only available
+        *                if $no_geuessing = false
+        *    array'images' = Array of preview pictures
+        *    string 'keywords' => The tags which belong to the content
+        * 
+        * @see ParseUrl::getSiteinfo() for more information about scraping
+        * embeddable content 
+        */
+       public static function getSiteinfoCached($url, $no_guessing = false, $do_oembed = true) {
+
+               if ($url == "") {
+                       return false;
+               }
+
+               $r = q("SELECT * FROM `parsed_url` WHERE `url` = '%s' AND `guessing` = %d AND `oembed` = %d",
+                       dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed));
+
+               if ($r) {
+                       $data = $r[0]["content"];
+               }
+
+               if (!is_null($data)) {
+                       $data = unserialize($data);
+                       return $data;
+               }
+
+               $data = self::getSiteinfo($url, $no_guessing, $do_oembed);
+
+               q("INSERT INTO `parsed_url` (`url`, `guessing`, `oembed`, `content`, `created`) VALUES ('%s', %d, %d, '%s', '%s')
+                        ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'",
+                       dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed),
+                       dbesc(serialize($data)), dbesc(datetime_convert()),
+                       dbesc(serialize($data)), dbesc(datetime_convert()));
+
+               return $data;
+       }
+       /**
+        * @brief Parse a page for embeddable content information
+        * 
+        * This method parses to url for meta data which can be used to embed
+        * the content. If available it prioritizes Open Graph meta tags.
+        * If this is not available it uses the twitter cards meta tags.
+        * As fallback it uses standard html elements with meta informations
+        * like \<title\>Awesome Title\</title\> or
+        * \<meta name="description" content="An awesome description"\>
+        * 
+        * @param type $url The url of the page which should be scraped
+        * @param type $no_guessing If true the parse doens't search for
+        *    preview pictures
+        * @param type $do_oembed The false option is used by the function fetch_oembed()
+        *    to avoid endless loops
+        * @param type $count Internal counter to avoid endless loops
+        * 
+        * @return array which contains needed data for embedding
+        *    string 'url' => The url of the parsed page
+        *    string 'type' => Content type
+        *    string 'title' => The title of the content
+        *    string 'text' => The description for the content
+        *    string 'image' => A preview image of the content (only available
+        *                if $no_geuessing = false
+        *    array'images' = Array of preview pictures
+        *    string 'keywords' => The tags which belong to the content
+        * 
+        * @todo https://developers.google.com/+/plugins/snippet/
+        * @verbatim
+        * <meta itemprop="name" content="Awesome title">
+        * <meta itemprop="description" content="An awesome description">
+        * <meta itemprop="image" content="http://maple.libertreeproject.org/images/tree-icon.png">
+        * 
+        * <body itemscope itemtype="http://schema.org/Product">
+        *   <h1 itemprop="name">Shiny Trinket</h1>
+        *   <img itemprop="image" src="{image-url}" />
+        *   <p itemprop="description">Shiny trinkets are shiny.</p>
+        * </body>
+        * @endverbatim
+        */
+       public static function getSiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
+
+               $a = get_app();
+
+               $siteinfo = array();
+
+               // Check if the URL does contain a scheme
+               $scheme = parse_url($url, PHP_URL_SCHEME);
+
+               if ($scheme == "") {
+                       $url = "http://".trim($url, "/");
+               }
+
+               if ($count > 10) {
+                       logger("parseurl_getsiteinfo: Endless loop detected for ".$url, LOGGER_DEBUG);
+                       return($siteinfo);
+               }
+
+               $url = trim($url, "'");
+               $url = trim($url, '"');
+
+               $url = original_url($url);
+
+               $siteinfo["url"] = $url;
+               $siteinfo["type"] = "link";
+
+               $check_cert = Config::get("system", "verifyssl");
+
+               $stamp1 = microtime(true);
+
+               $ch = curl_init();
+               curl_setopt($ch, CURLOPT_URL, $url);
+               curl_setopt($ch, CURLOPT_HEADER, 1);
+               curl_setopt($ch, CURLOPT_NOBODY, 1);
+               curl_setopt($ch, CURLOPT_TIMEOUT, 3);
+               curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+               curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+               curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
+               curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
+
+               $header = curl_exec($ch);
+               $curl_info = @curl_getinfo($ch);
+               $http_code = $curl_info["http_code"];
+               curl_close($ch);
+
+               $a->save_timestamp($stamp1, "network");
+
+               if ((($curl_info["http_code"] == "301") || ($curl_info["http_code"] == "302") || ($curl_info["http_code"] == "303") || ($curl_info["http_code"] == "307"))
+                       && (($curl_info["redirect_url"] != "") || ($curl_info["location"] != ""))) {
+                       if ($curl_info["redirect_url"] != "") {
+                               $siteinfo = self::getSiteinfo($curl_info["redirect_url"], $no_guessing, $do_oembed, ++$count);
+                       } else {
+                               $siteinfo = self::getSiteinfo($curl_info["location"], $no_guessing, $do_oembed, ++$count);
+                       }
+                       return($siteinfo);
+               }
+
+               // If the file is too large then exit
+               if ($curl_info["download_content_length"] > 1000000) {
+                       return($siteinfo);
+               }
+
+               // If it isn't a HTML file then exit
+               if (($curl_info["content_type"] != "") && !strstr(strtolower($curl_info["content_type"]), "html")) {
+                       return($siteinfo);
+               }
+
+               if ($do_oembed) {
+
+                       $oembed_data = oembed_fetch_url($url);
+
+                       if (!in_array($oembed_data->type, array("error", "rich"))) {
+                               $siteinfo["type"] = $oembed_data->type;
+                       }
+
+                       if (($oembed_data->type == "link") && ($siteinfo["type"] != "photo")) {
+                               if (isset($oembed_data->title)) {
+                                       $siteinfo["title"] = $oembed_data->title;
+                               }
+                               if (isset($oembed_data->description)) {
+                                       $siteinfo["text"] = trim($oembed_data->description);
+                               }
+                               if (isset($oembed_data->thumbnail_url)) {
+                                       $siteinfo["image"] = $oembed_data->thumbnail_url;
+                               }
+                       }
+               }
+
+               $stamp1 = microtime(true);
+
+               // Now fetch the body as well
+               $ch = curl_init();
+               curl_setopt($ch, CURLOPT_URL, $url);
+               curl_setopt($ch, CURLOPT_HEADER, 1);
+               curl_setopt($ch, CURLOPT_NOBODY, 0);
+               curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+               curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+               curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
+               curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
+               curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
+
+               $header = curl_exec($ch);
+               $curl_info = @curl_getinfo($ch);
+               $http_code = $curl_info["http_code"];
+               curl_close($ch);
+
+               $a->save_timestamp($stamp1, "network");
+
+               // Fetch the first mentioned charset. Can be in body or header
+               $charset = "";
+               if (preg_match('/charset=(.*?)['."'".'"\s\n]/', $header, $matches)) {
+                       $charset = trim(trim(trim(array_pop($matches)), ';,'));
+               }
+
+               if ($charset == "") {
+                       $charset = "utf-8";
+               }
+
+               $pos = strpos($header, "\r\n\r\n");
+
+               if ($pos) {
+                       $body = trim(substr($header, $pos));
+               } else {
+                       $body = $header;
+               }
+
+               if (($charset != "") && (strtoupper($charset) != "UTF-8")) {
+                       logger("parseurl_getsiteinfo: detected charset ".$charset, LOGGER_DEBUG);
+                       //$body = mb_convert_encoding($body, "UTF-8", $charset);
+                       $body = iconv($charset, "UTF-8//TRANSLIT", $body);
+               }
+
+               $body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
+
+               $doc = new \DOMDocument();
+               @$doc->loadHTML($body);
+
+               \xml::deleteNode($doc, "style");
+               \xml::deleteNode($doc, "script");
+               \xml::deleteNode($doc, "option");
+               \xml::deleteNode($doc, "h1");
+               \xml::deleteNode($doc, "h2");
+               \xml::deleteNode($doc, "h3");
+               \xml::deleteNode($doc, "h4");
+               \xml::deleteNode($doc, "h5");
+               \xml::deleteNode($doc, "h6");
+               \xml::deleteNode($doc, "ol");
+               \xml::deleteNode($doc, "ul");
+
+               $xpath = new \DomXPath($doc);
+
+               $list = $xpath->query("//meta[@content]");
+               foreach ($list as $node) {
+                       $attr = array();
+                       if ($node->attributes->length) {
+                               foreach ($node->attributes as $attribute) {
+                                       $attr[$attribute->name] = $attribute->value;
+                               }
+                       }
+
+                       if (@$attr["http-equiv"] == "refresh") {
+                               $path = $attr["content"];
+                               $pathinfo = explode(";", $path);
+                               $content = "";
+                               foreach ($pathinfo as $value) {
+                                       if (substr(strtolower($value), 0, 4) == "url=") {
+                                               $content = substr($value, 4);
+                                       }
+                               }
+                               if ($content != "") {
+                                       $siteinfo = self::getSiteinfo($content, $no_guessing, $do_oembed, ++$count);
+                                       return($siteinfo);
+                               }
+                       }
+               }
+
+               $list = $xpath->query("//title");
+               if ($list->length > 0) {
+                       $siteinfo["title"] = $list->item(0)->nodeValue;
+               }
+
+               //$list = $xpath->query("head/meta[@name]");
+               $list = $xpath->query("//meta[@name]");
+               foreach ($list as $node) {
+                       $attr = array();
+                       if ($node->attributes->length) {
+                               foreach ($node->attributes as $attribute) {
+                                       $attr[$attribute->name] = $attribute->value;
+                               }
+                       }
+
+                       $attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
+
+                       if ($attr["content"] != "") {
+                               switch (strtolower($attr["name"])) {
+                                       case "fulltitle":
+                                               $siteinfo["title"] = $attr["content"];
+                                               break;
+                                       case "description":
+                                               $siteinfo["text"] = $attr["content"];
+                                               break;
+                                       case "thumbnail":
+                                               $siteinfo["image"] = $attr["content"];
+                                               break;
+                                       case "twitter:image":
+                                               $siteinfo["image"] = $attr["content"];
+                                               break;
+                                       case "twitter:image:src":
+                                               $siteinfo["image"] = $attr["content"];
+                                               break;
+                                       case "twitter:card":
+                                               if (($siteinfo["type"] == "") || ($attr["content"] == "photo")) {
+                                                       $siteinfo["type"] = $attr["content"];
+                                               }
+                                               break;
+                                       case "twitter:description":
+                                               $siteinfo["text"] = $attr["content"];
+                                               break;
+                                       case "twitter:title":
+                                               $siteinfo["title"] = $attr["content"];
+                                               break;
+                                       case "dc.title":
+                                               $siteinfo["title"] = $attr["content"];
+                                               break;
+                                       case "dc.description":
+                                               $siteinfo["text"] = $attr["content"];
+                                               break;
+                                       case "keywords":
+                                               $keywords = explode(",", $attr["content"]);
+                                               break;
+                                       case "news_keywords":
+                                               $keywords = explode(",", $attr["content"]);
+                                               break;
+                               }
+                       }
+                       if ($siteinfo["type"] == "summary") {
+                               $siteinfo["type"] = "link";
+                       }
+               }
+
+               if (isset($keywords)) {
+                       $siteinfo["keywords"] = array();
+                       foreach ($keywords as $keyword) {
+                               if (!in_array(trim($keyword), $siteinfo["keywords"])) {
+                                       $siteinfo["keywords"][] = trim($keyword);
+                               }
+                       }
+               }
+
+               //$list = $xpath->query("head/meta[@property]");
+               $list = $xpath->query("//meta[@property]");
+               foreach ($list as $node) {
+                       $attr = array();
+                       if ($node->attributes->length) {
+                               foreach ($node->attributes as $attribute) {
+                                       $attr[$attribute->name] = $attribute->value;
+                               }
+                       }
+
+                       $attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
+
+                       if ($attr["content"] != "") {
+                               switch (strtolower($attr["property"])) {
+                                       case "og:image":
+                                               $siteinfo["image"] = $attr["content"];
+                                               break;
+                                       case "og:title":
+                                               $siteinfo["title"] = $attr["content"];
+                                               break;
+                                       case "og:description":
+                                               $siteinfo["text"] = $attr["content"];
+                                               break;
+                               }
+                       }
+               }
+
+               if ((@$siteinfo["image"] == "") && !$no_guessing) {
+                       $list = $xpath->query("//img[@src]");
+                       foreach ($list as $node) {
+                               $attr = array();
+                               if ($node->attributes->length) {
+                                       foreach ($node->attributes as $attribute) {
+                                               $attr[$attribute->name] = $attribute->value;
+                                       }
+                               }
+
+                               $src = self::completeUrl($attr["src"], $url);
+                               $photodata = get_photo_info($src);
+
+                               if (($photodata) && ($photodata[0] > 150) && ($photodata[1] > 150)) {
+                                       if ($photodata[0] > 300) {
+                                               $photodata[1] = round($photodata[1] * (300 / $photodata[0]));
+                                               $photodata[0] = 300;
+                                       }
+                                       if ($photodata[1] > 300) {
+                                               $photodata[0] = round($photodata[0] * (300 / $photodata[1]));
+                                               $photodata[1] = 300;
+                                       }
+                                       $siteinfo["images"][] = array("src" => $src,
+                                                                       "width" => $photodata[0],
+                                                                       "height" => $photodata[1]);
+                               }
+
+                               }
+               } elseif ($siteinfo["image"] != "") {
+                       $src = self::completeUrl($siteinfo["image"], $url);
+
+                       unset($siteinfo["image"]);
+
+                       $photodata = get_photo_info($src);
+
+                       if (($photodata) && ($photodata[0] > 10) && ($photodata[1] > 10)) {
+                               $siteinfo["images"][] = array("src" => $src,
+                                                               "width" => $photodata[0],
+                                                               "height" => $photodata[1]);
+                       }
+               }
+
+               if ((@$siteinfo["text"] == "") && (@$siteinfo["title"] != "") && !$no_guessing) {
+                       $text = "";
+
+                       $list = $xpath->query("//div[@class='article']");
+                       foreach ($list as $node) {
+                               if (strlen($node->nodeValue) > 40) {
+                                       $text .= " ".trim($node->nodeValue);
+                               }
+                       }
+
+                       if ($text == "") {
+                               $list = $xpath->query("//div[@class='content']");
+                               foreach ($list as $node) {
+                                       if (strlen($node->nodeValue) > 40) {
+                                               $text .= " ".trim($node->nodeValue);
+                                       }
+                               }
+                       }
+
+                       // If none text was found then take the paragraph content
+                       if ($text == "") {
+                               $list = $xpath->query("//p");
+                               foreach ($list as $node) {
+                                       if (strlen($node->nodeValue) > 40) {
+                                               $text .= " ".trim($node->nodeValue);
+                                       }
+                               }
+                       }
+
+                       if ($text != "") {
+                               $text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
+
+                               while (strpos($text, "  ")) {
+                                       $text = trim(str_replace("  ", " ", $text));
+                               }
+
+                               $siteinfo["text"] = trim(html_entity_decode(substr($text, 0, 350), ENT_QUOTES, "UTF-8").'...');
+                       }
+               }
+
+               logger("parseurl_getsiteinfo: Siteinfo for ".$url." ".print_r($siteinfo, true), LOGGER_DEBUG);
+
+               call_hooks("getsiteinfo", $siteinfo);
+
+               return($siteinfo);
+       }
+
+       /**
+        * @brief Convert tags from CSV to an array
+        * 
+        * @param string $string Tags
+        * @return array with formatted Hashtags
+        */
+       public static function convertTagsToArray($string) {
+               $arr_tags = str_getcsv($string);
+               if (count($arr_tags)) {
+                       // add the # sign to every tag
+                       array_walk($arr_tags, array("self", "arrAddHashes"));
+
+                       return $arr_tags;
+               }
+       }
+
+       /**
+        * @brief Add a hasht sign to a string
+        * 
+        *  This method is used as callback function
+        * 
+        * @param string $tag The pure tag name
+        * @param int $k Counter for internal use
+        */
+       private static function arrAddHashes(&$tag, $k) {
+               $tag = "#" . $tag;
+       }
+
+       /**
+        * @brief Add a scheme to an url
+        * 
+        * The src attribute of some html elements (e.g. images)
+        * can miss the scheme so we need to add the correct
+        * scheme
+        * 
+        * @param string $url The url which possibly does have
+        *    a missing scheme (a link to an image)
+        * @param string $scheme The url with a correct scheme
+        *    (e.g. the url from the webpage which does contain the image)
+        * 
+        * @return string The url with a scheme
+        */
+       private static function completeUrl($url, $scheme) {
+               $urlarr = parse_url($url);
+
+               // If the url does allready have an scheme
+               // we can stop the process here
+               if (isset($urlarr["scheme"])) {
+                       return($url);
+               }
+
+               $schemearr = parse_url($scheme);
+
+               $complete = $schemearr["scheme"]."://".$schemearr["host"];
+
+               if (@$schemearr["port"] != "") {
+                       $complete .= ":".$schemearr["port"];
+               }
+
+               if (strpos($urlarr["path"],"/") !== 0) {
+                       $complete .= "/";
+               }
+
+               $complete .= $urlarr["path"];
+
+               if (@$urlarr["query"] != "") {
+                       $complete .= "?".$urlarr["query"];
+               }
+
+               if (@$urlarr["fragment"] != "") {
+                       $complete .= "#".$urlarr["fragment"];
+               }
+
+               return($complete);
+       }
+}
index f8facc5741afa028e753fdac92146ca1e878bb1a..63db42d93ad91439b552d7213dfdd1f5fe7b5ffe 100644 (file)
@@ -1064,6 +1064,9 @@ function builtin_activity_puller($item, &$conv_responses) {
                        else
                                $conv_responses[$mode][$item['thr-parent']] ++;
 
+                       if((local_user()) && (local_user() == $item['uid']) && ($item['self']))
+                               $conv_responses[$mode][$item['thr-parent'] . '-self'] = 1;
+
                        $conv_responses[$mode][$item['thr-parent'] . '-l'][] = $url;
 
                        // there can only be one activity verb per item so if we found anything, we can stop looking
@@ -1443,6 +1446,7 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) {
                $ret[$v] = array();
                $ret[$v]['count'] = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri']] : '');
                $ret[$v]['list']  = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri'] . '-l'] : '');
+               $ret[$v]['self']  = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri'] . '-self'] : '0');
                if(count($ret[$v]['list']) > MAX_LIKERS) {
                        $ret[$v]['list_part'] = array_slice($ret[$v]['list'], 0, MAX_LIKERS);
                        array_push($ret[$v]['list_part'], '<a href="#" data-toggle="modal" data-target="#' . $v . 'Modal-'
index 49af5b2acb8ea8ea201597c9ebefa50705f81210..272105128fe07a2ea4c9711a54cdf4d52deb6c67 100644 (file)
@@ -3,7 +3,8 @@
  * @file include/dfrn.php
  * @brief The implementation of the dfrn protocol
  *
- * https://github.com/friendica/friendica/wiki/Protocol
+ * @see https://github.com/friendica/friendica/wiki/Protocol and
+ * https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
  */
 
 require_once("include/Contact.php");
index 28e251aee4e82425a0fd0c88574558c43f701dd7..189ba91f19c847e673844367c10c9a02054da19b 100644 (file)
@@ -1,11 +1,14 @@
 <?php
-/*
-html2bbcode.php
-Converter for HTML to BBCode
-Made by: ike@piratenpartei.de
-Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
-                                       https://github.com/annando/Syncom
-*/
+/**
+ * @file include/html2bbcode.php
+ * @brief Converter for HTML to BBCode
+ * 
+ * Made by: ike@piratenpartei.de
+ * Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
+ *                                     https://github.com/annando/Syncom
+ */
+
+require_once("include/xml.php");
 
 function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
 {
@@ -76,15 +79,6 @@ function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
        return($replace);
 }
 
-if(!function_exists('deletenode')) {
-function deletenode(&$doc, $node)
-{
-       $xpath = new DomXPath($doc);
-       $list = $xpath->query("//".$node);
-       foreach ($list as $child)
-               $child->parentNode->removeChild($child);
-}}
-
 function _replace_code_cb($m){
        return "<code>".str_replace("\n","<br>\n",$m[1]). "</code>";
 }
@@ -117,12 +111,12 @@ function html2bbcode($message)
 
        @$doc->loadHTML($message);
 
-       deletenode($doc, 'style');
-       deletenode($doc, 'head');
-       deletenode($doc, 'title');
-       deletenode($doc, 'meta');
-       deletenode($doc, 'xml');
-       deletenode($doc, 'removeme');
+       xml::deleteNode($doc, 'style');
+       xml::deleteNode($doc, 'head');
+       xml::deleteNode($doc, 'title');
+       xml::deleteNode($doc, 'meta');
+       xml::deleteNode($doc, 'xml');
+       xml::deleteNode($doc, 'removeme');
 
        $xpath = new DomXPath($doc);
        $list = $xpath->query("//pre");
@@ -239,7 +233,7 @@ function html2bbcode($message)
        node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), '[iframe]$1', '[/iframe]');
 
        node2bbcode($doc, 'code', array(), '[code]', '[/code]');
-    node2bbcode($doc, 'key', array(), '[code]', '[/code]');
+       node2bbcode($doc, 'key', array(), '[code]', '[/code]');
 
        $message = $doc->saveHTML();
 
index 9b199aed3ba931956b2556ce89aca5ba77094c02..e9354b62d3eda2906753cb6641259640294ba856 100644 (file)
@@ -1,5 +1,11 @@
 <?php
 
+/**
+ * @file include/items.php
+ */
+
+use \Friendica\ParseUrl;
+
 require_once('include/bbcode.php');
 require_once('include/oembed.php');
 require_once('include/salmon.php');
@@ -216,9 +222,8 @@ function add_page_info_data($data) {
 }
 
 function query_page_info($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "") {
-       require_once("mod/parse_url.php");
 
-       $data = parseurl_getsiteinfo_cached($url, true);
+       $data = ParseUrl::getSiteinfoCached($url, true);
 
        if ($photo != "")
                $data["images"][0]["src"] = $photo;
index be6c298e8d5ff0f5f89ccc1e15afc2395ca3366c..a3d2deaca00fead83b14b1fec50605179b040e2f 100755 (executable)
@@ -1,8 +1,17 @@
 <?php
+
+/**
+ * @file include/oembed.php
+ */
+
+use \Friendica\ParseUrl;
+use \Friendica\Core\Config;
+
 function oembed_replacecb($matches){
        $embedurl=$matches[1];
        $j = oembed_fetch_url($embedurl);
        $s =  oembed_format_object($j);
+
        return $s;
 }
 
@@ -66,7 +75,7 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
                }
 
                if ($txt==false || $txt=="") {
-                       $embedly = get_config("system", "embedly");
+                       $embedly = Config::get("system", "embedly");
                        if ($embedly != "") {
                                // try embedly service
                                $ourl = "https://api.embed.ly/1/oembed?key=".$embedly."&url=".urlencode($embedurl);
@@ -110,8 +119,7 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
 
        // If fetching information doesn't work, then improve via internal functions
        if (($j->type == "error") OR ($no_rich_type AND ($j->type == "rich"))) {
-               require_once("mod/parse_url.php");
-               $data = parseurl_getsiteinfo_cached($embedurl, true, false);
+               $data = ParseUrl::getSiteinfoCached($embedurl, true, false);
                $j->type = $data["type"];
 
                if ($j->type == "photo") {
@@ -143,12 +151,11 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
 function oembed_format_object($j){
        require_once("mod/proxy.php");
 
-       $a = get_app();
        $embedurl = $j->embedurl;
        $jhtml = oembed_iframe($j->embedurl,(isset($j->width) ? $j->width : null), (isset($j->height) ? $j->height : null) );
        $ret="<span class='oembed ".$j->type."'>";
        switch ($j->type) {
-               case "video": {
+               case "video":
                        if (isset($j->thumbnail_url)) {
                                $tw = (isset($j->thumbnail_width) && intval($j->thumbnail_width)) ? $j->thumbnail_width:200;
                                $th = (isset($j->thumbnail_height) && intval($j->thumbnail_height)) ? $j->thumbnail_height:180;
@@ -158,7 +165,7 @@ function oembed_format_object($j){
                                $th=120; $tw = $th*$tr;
                                $tpl=get_markup_template('oembed_video.tpl');
                                $ret.=replace_macros($tpl, array(
-                               '$baseurl' => $a->get_baseurl(),
+                                       '$baseurl' => App::get_baseurl(),
                                        '$embedurl'=>$embedurl,
                                        '$escapedhtml'=>base64_encode($jhtml),
                                        '$tw'=>$tw,
@@ -170,43 +177,49 @@ function oembed_format_object($j){
                                $ret=$jhtml;
                        }
                        //$ret.="<br>";
-               }; break;
-               case "photo": {
+                       break;
+               case "photo":
                        $ret.= "<img width='".$j->width."' src='".proxy_url($j->url)."'>";
-               }; break;
-               case "link": {
-               }; break;
-               case "rich": {
+                       break;
+               case "link":
+                       break;
+               case "rich":
                        // not so safe..
-                       if (!get_config("system","no_oembed_rich_content"))
+                       if (!Config::get("system","no_oembed_rich_content")) {
                                $ret.= proxy_parse_html($jhtml);
-               }; break;
+                       }
+                       break;
        }
 
        // add link to source if not present in "rich" type
        if ($j->type!='rich' || !strpos($j->html,$embedurl) ){
                $ret .= "<h4>";
                if (isset($j->title)) {
-                       if (isset($j->provider_name))
+                       if (isset($j->provider_name)) {
                                $ret .= $j->provider_name.": ";
+                       }
 
                        $embedlink = (isset($j->title))?$j->title:$embedurl;
                        $ret .= "<a href='$embedurl' rel='oembed'>$embedlink</a>";
-                       if (isset($j->author_name))
+                       if (isset($j->author_name)) {
                                $ret.=" (".$j->author_name.")";
+                       }
                } elseif (isset($j->provider_name) OR isset($j->author_name)) {
                        $embedlink = "";
-                       if (isset($j->provider_name))
+                       if (isset($j->provider_name)) {
                                $embedlink .= $j->provider_name;
+                       }
 
                        if (isset($j->author_name)) {
-                               if ($embedlink != "")
+                               if ($embedlink != "") {
                                        $embedlink .= ": ";
+                               }
 
                                $embedlink .= $j->author_name;
                        }
-                       if (trim($embedlink) == "")
+                       if (trim($embedlink) == "") {
                                $embedlink = $embedurl;
+                       }
 
                        $ret .= "<a href='$embedurl' rel='oembed'>$embedlink</a>";
                }
@@ -247,15 +260,14 @@ function oembed_iframe($src, $width, $height) {
        }
        $width = '100%';
 
-       $a = get_app();
-       $s = $a->get_baseurl() . '/oembed/'.base64url_encode($src);
+       $s = App::get_baseurl() . '/oembed/'.base64url_encode($src);
        return '<iframe onload="resizeIframe(this);" class="embed_rich" height="' . $height . '" width="' . $width . '" src="' . $s . '" scrolling="no" frameborder="no">' . t('Embedded content') . '</iframe>';
 }
 
 
 
 function oembed_bbcode2html($text){
-       $stopoembed = get_config("system","no_oembed");
+       $stopoembed = Config::get("system","no_oembed");
        if ($stopoembed == true){
                return preg_replace("/\[embed\](.+?)\[\/embed\]/is", "<!-- oembed $1 --><i>". t('Embedding disabled') ." : $1</i><!-- /oembed $1 -->" ,$text);
        }
@@ -268,13 +280,13 @@ function oe_build_xpath($attr, $value){
        return "contains( normalize-space( @$attr ), ' $value ' ) or substring( normalize-space( @$attr ), 1, string-length( '$value' ) + 1 ) = '$value ' or substring( normalize-space( @$attr ), string-length( @$attr ) - string-length( '$value' ) ) = ' $value' or @$attr = '$value'";
 }
 
-function oe_get_inner_html( $node ) {
-    $innerHTML= '';
-    $children = $node->childNodes;
-    foreach ($children as $child) {
-        $innerHTML .= $child->ownerDocument->saveXML( $child );
-    }
-    return $innerHTML;
+function oe_get_inner_html($node) {
+       $innerHTML= '';
+       $children = $node->childNodes;
+       foreach ($children as $child) {
+               $innerHTML .= $child->ownerDocument->saveXML($child);
+       }
+       return $innerHTML;
 }
 
 /**
@@ -283,15 +295,16 @@ function oe_get_inner_html( $node ) {
  */
 function oembed_html2bbcode($text) {
        // start parser only if 'oembed' is in text
-       if (strpos($text, "oembed")){
+       if (strpos($text, "oembed")) {
 
                // convert non ascii chars to html entities
                $html_text = mb_convert_encoding($text, 'HTML-ENTITIES', mb_detect_encoding($text));
 
                // If it doesn't parse at all, just return the text.
                $dom = @DOMDocument::loadHTML($html_text);
-               if(! $dom)
+               if (! $dom) {
                        return $text;
+               }
                $xpath = new DOMXPath($dom);
                $attr = "oembed";
 
index 539ef020df8571a7e49a8ec0b48b19a311bf061c..d98d736550469225f226b6fbc7341065b9b43fef 100644 (file)
@@ -1,6 +1,15 @@
 <?php
 
+/**
+ * @file include/plaintext.php
+ */
+
+use \Friendica\ParseUrl;
+
 require_once("include/Photo.php");
+require_once("include/bbcode.php");
+require_once("include/html2plain.php");
+require_once("include/network.php");
 
 /**
  * @brief Fetches attachment data that were generated the old way
@@ -181,20 +190,17 @@ function get_attached_data($body) {
 
        // if nothing is found, it maybe having an image.
        if (!isset($post["type"])) {
-               require_once("mod/parse_url.php");
-               require_once("include/Photo.php");
-
                $URLSearchString = "^\[\]";
                if (preg_match_all("(\[url=([$URLSearchString]*)\]\s*\[img\]([$URLSearchString]*)\[\/img\]\s*\[\/url\])ism", $body, $pictures,  PREG_SET_ORDER)) {
                        if (count($pictures) == 1) {
                                // Checking, if the link goes to a picture
-                               $data = parseurl_getsiteinfo_cached($pictures[0][1], true);
+                               $data = ParseUrl::getSiteinfoCached($pictures[0][1], true);
 
                                // Workaround:
                                // Sometimes photo posts to the own album are not detected at the start.
                                // So we seem to cannot use the cache for these cases. That's strange.
                                if (($data["type"] != "photo") AND strstr($pictures[0][1], "/photos/"))
-                                       $data = parseurl_getsiteinfo($pictures[0][1], true);
+                                       $data = ParseUrl::getSiteinfo($pictures[0][1], true);
 
                                if ($data["type"] == "photo") {
                                        $post["type"] = "photo";
@@ -246,8 +252,7 @@ function get_attached_data($body) {
                        $post["text"] = trim($body);
                }
        } elseif (isset($post["url"]) AND ($post["type"] == "video")) {
-               require_once("mod/parse_url.php");
-               $data = parseurl_getsiteinfo_cached($post["url"], true);
+               $data = ParseUrl::getSiteinfoCached($post["url"], true);
 
                if (isset($data["images"][0]))
                        $post["image"] = $data["images"][0]["src"];
@@ -288,9 +293,6 @@ function shortenmsg($msg, $limit, $twitter = false) {
  * @return string The converted message
  */
 function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2, $target_network = "") {
-       require_once("include/bbcode.php");
-       require_once("include/html2plain.php");
-       require_once("include/network.php");
 
        // Remove the hash tags
        $URLSearchString = "^\[\]";
index 2e036247e237cf06c40d5f514300b2c57e1a1525..b3a66fc389d467476db31c16d36eebb53454fcad 100644 (file)
@@ -15,7 +15,7 @@ use \Friendica\Core\PConfig;
 
 require_once("boot.php");
 
-function poller_run(&$argv, &$argc){
+function poller_run($argv, $argc){
        global $a, $db;
 
        if(is_null($a)) {
@@ -35,16 +35,21 @@ function poller_run(&$argv, &$argc){
 
        $a->start_process();
 
-       $mypid = getmypid();
-
-       if ($a->max_processes_reached())
+       if (poller_max_connections_reached()) {
                return;
+       }
 
-       if (poller_max_connections_reached())
+       if (App::maxload_reached()) {
                return;
+       }
 
-       if (App::maxload_reached())
+       if(($argc <= 1) OR ($argv[1] != "no_cron")) {
+               poller_run_cron();
+       }
+
+       if ($a->max_processes_reached()) {
                return;
+       }
 
        // Checking the number of workers
        if (poller_too_much_workers()) {
@@ -52,118 +57,126 @@ function poller_run(&$argv, &$argc){
                return;
        }
 
-       if(($argc <= 1) OR ($argv[1] != "no_cron")) {
-               // Run the cron job that calls all other jobs
-               proc_run(PRIORITY_MEDIUM, "include/cron.php");
-
-               // Run the cronhooks job separately from cron for being able to use a different timing
-               proc_run(PRIORITY_MEDIUM, "include/cronhooks.php");
-
-               // Cleaning dead processes
-               poller_kill_stale_workers();
-       } else
-               // Sleep four seconds before checking for running processes again to avoid having too many workers
-               sleep(4);
-
-       // Checking number of workers
-       if (poller_too_much_workers())
-               return;
-
-       $cooldown = Config::get("system", "worker_cooldown", 0);
-
        $starttime = time();
 
        while ($r = poller_worker_process()) {
 
-               // Quit when in maintenance
-               if (get_config('system', 'maintenance', true))
+               // Count active workers and compare them with a maximum value that depends on the load
+               if (poller_too_much_workers()) {
                        return;
+               }
 
-               // Constantly check the number of parallel database processes
-               if ($a->max_processes_reached())
+               if (!poller_execute($r[0])) {
                        return;
+               }
 
-               // Constantly check the number of available database connections to let the frontend be accessible at any time
-               if (poller_max_connections_reached())
+               // Quit the poller once every hour
+               if (time() > ($starttime + 3600))
                        return;
+       }
 
-               // Count active workers and compare them with a maximum value that depends on the load
-               if (poller_too_much_workers())
-                       return;
+}
 
-               $upd = q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d AND `pid` = 0",
-                       dbesc(datetime_convert()),
-                       intval($mypid),
-                       intval($r[0]["id"]));
+/**
+ * @brief Execute a worker entry
+ *
+ * @param array $queue Workerqueue entry
+ *
+ * @return boolean "true" if further processing should be stopped
+ */
+function poller_execute($queue) {
 
-               if (!$upd) {
-                       logger("Couldn't update queue entry ".$r[0]["id"]." - skip this execution", LOGGER_DEBUG);
-                       q("COMMIT");
-                       continue;
-               }
+       $a = get_app();
 
-               // Assure that there are no tasks executed twice
-               $id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
-               if (!$id) {
-                       logger("Queue item ".$r[0]["id"]." vanished - skip this execution", LOGGER_DEBUG);
-                       q("COMMIT");
-                       continue;
-               } elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
-                       logger("Entry for queue item ".$r[0]["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
-                       q("COMMIT");
-                       continue;
-               } elseif ($id[0]["pid"] != $mypid) {
-                       logger("Queue item ".$r[0]["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
-                       q("COMMIT");
-                       continue;
-               }
+       $mypid = getmypid();
+
+       $cooldown = Config::get("system", "worker_cooldown", 0);
+
+       // Quit when in maintenance
+       if (get_config('system', 'maintenance', true)) {
+               return false;
+       }
+
+       // Constantly check the number of parallel database processes
+       if ($a->max_processes_reached()) {
+               return false;
+       }
+
+       // Constantly check the number of available database connections to let the frontend be accessible at any time
+       if (poller_max_connections_reached()) {
+               return false;
+       }
+
+       $upd = q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d AND `pid` = 0",
+               dbesc(datetime_convert()),
+               intval($mypid),
+               intval($queue["id"]));
+
+       if (!$upd) {
+               logger("Couldn't update queue entry ".$queue["id"]." - skip this execution", LOGGER_DEBUG);
                q("COMMIT");
+               return true;
+       }
 
-               $argv = json_decode($r[0]["parameter"]);
+       // Assure that there are no tasks executed twice
+       $id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
+       if (!$id) {
+               logger("Queue item ".$queue["id"]." vanished - skip this execution", LOGGER_DEBUG);
+               q("COMMIT");
+               return true;
+       } elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
+               logger("Entry for queue item ".$queue["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
+               q("COMMIT");
+               return true;
+       } elseif ($id[0]["pid"] != $mypid) {
+               logger("Queue item ".$queue["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
+               q("COMMIT");
+               return true;
+       }
+       q("COMMIT");
 
-               $argc = count($argv);
+       $argv = json_decode($queue["parameter"]);
 
-               // Check for existance and validity of the include file
-               $include = $argv[0];
+       $argc = count($argv);
 
-               if (!validate_include($include)) {
-                       logger("Include file ".$argv[0]." is not valid!");
-                       q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
-                       continue;
-               }
+       // Check for existance and validity of the include file
+       $include = $argv[0];
 
-               require_once($include);
+       if (!validate_include($include)) {
+               logger("Include file ".$argv[0]." is not valid!");
+               q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
+               return true;
+       }
 
-               $funcname = str_replace(".php", "", basename($argv[0]))."_run";
+       require_once($include);
 
-               if (function_exists($funcname)) {
-                       logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." ".$r[0]["parameter"]);
+       $funcname = str_replace(".php", "", basename($argv[0]))."_run";
 
-                       // For better logging create a new process id for every worker call
-                       // But preserve the old one for the worker
-                       $old_process_id = $a->process_id;
-                       $a->process_id = uniqid("wrk", true);
+       if (function_exists($funcname)) {
+               logger("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." ".$queue["parameter"]);
 
-                       $funcname($argv, $argc);
+               // For better logging create a new process id for every worker call
+               // But preserve the old one for the worker
+               $old_process_id = $a->process_id;
+               $a->process_id = uniqid("wrk", true);
 
-                       $a->process_id = $old_process_id;
+               $funcname($argv, $argc);
 
-                       if ($cooldown > 0) {
-                               logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." - in cooldown for ".$cooldown." seconds");
-                               sleep($cooldown);
-                       }
+               $a->process_id = $old_process_id;
 
-                       logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." - done");
+               if ($cooldown > 0) {
+                       logger("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." - in cooldown for ".$cooldown." seconds");
+                       sleep($cooldown);
+               }
 
-                       q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
-               } else
-                       logger("Function ".$funcname." does not exist");
+               logger("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." - done");
 
-               // Quit the poller once every hour
-               if (time() > ($starttime + 3600))
-                       return;
+               q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
+       } else {
+               logger("Function ".$funcname." does not exist");
        }
 
+       return true;
 }
 
 /**
@@ -177,9 +190,7 @@ function poller_max_connections_reached() {
        $max = get_config("system", "max_connections");
 
        // Fetch the percentage level where the poller will get active
-       $maxlevel = get_config("system", "max_connections_level");
-       if ($maxlevel == 0)
-               $maxlevel = 75;
+       $maxlevel = Config::get("system", "max_connections_level", 75);
 
        if ($max == 0) {
                // the maximum number of possible user connections can be a system variable
@@ -295,13 +306,13 @@ function poller_kill_stale_workers() {
                }
 }
 
+/**
+ * @brief Checks if the number of active workers exceeds the given limits
+ *
+ * @return bool Are there too much workers running?
+ */
 function poller_too_much_workers() {
-
-
-       $queues = get_config("system", "worker_queues");
-
-       if ($queues == 0)
-               $queues = 4;
+       $queues = Config::get("system", "worker_queues", 4);
 
        $maxqueues = $queues;
 
@@ -310,9 +321,7 @@ function poller_too_much_workers() {
        // Decrease the number of workers at higher load
        $load = current_load();
        if($load) {
-               $maxsysload = intval(get_config('system','maxloadavg'));
-               if($maxsysload < 1)
-                       $maxsysload = 50;
+               $maxsysload = intval(Config::get("system", "maxloadavg", 50));
 
                $maxworkers = $queues;
 
@@ -373,6 +382,11 @@ function poller_too_much_workers() {
        return($active >= $queues);
 }
 
+/**
+ * @brief Returns the number of active poller processes
+ *
+ * @return integer Number of active poller processes
+ */
 function poller_active_workers() {
        $workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'poller.php'");
 
@@ -394,8 +408,7 @@ function poller_passing_slow(&$highest_priority) {
 
        $r = q("SELECT `priority`
                FROM `process`
-               INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
-               WHERE `process`.`command` = 'poller.php'");
+               INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`");
 
        // No active processes at all? Fine
        if (!dbm::is_result($r))
@@ -435,7 +448,6 @@ function poller_passing_slow(&$highest_priority) {
  *
  * @return string SQL statement
  */
-
 function poller_worker_process() {
 
        q("START TRANSACTION;");
@@ -464,6 +476,96 @@ function poller_worker_process() {
        return $r;
 }
 
+/**
+ * @brief Call the front end worker
+ */
+function call_worker() {
+       if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
+               return;
+       }
+
+       $url = get_app()->get_baseurl()."/worker";
+       fetch_url($url, false, $redirects, 1);
+}
+
+/**
+ * @brief Call the front end worker if there aren't any active
+ */
+function call_worker_if_idle() {
+       if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
+               return;
+       }
+
+       // Do we have "proc_open"? Then we can fork the poller
+       if (function_exists("proc_open")) {
+               // When was the last time that we called the worker?
+               // Less than one minute? Then we quit
+               if ((time() - get_config("system", "worker_started")) < 60) {
+                       return;
+               }
+
+               set_config("system", "worker_started", time());
+
+               // Do we have enough running workers? Then we quit here.
+               if (poller_too_much_workers()) {
+                       // Cleaning dead processes
+                       poller_kill_stale_workers();
+                       get_app()->remove_inactive_processes();
+
+                       return;
+               }
+
+               poller_run_cron();
+
+               logger('Call poller', LOGGER_DEBUG);
+
+               $args = array("php", "include/poller.php", "no_cron");
+               $a = get_app();
+               $a->proc_run($args);
+               return;
+       }
+
+       // We cannot execute background processes.
+       // We now run the processes from the frontend.
+       // This won't work with long running processes.
+       poller_run_cron();
+
+       clear_worker_processes();
+
+       $workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'worker.php'");
+
+       if ($workers[0]["processes"] == 0) {
+               call_worker();
+       }
+}
+
+/**
+ * @brief Removes long running worker processes
+ */
+function clear_worker_processes() {
+       $timeout = Config::get("system", "frontend_worker_timeout", 10);
+
+       /// @todo We should clean up the corresponding workerqueue entries as well
+       q("DELETE FROM `process` WHERE `created` < '%s' AND `command` = 'worker.php'",
+               dbesc(datetime_convert('UTC','UTC',"now - ".$timeout." minutes")));
+}
+
+/**
+ * @brief Runs the cron processes
+ */
+function poller_run_cron() {
+       logger('Add cron entries', LOGGER_DEBUG);
+
+       // Run the cron job that calls all other jobs
+       proc_run(PRIORITY_MEDIUM, "include/cron.php");
+
+       // Run the cronhooks job separately from cron for being able to use a different timing
+       proc_run(PRIORITY_MEDIUM, "include/cronhooks.php");
+
+       // Cleaning dead processes
+       poller_kill_stale_workers();
+}
+
 if (array_search(__file__,get_included_files())===0){
        poller_run($_SERVER["argv"],$_SERVER["argc"]);
 
diff --git a/include/remove_contact.php b/include/remove_contact.php
new file mode 100644 (file)
index 0000000..ec8b83e
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @file include/remove_contact.php
+ * @brief Removes orphaned data from deleted contacts
+ */
+require_once("boot.php");
+
+function remove_contact_run($argv, $argc) {
+       global $a, $db;
+
+       if (is_null($a)) {
+               $a = new App;
+       }
+
+       if (is_null($db)) {
+               @include(".htconfig.php");
+               require_once("include/dba.php");
+               $db = new dba($db_host, $db_user, $db_pass, $db_data);
+               unset($db_host, $db_user, $db_pass, $db_data);
+       }
+
+       load_config('config');
+       load_config('system');
+
+       if ($argc != 2) {
+               return;
+       }
+
+       $id = intval($argv[1]);
+
+       // Only delete if the contact doesn't exist (anymore)
+       $r = q("SELECT `id` FROM `contact` WHERE `id` = %d", intval($id));
+       if (dbm::is_result($r)) {
+               return;
+       }
+
+       q("DELETE FROM `item` WHERE `contact-id` = %d", intval($id));
+
+       q("DELETE FROM `photo` WHERE `contact-id` = %d", intval($id));
+
+       q("DELETE FROM `mail` WHERE `contact-id` = %d", intval($id));
+
+       q("DELETE FROM `event` WHERE `cid` = %d", intval($id));
+
+       q("DELETE FROM `queue` WHERE `cid` = %d", intval($id));
+}
+
+if (array_search(__file__, get_included_files()) === 0) {
+       remove_contact_run($_SERVER["argv"], $_SERVER["argc"]);
+       killme();
+}
+?>
index 3bb376abafe8034fb85d550248c4a0758832df83..9f7de8f33e66732fc790840eaf2e3cf3f0ea03cb 100644 (file)
@@ -1,11 +1,12 @@
 <?php
+
 /**
  * @file include/xml.php
  */
 
 
 /**
- * @brief This class contain functions to work with XML data
+ * @brief This class contain methods to work with XML data
  *
  */
 class xml {
@@ -23,15 +24,17 @@ class xml {
        public static function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
 
                if ($root) {
-                       foreach($array as $key => $value) {
-                               foreach ($namespaces AS $nskey => $nsvalue)
+                       foreach ($array as $key => $value) {
+                               foreach ($namespaces AS $nskey => $nsvalue) {
                                        $key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"';
+                               }
 
                                if (is_array($value)) {
                                        $root = new SimpleXMLElement("<".$key."/>");
                                        self::from_array($value, $root, $remove_header, $namespaces, false);
-                               } else
+                               } else {
                                        $root = new SimpleXMLElement("<".$key.">".xmlify($value)."</".$key.">");
+                               }
 
                                $dom = dom_import_simplexml($root)->ownerDocument;
                                $dom->formatOutput = true;
@@ -39,16 +42,18 @@ class xml {
 
                                $xml_text = $dom->saveXML();
 
-                               if ($remove_header)
+                               if ($remove_header) {
                                        $xml_text = trim(substr($xml_text, 21));
+                               }
 
                                return $xml_text;
                        }
                }
 
                foreach($array as $key => $value) {
-                       if (!isset($element) AND isset($xml))
+                       if (!isset($element) AND isset($xml)) {
                                $element = $xml;
+                       }
 
                        if (is_integer($key)) {
                                if (isset($element)) {
@@ -62,27 +67,31 @@ class xml {
                        }
 
                        $element_parts = explode(":", $key);
-                       if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
+                       if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]])) {
                                $namespace = $namespaces[$element_parts[0]];
-                       elseif (isset($namespaces[""])) {
+                       elseif (isset($namespaces[""])) {
                                $namespace = $namespaces[""];
-                       } else
+                       } else {
                                $namespace = NULL;
+                       }
 
                        // Remove undefined namespaces from the key
-                       if ((count($element_parts) > 1) AND is_null($namespace))
+                       if ((count($element_parts) > 1) AND is_null($namespace)) {
                                $key = $element_parts[1];
+                       }
 
                        if (substr($key, 0, 11) == "@attributes") {
-                               if (!isset($element) OR !is_array($value))
+                               if (!isset($element) OR !is_array($value)) {
                                        continue;
+                               }
 
                                foreach ($value as $attr_key => $attr_value) {
                                        $element_parts = explode(":", $attr_key);
-                                       if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
+                                       if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]])) {
                                                $namespace = $namespaces[$element_parts[0]];
-                                       else
+                                       } else {
                                                $namespace = NULL;
+                                       }
 
                                        $element->addAttribute($attr_key, $attr_value, $namespace);
                                }
@@ -90,9 +99,9 @@ class xml {
                                continue;
                        }
 
-                       if (!is_array($value))
+                       if (!is_array($value)) {
                                $element = $xml->addChild($key, xmlify($value), $namespace);
-                       elseif (is_array($value)) {
+                       elseif (is_array($value)) {
                                $element = $xml->addChild($key, NULL, $namespace);
                                self::from_array($value, $element, $remove_header, $namespaces, false);
                        }
@@ -111,8 +120,9 @@ class xml {
                        $target->addChild($elementname, xmlify($source));
                else {
                        $child = $target->addChild($elementname);
-                       foreach ($source->children() AS $childfield => $childentry)
+                       foreach ($source->children() AS $childfield => $childentry) {
                                self::copy($childentry, $child, $childfield);
+                       }
                }
        }
 
@@ -168,11 +178,11 @@ class xml {
                        return(null);
                }
 
-               if (!is_string($xml_element) &&
-               !is_array($xml_element) &&
-               (get_class($xml_element) == 'SimpleXMLElement')) {
-                       $xml_element_copy = $xml_element;
-                       $xml_element = get_object_vars($xml_element);
+               if (!is_string($xml_element)
+                       && !is_array($xml_element)
+                       && (get_class($xml_element) == 'SimpleXMLElement')) {
+                               $xml_element_copy = $xml_element;
+                               $xml_element = get_object_vars($xml_element);
                }
 
                if (is_array($xml_element)) {
@@ -181,7 +191,7 @@ class xml {
                                return (trim(strval($xml_element_copy)));
                        }
 
-                       foreach($xml_element as $key=>$value) {
+                       foreach ($xml_element as $key => $value) {
 
                                $recursion_depth++;
                                $result_array[strtolower($key)] =
@@ -223,10 +233,12 @@ class xml {
         *
         * @return array The parsed XML in an array form. Use print_r() to see the resulting array structure.
         */
-       public static function to_array($contents, $namespaces = true, $get_attributes=1, $priority = 'attribute') {
-               if(!$contents) return array();
+       public static function to_array($contents, $namespaces = true, $get_attributes = 1, $priority = 'attribute') {
+               if (!$contents) {
+                       return array();
+               }
 
-               if(!function_exists('xml_parser_create')) {
+               if (!function_exists('xml_parser_create')) {
                        logger('xml::to_array: parser function missing');
                        return array();
                }
@@ -235,12 +247,13 @@ class xml {
                libxml_use_internal_errors(true);
                libxml_clear_errors();
 
-               if($namespaces)
+               if ($namespaces) {
                        $parser = @xml_parser_create_ns("UTF-8",':');
-               else
+               } else {
                        $parser = @xml_parser_create();
+               }
 
-               if(! $parser) {
+               if (! $parser) {
                        logger('xml::to_array: xml_parser_create: no resource');
                        return array();
                }
@@ -252,10 +265,11 @@ class xml {
                @xml_parse_into_struct($parser, trim($contents), $xml_values);
                @xml_parser_free($parser);
 
-               if(! $xml_values) {
+               if (! $xml_values) {
                        logger('xml::to_array: libxml: parse error: ' . $contents, LOGGER_DATA);
-                       foreach(libxml_get_errors() as $err)
+                       foreach (libxml_get_errors() as $err) {
                                logger('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message, LOGGER_DATA);
+                       }
                        libxml_clear_errors();
                        return;
                }
@@ -270,8 +284,8 @@ class xml {
 
                // Go through the tags.
                $repeated_tag_index = array(); // Multiple tags with same name will be turned into an array
-               foreach($xml_values as $data) {
-                       unset($attributes,$value); // Remove existing values, or there will be trouble
+               foreach ($xml_values as $data) {
+                       unset($attributes, $value); // Remove existing values, or there will be trouble
 
                        // This command will extract these variables into the foreach scope
                        // tag(string), type(string), level(int), attributes(array).
@@ -280,46 +294,54 @@ class xml {
                        $result = array();
                        $attributes_data = array();
 
-                       if(isset($value)) {
-                               if($priority == 'tag') $result = $value;
-                               else $result['value'] = $value; // Put the value in a assoc array if we are in the 'Attribute' mode
+                       if (isset($value)) {
+                               if ($priority == 'tag') {
+                                       $result = $value;
+                               } else {
+                                       $result['value'] = $value; // Put the value in a assoc array if we are in the 'Attribute' mode
+                               }
                        }
 
                        //Set the attributes too.
-                       if(isset($attributes) and $get_attributes) {
-                               foreach($attributes as $attr => $val) {
-                                       if($priority == 'tag') $attributes_data[$attr] = $val;
-                                       else $result['@attributes'][$attr] = $val; // Set all the attributes in a array called 'attr'
+                       if (isset($attributes) and $get_attributes) {
+                               foreach ($attributes as $attr => $val) {
+                                       if($priority == 'tag') {
+                                               $attributes_data[$attr] = $val;
+                                       } else {
+                                               $result['@attributes'][$attr] = $val; // Set all the attributes in a array called 'attr'
+                                       }
                                }
                        }
 
                        // See tag status and do the needed.
-                       if($namespaces && strpos($tag,':')) {
-                               $namespc = substr($tag,0,strrpos($tag,':'));
-                               $tag = strtolower(substr($tag,strlen($namespc)+1));
+                       if ($namespaces && strpos($tag, ':')) {
+                               $namespc = substr($tag, 0, strrpos($tag, ':'));
+                               $tag = strtolower(substr($tag, strlen($namespc)+1));
                                $result['@namespace'] = $namespc;
                        }
                        $tag = strtolower($tag);
 
-                       if($type == "open") {   // The starting of the tag '<tag>'
+                       if ($type == "open") {   // The starting of the tag '<tag>'
                                $parent[$level-1] = &$current;
-                               if(!is_array($current) or (!in_array($tag, array_keys($current)))) { // Insert New tag
+                               if (!is_array($current) or (!in_array($tag, array_keys($current)))) { // Insert New tag
                                        $current[$tag] = $result;
-                                       if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
+                                       if ($attributes_data) {
+                                               $current[$tag. '_attr'] = $attributes_data;
+                                       }
                                        $repeated_tag_index[$tag.'_'.$level] = 1;
 
                                        $current = &$current[$tag];
 
                                } else { // There was another element with the same tag name
 
-                                       if(isset($current[$tag][0])) { // If there is a 0th element it is already an array
+                                       if (isset($current[$tag][0])) { // If there is a 0th element it is already an array
                                                $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                                                $repeated_tag_index[$tag.'_'.$level]++;
                                        } else { // This section will make the value an array if multiple tags with the same name appear together
-                                               $current[$tag] = array($current[$tag],$result); // This will combine the existing item and the new item together to make an array
+                                               $current[$tag] = array($current[$tag], $result); // This will combine the existing item and the new item together to make an array
                                                $repeated_tag_index[$tag.'_'.$level] = 2;
 
-                                               if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
+                                               if (isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
                                                        $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                                                        unset($current[$tag.'_attr']);
                                                }
@@ -329,35 +351,37 @@ class xml {
                                        $current = &$current[$tag][$last_item_index];
                                }
 
-                       } elseif($type == "complete") { // Tags that ends in 1 line '<tag />'
+                       } elseif ($type == "complete") { // Tags that ends in 1 line '<tag />'
                                //See if the key is already taken.
-                               if(!isset($current[$tag])) { //New Key
+                               if (!isset($current[$tag])) { //New Key
                                        $current[$tag] = $result;
                                        $repeated_tag_index[$tag.'_'.$level] = 1;
-                                       if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;
+                                       if ($priority == 'tag' and $attributes_data) {
+                                               $current[$tag. '_attr'] = $attributes_data;
+                                       }
 
                                } else { // If taken, put all things inside a list(array)
-                                       if(isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array...
+                                       if (isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array...
 
                                                // ...push the new element into that array.
                                                $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
 
-                                               if($priority == 'tag' and $get_attributes and $attributes_data) {
+                                               if ($priority == 'tag' and $get_attributes and $attributes_data) {
                                                        $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                                                }
                                                $repeated_tag_index[$tag.'_'.$level]++;
 
                                        } else { // If it is not an array...
-                                               $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
+                                               $current[$tag] = array($current[$tag], $result); //...Make it an array using using the existing value and the new value
                                                $repeated_tag_index[$tag.'_'.$level] = 1;
-                                               if($priority == 'tag' and $get_attributes) {
-                                                       if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
+                                               if ($priority == 'tag' and $get_attributes) {
+                                                       if (isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
 
                                                                $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                                                                unset($current[$tag.'_attr']);
                                                        }
 
-                                                       if($attributes_data) {
+                                                       if ($attributes_data) {
                                                                $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                                                        }
                                                }
@@ -365,12 +389,25 @@ class xml {
                                        }
                                }
 
-                       } elseif($type == 'close') { // End of tag '</tag>'
+                       } elseif ($type == 'close') { // End of tag '</tag>'
                                $current = &$parent[$level-1];
                        }
                }
 
                return($xml_array);
        }
+
+       /**
+        * @brief Delete a node in a XML object
+        * 
+        * @param object $doc XML document
+        * @param string $node Node name
+        */
+       public static function deleteNode(&$doc, $node) {
+               $xpath = new DomXPath($doc);
+               $list = $xpath->query("//".$node);
+               foreach ($list as $child) {
+                       $child->parentNode->removeChild($child);
+               }
+       }
 }
-?>
index 13c3f6318f815fd4923926836af04bca8abb8120..08f24af60f49238d43a7d30832767dd939feea2b 100644 (file)
--- a/index.php
+++ b/index.php
@@ -99,6 +99,10 @@ if (!$a->is_backend()) {
        $stamp1 = microtime(true);
        session_start();
        $a->save_timestamp($stamp1, "parser");
+} else {
+       require_once "include/poller.php";
+
+       call_worker_if_idle();
 }
 
 /**
index 958b0a8ae3c8d74b92671b203f5b694f9ab4d42e..b2a4dfe35cf71bd06a6a1d692df18d4de45bf187 100644 (file)
@@ -92,7 +92,6 @@
                /* event from comment textarea button popups */
                /* insert returned bbcode at cursor position or replace selected text */
                $("body").on("fbrowser.image.comment", function(e, filename, bbcode, id) {
-                       console.log("on", id);
                        $.colorbox.close();
                        var textarea = document.getElementById("comment-edit-text-" +id);
                        var start = textarea.selectionStart;
                        $("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
                        $("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
                        input.val(val);
-                       //console.log(id);
                });
 
                /* setup field_richtext */
                                $("#nav-notifications-linkmenu").removeClass("on");
                        }
 
-                       console.log(data.sysmsgs);
-
                        $(data.sysmsgs.notice).each(function(key, message){
                                $.jGrowl(message, {sticky: true, theme: 'notice'});
                        });
                // page number
                infinite_scroll.pageno+=1;
 
-               console.log('Loading page ' + infinite_scroll.pageno);
-
                // get the raw content from the next page and insert this content
                // right before "#conversation-end"
                $.get('network?mode=raw' + infinite_scroll.reload_uri + '&page=' + infinite_scroll.pageno, function(data) {
index 51cd59c62fe100b203e6caf8683571725491318c..5aea4eede967524f4b093dd04657aebadb985479 100644 (file)
@@ -1,17 +1,21 @@
 <?php
 
-/*
- * Module: dfrn_confirm
+/**
+ * @file mod/dfrn_confirm.php
+ * @brief Module: dfrn_confirm
  * Purpose: Friendship acceptance for DFRN contacts
- *
+ *.
  * There are two possible entry points and three scenarios.
- *
+ *.
  *   1. A form was submitted by our user approving a friendship that originated elsewhere.
  *      This may also be called from dfrn_request to automatically approve a friendship.
  *
  *   2. We may be the target or other side of the conversation to scenario 1, and will
  *      interact with that process on our own user's behalf.
- *
+ *.
+ *  @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
+ *    You also find a graphic which describes the confirmation process at
+ *    https://github.com/friendica/friendica/blob/master/spec/dfrn2_contact_confirmation.png
  */
 
 require_once('include/enotify.php');
@@ -22,7 +26,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
        if(is_array($handsfree)) {
 
-               /**
+               /*
                 * We were called directly from dfrn_request due to automatic friend acceptance.
                 * Any $_POST parameters we may require are supplied in the $handsfree array.
                 *
@@ -37,7 +41,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        $node = $a->argv[1];
        }
 
-               /**
+               /*
                 *
                 * Main entry point. Scenario 1. Our user received a friend request notification (perhaps
                 * from another site) and clicked 'Approve'.
@@ -87,7 +91,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        $activity = ((x($_POST,'activity'))   ? intval($_POST['activity'])      : 0 );
                }
 
-               /**
+               /*
                 *
                 * Ensure that dfrn_id has precedence when we go to find the contact record.
                 * We only want to search based on contact id if there is no dfrn_id,
@@ -103,7 +107,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                        logger('Confirming follower with contact_id: ' . $cid);
 
 
-               /**
+               /*
                 *
                 * The other person will have been issued an ID when they first requested friendship.
                 * Locate their record. At this time, their record will have both pending and blocked set to 1.
@@ -139,7 +143,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
                if($network === NETWORK_DFRN) {
 
-                       /**
+                       /*
                         *
                         * Generate a key pair for all further communications with this person.
                         * We have a keypair for every contact, and a site key for unknown people.
@@ -166,7 +170,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
                        $params = array();
 
-                       /**
+                       /*
                         *
                         * Per the DFRN protocol, we will verify both ends by encrypting the dfrn_id with our
                         * site private key (person on the other end can decrypt it with our site public key).
@@ -212,7 +216,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
                        logger('Confirm: posting data to ' . $dfrn_confirm . ': ' . print_r($params,true), LOGGER_DATA);
 
-                       /**
+                       /*
                         *
                         * POST all this stuff to the other site.
                         * Temporarily raise the network timeout to 120 seconds because the default 60
@@ -506,7 +510,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
                //NOTREACHED
        }
 
-       /**
+       /*
         *
         *
         * End of Scenario 1. [Local confirmation of remote friend request].
index 780fb456f5cd33f43e7bc6783196fd15e55570f1..6f6fc41c12d28078290c9bd85cc66f9dd01cc5db 100644 (file)
@@ -1,5 +1,10 @@
 <?php
 
+/**
+ * @file mod/dfrn_notify.php
+ * @brief The dfrn notify endpoint
+ * @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
+ */
 require_once('include/items.php');
 require_once('include/dfrn.php');
 require_once('include/event.php');
@@ -7,7 +12,7 @@ require_once('include/event.php');
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
 function dfrn_notify_post(&$a) {
-    logger(__function__, LOGGER_TRACE);
+       logger(__function__, LOGGER_TRACE);
        $dfrn_id      = ((x($_POST,'dfrn_id'))      ? notags(trim($_POST['dfrn_id']))   : '');
        $dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version']    : 2.0);
        $challenge    = ((x($_POST,'challenge'))    ? notags(trim($_POST['challenge'])) : '');
@@ -117,7 +122,7 @@ function dfrn_notify_post(&$a) {
 
        if($dissolve == 1) {
 
-               /**
+               /*
                 * Relationship is dissolved permanently
                 */
 
index 7fe2527f3d73c9401654243c4bcaa1b2cf29d757..d7566905b72f6291f64a7c0ce989f854a34416ad 100644 (file)
@@ -1,12 +1,15 @@
 <?php
 
 /**
- *
- * Module: dfrn_request
+ * @file mod/dfrn_request.php
+ * @brief Module: dfrn_request
  *
  * Purpose: Handles communication associated with the issuance of
  * friend requests.
  *
+ * @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
+ *    You also find a graphic which describes the confirmation process at
+ *    https://github.com/friendica/friendica/blob/master/spec/dfrn2_contact_request.png
  */
 
 require_once('include/enotify.php');
@@ -14,7 +17,6 @@ require_once('include/Scrape.php');
 require_once('include/Probe.php');
 require_once('include/group.php');
 
-if(! function_exists('dfrn_request_init')) {
 function dfrn_request_init(&$a) {
 
        if($a->argc > 1)
@@ -22,7 +24,7 @@ function dfrn_request_init(&$a) {
 
        profile_load($a,$which);
        return;
-}}
+}
 
 
 /**
@@ -40,8 +42,6 @@ function dfrn_request_init(&$a) {
  * After logging in, we click 'submit' to approve the linkage.
  *
  */
-
-if(! function_exists('dfrn_request_post')) {
 function dfrn_request_post(&$a) {
 
        if(($a->argc != 2) || (! count($a->profile))) {
@@ -55,7 +55,7 @@ function dfrn_request_post(&$a) {
        }
 
 
-       /**
+       /*
         *
         * Scenario 2: We've introduced ourself to another cell, then have been returned to our own cell
         * to confirm the request, and then we've clicked submit (perhaps after logging in).
@@ -65,7 +65,7 @@ function dfrn_request_post(&$a) {
 
        if((x($_POST,'localconfirm')) && ($_POST['localconfirm'] == 1)) {
 
-               /**
+               /*
                 * Ensure this is a valid request
                 */
 
@@ -77,23 +77,24 @@ function dfrn_request_post(&$a) {
                        $confirm_key = ((x($_POST,'confirm_key')) ? $_POST['confirm_key'] : "");
                        $hidden = ((x($_POST,'hidden-contact')) ? intval($_POST['hidden-contact']) : 0);
                        $contact_record = null;
+                       $blocked = 1;
+                       $pending = 1;
 
                        if(x($dfrn_url)) {
 
-                               /**
+                               /*
                                 * Lookup the contact based on their URL (which is the only unique thing we have at the moment)
                                 */
 
-                               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND (`url` = '%s' OR `nurl` = '%s') AND `self` = 0 LIMIT 1",
+                               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND NOT `self` LIMIT 1",
                                        intval(local_user()),
-                                       dbesc($dfrn_url),
                                        dbesc(normalise_link($dfrn_url))
                                );
 
                                if(count($r)) {
                                        if(strlen($r[0]['dfrn-id'])) {
 
-                                               /**
+                                               /*
                                                 * We don't need to be here. It has already happened.
                                                 */
 
@@ -113,7 +114,7 @@ function dfrn_request_post(&$a) {
                                }
                                else {
 
-                                       /**
+                                       /*
                                         * Scrape the other site's profile page to pick up the dfrn links, key, fn, and photo
                                         */
 
@@ -141,19 +142,18 @@ function dfrn_request_post(&$a) {
 
                                        $photo = $parms["photo"];
 
-                                       /********* Escape the entire array ********/
+                                       // Escape the entire array
 
                                        dbesc_array($parms);
 
-                                       /******************************************/
 
-                                       /**
+                                       /*
                                         * Create a contact record on our site for the other person
                                         */
 
                                        $r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `nurl`, `addr`, `name`, `nick`, `photo`, `site-pubkey`,
-                                               `request`, `confirm`, `notify`, `poll`, `poco`, `network`, `aes_allow`, `hidden`)
-                                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
+                                               `request`, `confirm`, `notify`, `poll`, `poco`, `network`, `aes_allow`, `hidden`, `blocked`, `pending`)
+                                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d)",
                                                intval(local_user()),
                                                datetime_convert(),
                                                dbesc($dfrn_url),
@@ -170,7 +170,9 @@ function dfrn_request_post(&$a) {
                                                $parms['dfrn-poco'],
                                                dbesc(NETWORK_DFRN),
                                                intval($aes_allow),
-                                               intval($hidden)
+                                               intval($hidden),
+                                               intval($blocked),
+                                               intval($pending)
                                        );
                                }
 
@@ -195,7 +197,7 @@ function dfrn_request_post(&$a) {
                                } else
                                        $forwardurl = $a->get_baseurl()."/contacts";
 
-                               /**
+                               /*
                                 * Allow the blocked remote notification to complete
                                 */
 
@@ -222,7 +224,7 @@ function dfrn_request_post(&$a) {
                return; // NOTREACHED
        }
 
-       /**
+       /*
         * Otherwise:
         *
         * Scenario 1:
@@ -256,11 +258,13 @@ function dfrn_request_post(&$a) {
        $contact_record = null;
        $failed         = false;
        $parms          = null;
+       $blocked = 1;
+       $pending = 1;
 
 
        if( x($_POST,'dfrn_url')) {
 
-               /**
+               /*
                 * Block friend request spam
                 */
 
@@ -277,7 +281,7 @@ function dfrn_request_post(&$a) {
                        }
                }
 
-               /**
+               /*
                 *
                 * Cleanup old introductions that remain blocked.
                 * Also remove the contact record, but only if there is no existing relationship
@@ -304,7 +308,7 @@ function dfrn_request_post(&$a) {
                        }
                }
 
-               /**
+               /*
                 *
                 * Cleanup any old email intros - which will have a greater lifetime
                 */
@@ -354,8 +358,6 @@ function dfrn_request_post(&$a) {
                        $nurl    = normalise_url($host);
                        $poll    = 'email ' . random_string();
                        $notify  = 'smtp ' . random_string();
-                       $blocked = 1;
-                       $pending = 1;
                        $network = NETWORK_MAIL2;
                        $rel     = CONTACT_IS_FOLLOWER;
 
@@ -540,8 +542,8 @@ function dfrn_request_post(&$a) {
 
                                dbesc_array($parms);
                                $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `name`, `nick`, `issued-id`, `photo`, `site-pubkey`,
-                                       `request`, `confirm`, `notify`, `poll`, `poco`, `network` )
-                                       VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
+                                       `request`, `confirm`, `notify`, `poll`, `poco`, `network`, `blocked`, `pending` )
+                                       VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
                                        intval($uid),
                                        dbesc(datetime_convert()),
                                        $parms['url'],
@@ -557,7 +559,9 @@ function dfrn_request_post(&$a) {
                                        $parms['dfrn-notify'],
                                        $parms['dfrn-poll'],
                                        $parms['dfrn-poco'],
-                                       dbesc(NETWORK_DFRN)
+                                       dbesc(NETWORK_DFRN),
+                                       intval($blocked),
+                                       intval($pending)
                                );
 
                                // find the contact record we just created
@@ -613,7 +617,7 @@ function dfrn_request_post(&$a) {
                        // END $network === NETWORK_DFRN
                } elseif (($network != NETWORK_PHANTOM) AND ($url != "")) {
 
-                       /**
+                       /*
                         *
                         * Substitute our user's feed URL into $url template
                         * Send the subscriber home to subscribe
@@ -642,12 +646,9 @@ function dfrn_request_post(&$a) {
                }
 
        }       return;
-}}
-
-
+}
 
 
-if(! function_exists('dfrn_request_content')) {
 function dfrn_request_content(&$a) {
 
        if(($a->argc != 2) || (! count($a->profile)))
@@ -781,7 +782,7 @@ function dfrn_request_content(&$a) {
        }
        else {
 
-               /**
+               /*
                 * Normal web request. Display our user's introduction form.
                 */
 
@@ -793,7 +794,7 @@ function dfrn_request_content(&$a) {
                }
 
 
-               /**
+               /*
                 * Try to auto-fill the profile address
                 */
 
@@ -816,7 +817,7 @@ function dfrn_request_content(&$a) {
                $target_addr = $a->profile['nickname'] . '@' . substr(z_root(), strpos(z_root(),'://') + 3 );
 
 
-               /**
+               /*
                 *
                 * The auto_request form only has the profile address
                 * because nobody is going to read the comments and
@@ -881,4 +882,4 @@ function dfrn_request_content(&$a) {
        }
 
        return; // Somebody is fishing.
-}}
+}
index 23075ad775e64a6bc73b7c47a3b4f3726fff45b2..410e0877377ef9291cbf0ae7b016c6a8204a3ea8 100644 (file)
 <?php
+
 /** 
  * @file mod/parse_url.php
+ * @brief The parse_url module
  * 
- * @todo https://developers.google.com/+/plugins/snippet/
- * 
- * @verbatim
- * <meta itemprop="name" content="Toller Titel">
- * <meta itemprop="description" content="Eine tolle Beschreibung">
- * <meta itemprop="image" content="http://maple.libertreeproject.org/images/tree-icon.png">
+ * This module does parse an url for embedable content (audio, video, image files or link)
+ * information and does format this information to BBCode or html (this depends
+ * on the user settings - default is BBCode output).
+ * If the user has enabled the richtext editor setting the output will be in html
+ * (Note: This is not always possible and in some case not useful because
+ * the richtext editor doesn't support all kind of html).
+ * Otherwise the output will be constructed BBCode.
  * 
- * <body itemscope itemtype="http://schema.org/Product">
- *   <h1 itemprop="name">Shiny Trinket</h1>
- *   <img itemprop="image" src="{image-url}" />
- *   <p itemprop="description">Shiny trinkets are shiny.</p>
- * </body>
- * @endverbatim
+ * @see ParseUrl::getSiteinfo() for more information about scraping embeddable content 
 */
 
-if(!function_exists('deletenode')) {
-       function deletenode(&$doc, $node)
-       {
-               $xpath = new DomXPath($doc);
-               $list = $xpath->query("//".$node);
-               foreach ($list as $child)
-                       $child->parentNode->removeChild($child);
-       }
-}
-
-function completeurl($url, $scheme) {
-       $urlarr = parse_url($url);
-
-       if (isset($urlarr["scheme"]))
-               return($url);
-
-       $schemearr = parse_url($scheme);
-
-       $complete = $schemearr["scheme"]."://".$schemearr["host"];
-
-       if (@$schemearr["port"] != "")
-               $complete .= ":".$schemearr["port"];
-
-               if(strpos($urlarr['path'],'/') !== 0)
-                       $complete .= '/';
-
-       $complete .= $urlarr["path"];
-
-       if (@$urlarr["query"] != "")
-               $complete .= "?".$urlarr["query"];
-
-       if (@$urlarr["fragment"] != "")
-               $complete .= "#".$urlarr["fragment"];
-
-       return($complete);
-}
+use \Friendica\ParseUrl;
 
-function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
+require_once("include/items.php");
 
-       if ($url == "")
-               return false;
+function parse_url_content(&$a) {
 
-       $r = q("SELECT * FROM `parsed_url` WHERE `url` = '%s' AND `guessing` = %d AND `oembed` = %d",
-               dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed));
+       $text = null;
+       $str_tags = "";
 
-       if ($r)
-               $data = $r[0]["content"];
+       $textmode = false;
 
-       if (!is_null($data)) {
-               $data = unserialize($data);
-               return $data;
+       if (local_user() && (!feature_enabled(local_user(), "richtext"))) {
+               $textmode = true;
        }
 
-       $data = parseurl_getsiteinfo($url, $no_guessing, $do_oembed);
-
-       q("INSERT INTO `parsed_url` (`url`, `guessing`, `oembed`, `content`, `created`) VALUES ('%s', %d, %d, '%s', '%s')
-                ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'",
-               dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed),
-               dbesc(serialize($data)), dbesc(datetime_convert()),
-               dbesc(serialize($data)), dbesc(datetime_convert()));
+       $br = (($textmode) ? "\n" : "<br />");
 
-       return $data;
-}
-
-function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
-       require_once("include/network.php");
-       require_once("include/Photo.php");
-
-       $a = get_app();
-
-       $siteinfo = array();
-
-       // Check if the URL does contain a scheme
-       $scheme = parse_url($url, PHP_URL_SCHEME);
-
-       if ($scheme == "") {
-               $url = "http://".trim($url, "/");
+       if (x($_GET,"binurl")) {
+               $url = trim(hex2bin($_GET["binurl"]));
+       } else {
+               $url = trim($_GET["url"]);
        }
 
-       if ($count > 10) {
-               logger("parseurl_getsiteinfo: Endless loop detected for ".$url, LOGGER_DEBUG);
-               return($siteinfo);
+       if ($_GET["title"]) {
+               $title = strip_tags(trim($_GET["title"]));
        }
 
-       $url = trim($url, "'");
-       $url = trim($url, '"');
-
-       $url = original_url($url);
-
-       $siteinfo["url"] = $url;
-       $siteinfo["type"] = "link";
-
-       $check_cert = get_config('system','verifyssl');
-
-       $stamp1 = microtime(true);
-
-       $ch = curl_init();
-       curl_setopt($ch, CURLOPT_URL, $url);
-       curl_setopt($ch, CURLOPT_HEADER, 1);
-       curl_setopt($ch, CURLOPT_NOBODY, 1);
-       curl_setopt($ch, CURLOPT_TIMEOUT, 3);
-       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-       curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
-       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
-       curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
-
-       $header = curl_exec($ch);
-       $curl_info = @curl_getinfo($ch);
-       $http_code = $curl_info['http_code'];
-       curl_close($ch);
-
-       $a->save_timestamp($stamp1, "network");
-
-       if ((($curl_info['http_code'] == "301") OR ($curl_info['http_code'] == "302") OR ($curl_info['http_code'] == "303") OR ($curl_info['http_code'] == "307"))
-               AND (($curl_info['redirect_url'] != "") OR ($curl_info['location'] != ""))) {
-               if ($curl_info['redirect_url'] != "")
-                       $siteinfo = parseurl_getsiteinfo($curl_info['redirect_url'], $no_guessing, $do_oembed, ++$count);
-               else
-                       $siteinfo = parseurl_getsiteinfo($curl_info['location'], $no_guessing, $do_oembed, ++$count);
-               return($siteinfo);
+       if ($_GET["description"]) {
+               $text = strip_tags(trim($_GET["description"]));
        }
 
-       // if the file is too large then exit
-       if ($curl_info["download_content_length"] > 1000000)
-               return($siteinfo);
-
-       // if it isn't a HTML file then exit
-       if (($curl_info["content_type"] != "") AND !strstr(strtolower($curl_info["content_type"]),"html"))
-               return($siteinfo);
-
-       if ($do_oembed) {
-               require_once("include/oembed.php");
-
-               $oembed_data = oembed_fetch_url($url);
-
-               if (!in_array($oembed_data->type, array("error", "rich"))) {
-                       $siteinfo["type"] = $oembed_data->type;
-               }
-
-               if (($oembed_data->type == "link") AND ($siteinfo["type"] != "photo")) {
-                       if (isset($oembed_data->title))
-                               $siteinfo["title"] = $oembed_data->title;
-                       if (isset($oembed_data->description))
-                               $siteinfo["text"] = trim($oembed_data->description);
-                       if (isset($oembed_data->thumbnail_url))
-                               $siteinfo["image"] = $oembed_data->thumbnail_url;
+       if ($_GET["tags"]) {
+               $arr_tags = ParseUrl::convertTagsToArray($_GET["tags"]);
+               if (count($arr_tags)) {
+                       $str_tags = $br . implode(" ", $arr_tags) . $br;
                }
        }
 
-       $stamp1 = microtime(true);
-
-       // Now fetch the body as well
-       $ch = curl_init();
-       curl_setopt($ch, CURLOPT_URL, $url);
-       curl_setopt($ch, CURLOPT_HEADER, 1);
-       curl_setopt($ch, CURLOPT_NOBODY, 0);
-       curl_setopt($ch, CURLOPT_TIMEOUT, 10);
-       curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-       curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
-       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
-       curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
-
-       $header = curl_exec($ch);
-       $curl_info = @curl_getinfo($ch);
-       $http_code = $curl_info['http_code'];
-       curl_close($ch);
-
-       $a->save_timestamp($stamp1, "network");
-
-       // Fetch the first mentioned charset. Can be in body or header
-       $charset = "";
-       if (preg_match('/charset=(.*?)['."'".'"\s\n]/', $header, $matches))
-               $charset = trim(trim(trim(array_pop($matches)), ';,'));
-
-       if ($charset == "")
-               $charset = "utf-8";
-
-       $pos = strpos($header, "\r\n\r\n");
-
-       if ($pos)
-               $body = trim(substr($header, $pos));
-       else
-               $body = $header;
-
-       if (($charset != '') AND (strtoupper($charset) != "UTF-8")) {
-               logger("parseurl_getsiteinfo: detected charset ".$charset, LOGGER_DEBUG);
-               //$body = mb_convert_encoding($body, "UTF-8", $charset);
-               $body = iconv($charset, "UTF-8//TRANSLIT", $body);
-       }
-
-       $body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
-
-       $doc = new DOMDocument();
-       @$doc->loadHTML($body);
-
-       deletenode($doc, 'style');
-       deletenode($doc, 'script');
-       deletenode($doc, 'option');
-       deletenode($doc, 'h1');
-       deletenode($doc, 'h2');
-       deletenode($doc, 'h3');
-       deletenode($doc, 'h4');
-       deletenode($doc, 'h5');
-       deletenode($doc, 'h6');
-       deletenode($doc, 'ol');
-       deletenode($doc, 'ul');
-
-       $xpath = new DomXPath($doc);
-
-       $list = $xpath->query("//meta[@content]");
-       foreach ($list as $node) {
-               $attr = array();
-               if ($node->attributes->length)
-                       foreach ($node->attributes as $attribute)
-                               $attr[$attribute->name] = $attribute->value;
-
-               if (@$attr["http-equiv"] == 'refresh') {
-                       $path = $attr["content"];
-                       $pathinfo = explode(";", $path);
-                       $content = "";
-                       foreach ($pathinfo AS $value) {
-                               if (substr(strtolower($value), 0, 4) == "url=")
-                                       $content = substr($value, 4);
-                       }
-                       if ($content != "") {
-                               $siteinfo = parseurl_getsiteinfo($content, $no_guessing, $do_oembed, ++$count);
-                               return($siteinfo);
-                       }
+       // Add url scheme if it is missing
+       $arrurl = parse_url($url);
+       if (!x($arrurl, "scheme")) {
+               if (x($arrurl, "host")) {
+                       $url = "http:".$url;
+               } else {
+                       $url = "http://".$url;
                }
        }
 
-       $list = $xpath->query("//title");
-       if ($list->length > 0)
-               $siteinfo["title"] = $list->item(0)->nodeValue;
-
-       //$list = $xpath->query("head/meta[@name]");
-       $list = $xpath->query("//meta[@name]");
-       foreach ($list as $node) {
-               $attr = array();
-               if ($node->attributes->length)
-                       foreach ($node->attributes as $attribute)
-                               $attr[$attribute->name] = $attribute->value;
-
-               $attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
-
-               if ($attr["content"] != "")
-                       switch (strtolower($attr["name"])) {
-                               case "fulltitle":
-                                       $siteinfo["title"] = $attr["content"];
-                                       break;
-                               case "description":
-                                       $siteinfo["text"] = $attr["content"];
-                                       break;
-                               case "thumbnail":
-                                       $siteinfo["image"] = $attr["content"];
-                                       break;
-                               case "twitter:image":
-                                       $siteinfo["image"] = $attr["content"];
-                                       break;
-                               case "twitter:image:src":
-                                       $siteinfo["image"] = $attr["content"];
-                                       break;
-                               case "twitter:card":
-                                       if (($siteinfo["type"] == "") OR ($attr["content"] == "photo"))
-                                               $siteinfo["type"] = $attr["content"];
-                                       break;
-                               case "twitter:description":
-                                       $siteinfo["text"] = $attr["content"];
-                                       break;
-                               case "twitter:title":
-                                       $siteinfo["title"] = $attr["content"];
-                                       break;
-                               case "dc.title":
-                                       $siteinfo["title"] = $attr["content"];
-                                       break;
-                               case "dc.description":
-                                       $siteinfo["text"] = $attr["content"];
-                                       break;
-                               case "keywords":
-                                       $keywords = explode(",", $attr["content"]);
-                                       break;
-                               case "news_keywords":
-                                       $keywords = explode(",", $attr["content"]);
-                                       break;
+       logger("prse_url: " . $url);
+
+       // Check if the URL is an image, video or audio file. If so format
+       // the URL with the corresponding BBCode media tag
+       $redirects = 0;
+       // Fetch the header of the URL
+       $result = z_fetch_url($url, false, $redirects, array("novalidate" => true, "nobody" => true));
+       if($result["success"]) {
+               // Convert the header fields into an array
+               $hdrs = array();
+               $h = explode("\n", $result["header"]);
+               foreach ($h as $l) {
+                       list($k,$v) = array_map("trim", explode(":", trim($l), 2));
+                       $hdrs[$k] = $v;
+               }
+               if (array_key_exists("Content-Type", $hdrs)) {
+                       $type = $hdrs["Content-Type"];
+               }
+               if ($type) {
+                       if(stripos($type, "image/") !== false) {
+                               echo $br . "[img]" . $url . "[/img]" . $br;
+                               killme();
                        }
-               if ($siteinfo["type"] == "summary")
-                       $siteinfo["type"] = "link";
-       }
-
-       if (isset($keywords)) {
-               $siteinfo["keywords"] = array();
-               foreach ($keywords as $keyword)
-                       if (!in_array(trim($keyword), $siteinfo["keywords"]))
-                               $siteinfo["keywords"][] = trim($keyword);
-       }
-
-       //$list = $xpath->query("head/meta[@property]");
-       $list = $xpath->query("//meta[@property]");
-       foreach ($list as $node) {
-               $attr = array();
-               if ($node->attributes->length)
-                       foreach ($node->attributes as $attribute)
-                               $attr[$attribute->name] = $attribute->value;
-
-               $attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
-
-               if ($attr["content"] != "")
-                       switch (strtolower($attr["property"])) {
-                               case "og:image":
-                                       $siteinfo["image"] = $attr["content"];
-                                       break;
-                               case "og:title":
-                                       $siteinfo["title"] = $attr["content"];
-                                       break;
-                               case "og:description":
-                                       $siteinfo["text"] = $attr["content"];
-                                       break;
+                       if (stripos($type, "video/") !== false) {
+                               echo $br . "[video]" . $url . "[/video]" . $br;
+                               killme();
                        }
-       }
-
-       if ((@$siteinfo["image"] == "") AND !$no_guessing) {
-           $list = $xpath->query("//img[@src]");
-           foreach ($list as $node) {
-               $attr = array();
-               if ($node->attributes->length)
-                   foreach ($node->attributes as $attribute)
-                       $attr[$attribute->name] = $attribute->value;
-
-                       $src = completeurl($attr["src"], $url);
-                       $photodata = get_photo_info($src);
-
-                       if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) {
-                               if ($photodata[0] > 300) {
-                                       $photodata[1] = round($photodata[1] * (300 / $photodata[0]));
-                                       $photodata[0] = 300;
-                               }
-                               if ($photodata[1] > 300) {
-                                       $photodata[0] = round($photodata[0] * (300 / $photodata[1]));
-                                       $photodata[1] = 300;
-                               }
-                               $siteinfo["images"][] = array("src"=>$src,
-                                                               "width"=>$photodata[0],
-                                                               "height"=>$photodata[1]);
+                       if (stripos($type, "audio/") !== false) {
+                               echo $br . "[audio]" . $url . "[/audio]" . $br;
+                               killme();
                        }
-
-               }
-    } elseif ($siteinfo["image"] != "") {
-               $src = completeurl($siteinfo["image"], $url);
-
-               unset($siteinfo["image"]);
-
-               $photodata = get_photo_info($src);
-
-               if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10))
-                       $siteinfo["images"][] = array("src"=>$src,
-                                                       "width"=>$photodata[0],
-                                                       "height"=>$photodata[1]);
-       }
-
-       if ((@$siteinfo["text"] == "") AND (@$siteinfo["title"] != "") AND !$no_guessing) {
-               $text = "";
-
-               $list = $xpath->query("//div[@class='article']");
-               foreach ($list as $node)
-                       if (strlen($node->nodeValue) > 40)
-                               $text .= " ".trim($node->nodeValue);
-
-               if ($text == "") {
-                       $list = $xpath->query("//div[@class='content']");
-                       foreach ($list as $node)
-                               if (strlen($node->nodeValue) > 40)
-                                       $text .= " ".trim($node->nodeValue);
-               }
-
-               // If none text was found then take the paragraph content
-               if ($text == "") {
-                       $list = $xpath->query("//p");
-                       foreach ($list as $node)
-                               if (strlen($node->nodeValue) > 40)
-                                       $text .= " ".trim($node->nodeValue);
-               }
-
-               if ($text != "") {
-                       $text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
-
-                       while (strpos($text, "  "))
-                               $text = trim(str_replace("  ", " ", $text));
-
-                       $siteinfo["text"] = trim(html_entity_decode(substr($text,0,350), ENT_QUOTES, "UTF-8").'...');
                }
        }
 
-       logger("parseurl_getsiteinfo: Siteinfo for ".$url." ".print_r($siteinfo, true), LOGGER_DEBUG);
-
-       call_hooks('getsiteinfo', $siteinfo);
-
-       return($siteinfo);
-}
-
-function arr_add_hashes(&$item,$k) {
-       $item = '#' . $item;
-}
-
-function parse_url_content(&$a) {
-
-       require_once("include/items.php");
-
-       $text = null;
-       $str_tags = '';
-
-       $textmode = false;
-
-       if(local_user() && (! feature_enabled(local_user(),'richtext')))
-               $textmode = true;
-
-       //if($textmode)
-       $br = (($textmode) ? "\n" : '<br />');
-
-       if(x($_GET,'binurl'))
-               $url = trim(hex2bin($_GET['binurl']));
-       else
-               $url = trim($_GET['url']);
-
-       if($_GET['title'])
-               $title = strip_tags(trim($_GET['title']));
-
-       if($_GET['description'])
-               $text = strip_tags(trim($_GET['description']));
-
-       if($_GET['tags']) {
-               $arr_tags = str_getcsv($_GET['tags']);
-               if(count($arr_tags)) {
-                       array_walk($arr_tags,'arr_add_hashes');
-                       $str_tags = $br . implode(' ',$arr_tags) . $br;
-               }
-       }
-
-       // add url scheme if missing
-       $arrurl = parse_url($url);
-       if (!x($arrurl, 'scheme')) {
-               if (x($arrurl, 'host'))
-                       $url = "http:".$url;
-               else
-                       $url = "http://".$url;
-       }
-
-       logger('parse_url: ' . $url);
-
-       if($textmode)
-               $template = '[bookmark=%s]%s[/bookmark]%s';
-       else
+       if ($textmode) {
+               $template = "[bookmark=%s]%s[/bookmark]%s";
+       } else {
                $template = "<a class=\"bookmark\" href=\"%s\" >%s</a>%s";
+       }
 
-       $arr = array('url' => $url, 'text' => '');
+       $arr = array("url" => $url, "text" => "");
 
-       call_hooks('parse_link', $arr);
+       call_hooks("parse_link", $arr);
 
-       if(strlen($arr['text'])) {
-               echo $arr['text'];
+       if (strlen($arr["text"])) {
+               echo $arr["text"];
                killme();
        }
 
+       // If there is allready some content information submitted we don't
+       // need to parse the url for content.
+       if ($url && $title && $text) {
 
-       if($url && $title && $text) {
-
-               $title = str_replace(array("\r","\n"),array('',''),$title);
+               $title = str_replace(array("\r","\n"),array("",""),$title);
 
-               if($textmode)
-                       $text = '[quote]' . trim($text) . '[/quote]' . $br;
-               else {
-                       $text = '<blockquote>' . htmlspecialchars(trim($text)) . '</blockquote><br />';
+               if ($textmode) {
+                       $text = "[quote]" . trim($text) . "[/quote]" . $br;
+               else {
+                       $text = "<blockquote>" . htmlspecialchars(trim($text)) . "</blockquote><br />";
                        $title = htmlspecialchars($title);
                }
 
-               $result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
+               $result = sprintf($template, $url, ($title) ? $title : $url, $text) . $str_tags;
 
-               logger('parse_url (unparsed): returns: ' . $result);
+               logger("parse_url (unparsed): returns: " . $result);
 
                echo $result;
                killme();
        }
 
-       $siteinfo = parseurl_getsiteinfo($url);
+       // Fetch the information directly from the webpage
+       $siteinfo = ParseUrl::getSiteinfo($url);
 
        unset($siteinfo["keywords"]);
 
+       // Format it as BBCode attachment
        $info = add_page_info_data($siteinfo);
 
-       if (!$textmode)
+       if (!$textmode) {
                // Replace ' with ’ - not perfect - but the richtext editor has problems otherwise
                $info = str_replace(array("&#039;"), array("&#8217;"), $info);
+       }
 
        echo $info;
 
        killme();
 }
-?>
+
+/**
+ * @brief Legacy function to call ParseUrl::getSiteinfoCached
+ * 
+ * Note: We have moved the function to ParseUrl.php. This function is only for
+ * legacy support and will be remove in the future
+ * 
+ * @param type $url The url of the page which should be scraped
+ * @param type $no_guessing If true the parse doens't search for
+ *    preview pictures
+ * @param type $do_oembed The false option is used by the function fetch_oembed()
+ *    to avoid endless loops
+ * 
+ * @return array which contains needed data for embedding
+ * 
+ * @see ParseUrl::getSiteinfoCached()
+ * 
+ * @todo Remove this function after all Addons has been changed to use
+ *    ParseUrl::getSiteinfoCached
+ */
+function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
+       $siteinfo = ParseUrl::getSiteinfoCached($url, $no_guessing, $do_oembed);
+       return $siteinfo;
+}
index 6f612303fb0ba9cceed3c26875af867106437790..1e1e7d8489e7fc63d635dc0587e2b57a2ba81fce 100644 (file)
@@ -6,14 +6,88 @@ require_once('include/group.php');
 require_once('mod/proxy.php');
 require_once('include/xml.php');
 
-function ping_init(&$a) {
-
+/**
+ * @brief Outputs the counts and the lists of various notifications
+ *
+ * The output format can be controlled via the GET parameter 'format'. It can be
+ * - xml (deprecated legacy default)
+ * - json (outputs JSONP with the 'callback' GET parameter)
+ *
+ * Expected JSON structure:
+ * {
+ *             "result": {
+ *                     "intro": 0,
+ *                     "mail": 0,
+ *                     "net": 0,
+ *                     "home": 0,
+ *                     "register": 0,
+ *                     "all-events": 0,
+ *                     "all-events-today": 0,
+ *                     "events": 0,
+ *                     "events-today": 0,
+ *                     "birthdays": 0,
+ *                     "birthdays-today": 0,
+ *                     "groups": [ ],
+ *                     "forums": [ ],
+ *                     "notify": 0,
+ *                     "notifications": [ ],
+ *                     "sysmsgs": {
+ *                             "notice": [ ],
+ *                             "info": [ ]
+ *                     }
+ *             }
+ *     }
+ *
+ * @param App $a The Friendica App instance
+ */
+function ping_init(App $a)
+{
        $format = 'xml';
 
        if (isset($_GET['format']) && $_GET['format'] == 'json') {
                $format = 'json';
        }
 
+       $tags          = array();
+       $comments      = array();
+       $likes         = array();
+       $dislikes      = array();
+       $friends       = array();
+       $posts         = array();
+       $regs          = array();
+       $mails         = array();
+       $notifications = array();
+
+       $intro_count    = 0;
+       $mail_count     = 0;
+       $home_count     = 0;
+       $network_count  = 0;
+       $register_count = 0;
+       $sysnotify_count = 0;
+       $groups_unseen  = array();
+       $forums_unseen  = array();
+
+       $all_events       = 0;
+       $all_events_today = 0;
+       $events           = 0;
+       $events_today     = 0;
+       $birthdays        = 0;
+       $birthdays_today  = 0;
+
+       $data = array();
+       $data['intro']    = $intro_count;
+       $data['mail']     = $mail_count;
+       $data['net']      = $network_count;
+       $data['home']     = $home_count;
+       $data['register'] = $register_count;
+
+       $data['all-events']       = $all_events;
+       $data['all-events-today'] = $all_events_today;
+       $data['events']           = $events;
+       $data['events-today']     = $events_today;
+       $data['birthdays']        = $birthdays;
+       $data['birthdays-today']  = $birthdays_today;
+
        if (local_user()){
                // Different login session than the page that is calling us.
                if (intval($_GET['uid']) && intval($_GET['uid']) != local_user()) {
@@ -37,27 +111,11 @@ function ping_init(&$a) {
                }
 
                $notifs = ping_get_notifications(local_user());
-               $sysnotify_count = 0; // we will update this in a moment
-
-               $tags     = array();
-               $comments = array();
-               $likes    = array();
-               $dislikes = array();
-               $friends  = array();
-               $posts    = array();
-               $regs     = array();
-               $mails    = array();
-
-               $home_count = 0;
-               $network_count = 0;
-               $register_count = 0;
-               $groups_unseen = array();
-               $forums_unseen = array();
-
-               $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`wall`, `item`.`author-name`,
+
+               $items_unseen = q("SELECT `item`.`id`, `item`.`parent`, `item`.`verb`, `item`.`wall`, `item`.`author-name`,
                                `item`.`contact-id`, `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object`,
-                               `pitem`.`author-name` as `pname`, `pitem`.`author-link` as `plink`
-                               FROM `item` INNER JOIN `item` as `pitem` ON  `pitem`.`id`=`item`.`parent`
+                               `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`
+                               FROM `item` INNER JOIN `item` AS `pitem` ON  `pitem`.`id` = `item`.`parent`
                                WHERE `item`.`unseen` = 1 AND `item`.`visible` = 1 AND
                                 `item`.`deleted` = 0 AND `item`.`uid` = %d AND `pitem`.`parent` != 0
                                AND `item`.`contact-id` != %d
@@ -65,13 +123,12 @@ function ping_init(&$a) {
                        intval(local_user()), intval(local_user())
                );
 
-               if (dbm::is_result($r)) {
-
-                       $arr = array('items' => $r);
+               if (dbm::is_result($items_unseen)) {
+                       $arr = array('items' => $items_unseen);
                        call_hooks('network_ping', $arr);
 
-                       foreach ($r as $it) {
-                               if ($it['wall']) {
+                       foreach ($items_unseen as $item) {
+                               if ($item['wall']) {
                                        $home_count++;
                                } else {
                                        $network_count++;
@@ -80,7 +137,7 @@ function ping_init(&$a) {
                }
 
                if ($network_count) {
-                       if (intval(feature_enabled(local_user(),'groups'))) {
+                       if (intval(feature_enabled(local_user(), 'groups'))) {
                                // Find out how unseen network posts are spread across groups
                                $group_counts = groups_count_unseen();
                                if (dbm::is_result($group_counts)) {
@@ -92,7 +149,7 @@ function ping_init(&$a) {
                                }
                        }
 
-                       if (intval(feature_enabled(local_user(),'forumlist_widget'))) {
+                       if (intval(feature_enabled(local_user(), 'forumlist_widget'))) {
                                $forum_counts = ForumManager::count_unseen_items();
                                if (dbm::is_result($forums_counts)) {
                                        foreach ($forums_counts as $forum_count) {
@@ -107,13 +164,13 @@ function ping_init(&$a) {
                $intros1 = q("SELECT  `intro`.`id`, `intro`.`datetime`,
                        `fcontact`.`name`, `fcontact`.`url`, `fcontact`.`photo`
                        FROM `intro` LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
-                       WHERE `intro`.`uid` = %d  AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`fid`!=0",
+                       WHERE `intro`.`uid` = %d  AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`fid` != 0",
                        intval(local_user())
                );
                $intros2 = q("SELECT `intro`.`id`, `intro`.`datetime`,
                        `contact`.`name`, `contact`.`url`, `contact`.`photo`
                        FROM `intro` LEFT JOIN `contact` ON `intro`.`contact-id` = `contact`.`id`
-                       WHERE `intro`.`uid` = %d  AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`contact-id`!=0",
+                       WHERE `intro`.`uid` = %d  AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`contact-id` != 0",
                        intval(local_user())
                );
 
@@ -129,32 +186,27 @@ function ping_init(&$a) {
                $mail_count = count($mails);
 
                if ($a->config['register_policy'] == REGISTER_APPROVE && is_site_admin()){
-                       $regs = q("SELECT `contact`.`name`, `contact`.`url`, `contact`.`micro`, `register`.`created`, COUNT(*) as `total` FROM `contact` RIGHT JOIN `register` ON `register`.`uid`=`contact`.`uid` WHERE `contact`.`self`=1");
+                       $regs = q("SELECT `contact`.`name`, `contact`.`url`, `contact`.`micro`, `register`.`created`, COUNT(*) AS `total`
+                               FROM `contact` RIGHT JOIN `register` ON `register`.`uid` = `contact`.`uid`
+                               WHERE `contact`.`self` = 1");
                        if ($regs) {
                                $register_count = $regs[0]['total'];
                        }
                }
 
-               $all_events = 0;
-               $all_events_today = 0;
-               $events = 0;
-               $events_today = 0;
-               $birthdays = 0;
-               $birthdays_today = 0;
-
-               $ev = q("SELECT count(`event`.`id`) as total, type, start, adjust FROM `event`
+               $ev = q("SELECT count(`event`.`id`) AS total, type, start, adjust FROM `event`
                        WHERE `event`.`uid` = %d AND `start` < '%s' AND `finish` > '%s' and `ignore` = 0
                        ORDER BY `start` ASC ",
                        intval(local_user()),
-                       dbesc(datetime_convert('UTC','UTC','now + 7 days')),
-                       dbesc(datetime_convert('UTC','UTC','now'))
+                       dbesc(datetime_convert('UTC', 'UTC', 'now + 7 days')),
+                       dbesc(datetime_convert('UTC', 'UTC', 'now'))
                );
 
                if (dbm::is_result($ev)) {
                        $all_events = intval($ev[0]['total']);
 
                        if ($all_events) {
-                               $str_now = datetime_convert('UTC',$a->timezone,'now','Y-m-d');
+                               $str_now = datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d');
                                foreach($ev as $x) {
                                        $bd = false;
                                        if ($x['type'] === 'birthday') {
@@ -164,7 +216,7 @@ function ping_init(&$a) {
                                        else {
                                                $events ++;
                                        }
-                                       if (datetime_convert('UTC',((intval($x['adjust'])) ? $a->timezone : 'UTC'), $x['start'],'Y-m-d') === $str_now) {
+                                       if (datetime_convert('UTC', ((intval($x['adjust'])) ? $a->timezone : 'UTC'), $x['start'], 'Y-m-d') === $str_now) {
                                                $all_events_today ++;
                                                if ($bd)
                                                        $birthdays_today ++;
@@ -175,7 +227,6 @@ function ping_init(&$a) {
                        }
                }
 
-               $data = array();
                $data['intro']    = $intro_count;
                $data['mail']     = $mail_count;
                $data['net']      = $network_count;
@@ -290,12 +341,12 @@ function ping_init(&$a) {
        $sysmsgs = array();
        $sysmsgs_info = array();
 
-       if (x($_SESSION,'sysmsg')) {
+       if (x($_SESSION, 'sysmsg')) {
                $sysmsgs = $_SESSION['sysmsg'];
                unset($_SESSION['sysmsg']);
        }
 
-       if (x($_SESSION,'sysmsg_info')) {
+       if (x($_SESSION, 'sysmsg_info')) {
                $sysmsgs_info = $_SESSION['sysmsg_info'];
                unset($_SESSION['sysmsg_info']);
        }
@@ -337,14 +388,14 @@ function ping_init(&$a) {
  * @param int $uid User id
  * @return array Associative array of notifications
  */
-function ping_get_notifications($uid) {
-
-       $result = array();
-       $offset = 0;
-       $seen = false;
+function ping_get_notifications($uid)
+{
+       $result  = array();
+       $offset  = 0;
+       $seen    = false;
        $seensql = "NOT";
-       $order = "DESC";
-       $quit = false;
+       $order   = "DESC";
+       $quit    = false;
 
        $a = get_app();
 
@@ -419,39 +470,42 @@ function ping_get_notifications($uid) {
  * @param array $notifs Complete list of notification
  * @param array $sysmsgs List of system notice messages
  * @param array $sysmsgs_info List of system info messages
+ * @param int $groups_unseen Number of unseen group items
+ * @param int $forums_unseen Number of unseen forum items
  * @return array XML-transform ready data array
  */
-function ping_format_xml_data($data, $sysnotify_count, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen) {
+function ping_format_xml_data($data, $sysnotify, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen)
+{
        $notifications = array();
-       foreach($notifs as $key => $n) {
-               $notifications[$key . ":note"] = $n['message'];
-
-               $notifications[$key . ":@attributes"] = array(
-                       "id" => $n["id"],
-                       "href" => $n['href'],
-                       "name" => $n['name'],
-                       "url" => $n['url'],
-                       "photo" => $n['photo'],
-                       "date" => $n['date'],
-                       "seen" => $n['seen'],
-                       "timestamp" => $n['timestamp']
+       foreach($notifs as $key => $notif) {
+               $notifications[$key . ':note'] = $notif['message'];
+
+               $notifications[$key . ':@attributes'] = array(
+                       'id'        => $notif['id'],
+                       'href'      => $notif['href'],
+                       'name'      => $notif['name'],
+                       'url'       => $notif['url'],
+                       'photo'     => $notif['photo'],
+                       'date'      => $notif['date'],
+                       'seen'      => $notif['seen'],
+                       'timestamp' => $notif['timestamp']
                );
        }
 
        $sysmsg = array();
        foreach ($sysmsgs as $key => $m){
-               $sysmsg[$key . ":notice"] = $m;
+               $sysmsg[$key . ':notice'] = $m;
        }
        foreach ($sysmsgs_info as $key => $m){
-               $sysmsg[$key . ":info"] = $m;
+               $sysmsg[$key . ':info'] = $m;
        }
 
-       $data["notif"] = $notifications;
-       $data["@attributes"] = array("count" => $sysnotify_count + $data["intro"] + $data["mail"] + $data["register"]);
-       $data["sysmsgs"] = $sysmsg;
+       $data['notif'] = $notifications;
+       $data['@attributes'] = array('count' => $sysnotify_count + $data['intro'] + $data['mail'] + $data['register']);
+       $data['sysmsgs'] = $sysmsg;
 
-       if ($data["register"] == 0) {
-               unset($data["register"]);
+       if ($data['register'] == 0) {
+               unset($data['register']);
        }
 
        $groups = array();
@@ -473,4 +527,4 @@ function ping_format_xml_data($data, $sysnotify_count, $notifs, $sysmsgs, $sysms
        }
 
        return $data;
-}
\ No newline at end of file
+}
diff --git a/mod/worker.php b/mod/worker.php
new file mode 100644 (file)
index 0000000..aebffed
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @file mod/worker.php
+ * @brief Module for running the poller as frontend process
+ */
+require_once("include/poller.php");
+
+use \Friendica\Core\Config;
+use \Friendica\Core\PConfig;
+
+function worker_init($a){
+
+       if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
+               return;
+       }
+
+       // We don't need the following lines if we can execute background jobs
+       if (function_exists("proc_open")) {
+               return;
+       }
+
+       clear_worker_processes();
+
+       $workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'worker.php'");
+
+       if ($workers[0]["processes"] > Config::get("system", "worker_queues", 4)) {
+               return;
+       }
+
+       $a->start_process();
+
+       logger("Front end worker started: ".getmypid());
+
+       call_worker();
+
+       if ($r = poller_worker_process()) {
+
+               // On most configurations this parameter wouldn't have any effect.
+               // But since it doesn't destroy anything, we just try to get more execution time in any way.
+               set_time_limit(0);
+
+               poller_execute($r[0]);
+       }
+
+       call_worker();
+
+       $a->end_process();
+
+       logger("Front end worker ended: ".getmypid());
+
+       killme();
+}
index 390fc4bb85ff10d3b39bd382b34a566a97366ae3..b95f6cc2f80f35a2900977fdb6093ba3ed05755f 100644 (file)
Binary files a/spec/dfrn2.odt and b/spec/dfrn2.odt differ
index e46225f7e90d78963c29a313aa847c97a920756a..f524c457afaddd7fbe9adb3b13baf3425f9f9eac 100644 (file)
Binary files a/spec/dfrn2.pdf and b/spec/dfrn2.pdf differ
diff --git a/spec/dfrn2_contact_confirmation.png b/spec/dfrn2_contact_confirmation.png
new file mode 100644 (file)
index 0000000..843e7c7
Binary files /dev/null and b/spec/dfrn2_contact_confirmation.png differ
diff --git a/spec/dfrn2_contact_confirmation.svg b/spec/dfrn2_contact_confirmation.svg
new file mode 100644 (file)
index 0000000..bb506a2
--- /dev/null
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="1633" height="2173" viewBox="0 0 1633 2173">
+<style type="text/css"><![CDATA[
+text { font:12px Dialog; }
+]]></style>
+<rect x="-485" y="-485" width="2603" height="3143" style="fill:rgb(255,255,255);stroke:none" />
+<clipPath id="clip1"><path d="M614,37 L1056,37 L1056,106 L614,106 L614,37 Z" /></clipPath>
+<path d="M616,39 L616,103 L1053,103 L1053,39 Z" style="fill:rgb(202,221,254);stroke:none" clip-path="url(#clip1)" />
+<clipPath id="clip2"><path d="M614,37 L1056,37 L1056,106 L614,106 L614,37 Z" /></clipPath>
+<path d="M616,39 L616,103 L1053,103 L1053,39 Z" style="fill:none;stroke:rgb(61,83,127)" clip-path="url(#clip2)" />
+<text x="649" y="76" style="font:18px Open Sans">Friendica - Contact confirmation</text>
+<clipPath id="clip3"><path d="M1198,202 L1388,202 L1388,244 L1198,244 L1198,202 Z" /></clipPath>
+<path d="M1208,204 C1203.5820313,204 1200,207.5820313 1200,212 L1200,233 C1200,237.4179688 1203.5820313,241 1208,241 L1377,241 C1381.4179688,241 1385,237.4179688 1385,233 L1385,212 C1385,207.5820313 1381.4179688,204 1377,204 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip3)" />
+<clipPath id="clip4"><path d="M1198,202 L1388,202 L1388,244 L1198,244 L1198,202 Z" /></clipPath>
+<path d="M1208,204 C1203.5820313,204 1200,207.5820313 1200,212 L1200,233 C1200,237.4179688 1203.5820313,241 1208,241 L1377,241 C1381.4179688,241 1385,237.4179688 1385,233 L1385,212 C1385,207.5820313 1381.4179688,204 1377,204 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip4)" />
+<text x="1213" y="225" style="font:13px Tahoma">bob@example.com</text>
+<image x="0" y="0" width="1374" height="231" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABV4AAADnCAYAAADmQE2RAAAIU0lEQVR42u3dTW+UZRSA4SYSfoACIi4EhERCJAhWpXZKUT4UEaGlRVuMgNQQlKCoGEBIGbUCEgsUkK+2YFsUUSIxhoVGkUBLCkIRypcSoOUPqCy6sceZUQyZoC5cel3JWUzeOZtneefN8+bkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPB/EBH/aQAAAAAAyJIdUgt3ne+V2NVeld905ofUdGVm19m2RNOZZPqZ8AoAAAAA8C9ujKiPNp18elTdyWu9R1bEvaU7Y8r6szG5+kwULtsfwxdui/yG9p8Tje3ThFcAAAAAgH9wPaCO2dFWmmg43X1fxd64Y9KxGDm/PUq3dETp5o4oSU3xxssxevlXUdB4untMw6lS4RUAAAAA4G+k42mi7njvRP0Pv+S9vj8mV1+KCVUXY/rWjnh6W0eU1XZGYeWFGDijLYbNbY+B4+pjTGP7r3kfnuwjvAIAAAAA3EQmvG5rSw57cVPkLToXRTVX4pntnanpiLK6zijaeDnyl52PQbNORt+px+K28a0xpHxlJLaeqBJeAQAAAABuIh1P8zcfbxswuiYefPVM5mqBstqOKK/vjBk7OmP86osx+q0LUZg8F3eXH4i+4/dE/7ylkVv15dnUek8nCAAAAACQJRNeNxzryn2pLaasv/zH9QJ1nfHszs54ruFq5K+4EE+u/SkeWHgwRr36USxqORyLj7ZE0ZZPfkut93OCAAAAAABZMuF1XWvX4yvP/3Wva3kmvF6Nok2Xo8/M76P39ANx/8t7YnFrSxStaYyH5qzKxNfBBQUFThAAAAAAIEsmvL5/pC3x2r4o2nglSrdcyXxQK/3Ga8mWizFg1rdxz+zGmPBOU0xYXh8F8+viieSGeKPlcHevQYNGOEEAAAAAgCyZj2utak4On7M+xiZ/jKEVp+KpdZeivPZSFFe3RtGaT2Npa3PM2b0vXtj9eUxdvSMWp34/9s7G5tR6bycIAAAAAJAlHV7z3jvcJ//dQz+Pmrcvbh1/NAbPbIvitSeipHpvvNnaHGOXbouy2s9i7t4vMtF13Nt1XXfmThmeWu/hBAEAAAAAsqTDa+at17cOTns4+V13//xN8cAr7TEx+XUsOXIoSqobY+CkDZG/YHsUV9dHwZLa7qGz11akVnuk9wAAAAAAyHI9vGbuel1xoGTUsm+u3fd8TeTN+yDePNoc4xZVx6TKmljaejjGrtjZNXzu1pmptVuu7wAAAAAAkOXG8JqewspveyUqv6nKXfDx2eJ1Tb+l4+uSI4e6JyZrDt0+cuK9OX++6Sq8AgAAAAD8jezwekNQ7ZmafkMeeaSg1113jcj540NaPbL/9ztNv3iKQ/ZEAwAAAABJRU5ErkJggg==" /><clipPath id="clip5"><path d="M181,198 L432,198 L432,240 L181,240 L181,198 Z" /></clipPath>
+<path d="M191,200 C186.5820313,200 183,203.5820313 183,208 L183,229 C183,233.4179688 186.5820313,237 191,237 L421,237 C425.4179688,237 429,233.4179688 429,229 L429,208 C429,203.5820313 425.4179688,200 421,200 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip5)" />
+<clipPath id="clip6"><path d="M181,198 L432,198 L432,240 L181,240 L181,198 Z" /></clipPath>
+<path d="M191,200 C186.5820313,200 183,203.5820313 183,208 L183,229 C183,233.4179688 186.5820313,237 191,237 L421,237 C425.4179688,237 429,233.4179688 429,229 L429,208 C429,203.5820313 425.4179688,200 421,200 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip6)" />
+<text x="197" y="221" style="font:13px Tahoma">karen@karenhompage.com</text>
+<image x="0" y="0" width="418" height="227" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaIAAADjCAYAAADHeBASAAAE2klEQVR42u3cS29VVRiAYRKNP0ApIg64CImEQEAEbe0pF6EookKhBSlGQGoISlBQDNeUg1RAI5cCcm3BtiiiRGIMAw0goYUUhHIpNyVAyx9AGXRCP3eP0RinLXHyPMkanazJmrz59l5nd+oEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+PiGjXAoAODdHwvVc7p/Y2luXWXDqfrJbM2nu5IVVzKd32mxABcN9C9HzNuSnZFefuZg0uif5Fe2L8xsvxyrpLMXzZoRg4f0fkVjXeSVU3ThIiADo8RCN2NxSlqi62Dio5EI+NOx2D5zZG0bamKNraFIXJmrj5Zgxb/mPkVV9sHVF1oUiIAOiwEKUqzmSlKs//nvPBoWQCuhFjyq7H5O1NMWVHU0zd1RzDS69Fr2kNMWB2Y/QaXRkjqhv/yPniXBchAqBjQrSjIT3g7S2Rs/BKFJTfitd2NicriVBFcxQkk1DusqvRe8a56DrhdDySXx99i1dHavvZMiECoENClLv1TEPPYeXxzIJLmUdxU3c1RXFlc0zb3Rz5a6/HsJXXYnj6SjxRfDS65u+PHjlLYkjZD5eT7Q85QQDaH6JNp1uGvNMQ4zfe/OtxXDIJvb6nOd6ouh25K67Fy+t/i6Hzj0X2gi9j4YnaWHTqRBRs+/pesr2bEwSg/SHaUN/y4uqr/7wXKs6E6HYUbLkZXab/ElmTj8bT7+6PRfVJgD6tjmdnrcnEqE9eXp4TBKD9IfrsZEPq/YNRsPlWFG27lbmg0DYRFW67Hj1nHIknZ1bHmFU1MWZ5ZeTNrYiX0pviwxO1rZ17937KCQLQ7hCl1tSlB87aGKPSv0a/kgvx6oYbUbzrRkxcV59MQN/Ekvq6mLXvYLy177uYsHZ3MhnVxQurNtcl27OcIADtDlHOJ7Vdcj8+fid7zsF4OP9U9JneEBPXn43CdQdiaRKdUUt2JFPStzH7wPeZCI3+qKLl8SHjBybbH3SCALQ7RJmpaOWxSc+lf27tkbslhr7XGGPTP8Xik8eTGFVHr3GbInfezmRCqoy8xbta+81cX9IWIde3AeiwEGXeFa04Wpi97PDdQW+WR86cz2PpqWT6WbguxpWWx5L62hi1Yk/LwNnbpyfbHvBlBQA6PESZj56WHumcKj1cNmTeV5cnbqi51xajZDJqHZsuP/7o4LH9/56EhAiA+xKifwWm7c+q3fqOHJnXuXv3tttxWf+NUNv6E/vueIp8e9bqAAAAAElFTkSuQmCC" /><clipPath id="clip7"><path d="M215,325 L390,325 L390,367 L215,367 L215,325 Z" /></clipPath>
+<path d="M224,326 C219.5820313,326 216,329.5820313 216,334 L216,357 C216,361.4179688 219.5820313,365 224,365 L380,365 C384.4179688,365 388,361.4179688 388,357 L388,334 C388,329.5820313 384.4179688,326 380,326 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip7)" />
+<text x="230" y="348" style="font:13px Open Sans">notifications.php</text>
+<clipPath id="clip8"><path d="M30,409 L580,409 L580,566 L30,566 L30,409 Z" /></clipPath>
+<path d="M39,410 C34.5820313,410 31,413.5820313 31,418 L31,556 C31,560.4179688 34.5820313,564 39,564 L570,564 C574.4179688,564 578,560.4179688 578,556 L578,418 C578,413.5820313 574.4179688,410 570,410 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip8)" />
+<text x="45" y="432" style="font:13px Open Sans">notifications_content()</text>
+<text x="45" y="455" style="font:13px Open Sans">-----------------------------------------</text>
+<text x="45" y="501" style="font:13px Open Sans">- This is the page where Karen see Bobs friendship request</text>
+<text x="45" y="524" style="font:13px Open Sans">- the submit form redirects to Karens local dfrn_confirm page </text>
+<text x="45" y="547" style="font:13px Open Sans">($dfrn_id, $contact_id, $intro_id are submitted)</text>
+<clipPath id="clip9"><path d="M219,640 L399,640 L399,682 L219,682 L219,640 Z" /></clipPath>
+<path d="M228,641 C223.5820313,641 220,644.5820313 220,649 L220,672 C220,676.4179688 223.5820313,680 228,680 L389,680 C393.4179688,680 397,676.4179688 397,672 L397,649 C397,644.5820313 393.4179688,641 389,641 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip9)" />
+<text x="234" y="663" style="font:13px Open Sans">dfrn_confirm.php</text>
+<clipPath id="clip10"><path d="M14,698 L594,698 L594,1798 L14,1798 L14,698 Z" /></clipPath>
+<path d="M23,699 C18.5820313,699 15,702.5820313 15,707 L15,1788 C15,1792.4179688 18.5820313,1796 23,1796 L584,1796 C588.4179688,1796 592,1792.4179688 592,1788 L592,707 C592,702.5820313 588.4179688,699 584,699 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip10)" />
+<text x="29" y="721" style="font:13px Open Sans">dfrn_confirm_post()</text>
+<text x="29" y="744" style="font:13px Open Sans">SCENARIO 1 ( no $_POST['source_url'] available)</text>
+<text x="29" y="767" style="font:13px Open Sans">--------------------------------------------------------------------------------</text>
+<text x="29" y="813" style="font:13px Open Sans">- contact data come either form $handsfree (if autoconfirm) or </text>
+<text x="29" y="836" style="font:13px Open Sans">from $_POST</text>
+<text x="29" y="882" style="font:13px Open Sans">- get all data about Karen form the user table</text>
+<text x="29" y="928" style="font:13px Open Sans">[Note: Bob have been issued an ID (contact issue-id) when he first </text>
+<text x="29" y="951" style="font:13px Open Sans">requested the friendship. Locate Bobs contact record. At this </text>
+<text x="29" y="974" style="font:13px Open Sans">time, his record will have both pending and blocked set to 1. </text>
+<text x="29" y="997" style="font:13px Open Sans">There won't be any dfrn_id if this is a network follower, so use </text>
+<text x="29" y="1020" style="font:13px Open Sans">the contact_id instead]</text>
+<text x="29" y="1066" style="font:13px Open Sans">- search for Bob in the contact table by contact_id, dfrn_id and </text>
+<text x="29" y="1089" style="font:13px Open Sans">issued-id not empty (for the uid -&gt; Karens user id)</text>
+<text x="29" y="1135" style="font:13px Open Sans">- if network = dfrn </text>
+<text x="29" y="1158" style="font:13px Open Sans">  -&gt; create a new keypair (prvkey &amp; pubkey) and update the </text>
+<text x="29" y="1181" style="font:13px Open Sans">contact</text>
+<text x="29" y="1227" style="font:13px Open Sans">[Note: Generate a key pair for all further communications with </text>
+<text x="29" y="1250" style="font:13px Open Sans">this person. We have a keypair for every contact, and a site key </text>
+<text x="29" y="1273" style="font:13px Open Sans">for unknown people. This provides a means to carry on </text>
+<text x="29" y="1296" style="font:13px Open Sans">relationships with other people any single key is compromised. It </text>
+<text x="29" y="1319" style="font:13px Open Sans">is a robust key. We're much more worried about key leakage </text>
+<text x="29" y="1342" style="font:13px Open Sans">than anybody cracking it.]</text>
+<text x="29" y="1388" style="font:13px Open Sans">     -&gt; update Bobs contact record (in the contact table) with the </text>
+<text x="29" y="1411" style="font:13px Open Sans">generated prvkey</text>
+<text x="29" y="1457" style="font:13px Open Sans">  -&gt; encrypting the dfrn_id with Karens prvkey (Bob can decrypt it </text>
+<text x="29" y="1480" style="font:13px Open Sans">on the other and with Karens site-pubkey) and add it to the </text>
+<text x="29" y="1503" style="font:13px Open Sans">transmit params.</text>
+<text x="29" y="1549" style="font:13px Open Sans">     -&gt; encrypting Karens profile url with Bobs site-pubkey (Bob </text>
+<text x="29" y="1572" style="font:13px Open Sans">can decrypt it with his own private key)  and add it to the </text>
+<text x="29" y="1595" style="font:13px Open Sans">transmit params.</text>
+<text x="29" y="1641" style="font:13px Open Sans">     -&gt; add the above generated public key to params which </text>
+<text x="29" y="1664" style="font:13px Open Sans">getting transmitted (if $aes_allow -&gt; encrypt the the public key)</text>
+<text x="29" y="1710" style="font:13px Open Sans">     -&gt; add duplex state and page-flags to the params</text>
+<text x="29" y="1756" style="font:13px Open Sans">  -&gt; send params to Bobs dfrn_confirm page ($res = </text>
+<text x="29" y="1779" style="font:13px Open Sans">post_url($dfrn_confirm,$params);</text>
+<clipPath id="clip11"><path d="M1041,1319 L1619,1319 L1619,1913 L1041,1913 L1041,1319 Z" /></clipPath>
+<path d="M1050,1320 C1045.5820313,1320 1042,1323.5820313 1042,1328 L1042,1903 C1042,1907.4179688 1045.5820313,1911 1050,1911 L1609,1911 C1613.4179688,1911 1617,1907.4179688 1617,1903 L1617,1328 C1617,1323.5820313 1613.4179688,1320 1609,1320 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip11)" />
+<text x="1055" y="1342" style="font:13px Open Sans">dfrn_confirm_post()</text>
+<text x="1055" y="1365" style="font:13px Open Sans">SCENARIO 2 ( $_POST['source_url'] is available)</text>
+<text x="1055" y="1388" style="font:13px Open Sans">------------------------------------------------------------------------</text>
+<text x="1055" y="1434" style="font:13px Open Sans">- get all data about Bob from the user table (prvkey and uid form </text>
+<text x="1055" y="1457" style="font:13px Open Sans">Bob )</text>
+<text x="1055" y="1503" style="font:13px Open Sans">- decrypt the transmitted source_url  (profile url) with Bobs </text>
+<text x="1055" y="1526" style="font:13px Open Sans">prvkey</text>
+<text x="1055" y="1572" style="font:13px Open Sans">- get data of Karen from contact table by her source_url (and by </text>
+<text x="1055" y="1595" style="font:13px Open Sans">her user id)</text>
+<text x="1055" y="1641" style="font:13px Open Sans">- decrypt the dfrn_id sent by Karen with Karens site-pubkey </text>
+<text x="1055" y="1664" style="font:13px Open Sans">(taken from contact table)</text>
+<text x="1055" y="1710" style="font:13px Open Sans">- if possible decrpyt the pubkey sent by Karen with the prvkey of </text>
+<text x="1055" y="1733" style="font:13px Open Sans">Bob (taken from user table) -&gt; if this is not possible use the raw </text>
+<text x="1055" y="1756" style="font:13px Open Sans">pubkey</text>
+<text x="1055" y="1802" style="font:13px Open Sans">- search if the dfrn_id is already present in the contact table (if it </text>
+<text x="1055" y="1825" style="font:13px Open Sans">is prensent it is a duplicate)</text>
+<text x="1055" y="1871" style="font:13px Open Sans">- update dfrn-id and pubkey for Karens contact entry in the </text>
+<text x="1055" y="1894" style="font:13px Open Sans">contact table</text>
+<clipPath id="clip12"><path d="M42,1841 L559,1841 L559,1906 L42,1906 L42,1841 Z" /></clipPath>
+<path d="M51,1842 C46.5820313,1842 43,1845.5820313 43,1850 L43,1896 C43,1900.4179688 46.5820313,1904 51,1904 L549,1904 C553.4179688,1904 557,1900.4179688 557,1896 L557,1850 C557,1845.5820313 553.4179688,1842 549,1842 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip12)" />
+<text x="57" y="1864" style="font:13px Open Sans"> -&gt; set the relation for the contact and set pending = 0 and </text>
+<text x="57" y="1887" style="font:13px Open Sans">blocked = 0</text>
+<clipPath id="clip13"><path d="M1128,1950 L1541,1950 L1541,2061 L1128,2061 L1128,1950 Z" /></clipPath>
+<path d="M1137,1951 C1132.5820313,1951 1129,1954.5820313 1129,1959 L1129,2051 C1129,2055.4179688 1132.5820313,2059 1137,2059 L1531,2059 C1535.4179688,2059 1539,2055.4179688 1539,2051 L1539,1959 C1539,1954.5820313 1535.4179688,1951 1531,1951 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip13)" />
+<text x="1142" y="1973" style="font:13px Open Sans">- update the relationship of the contact Karen</text>
+<text x="1142" y="2019" style="font:13px Open Sans">-&gt; if duplex delete the issued-id</text>
+<text x="1142" y="2042" style="font:13px Open Sans">-&gt; set blocked = 0 and pending = 0</text>
+<clipPath id="clip14"><path d="M1241,2117 L1428,2117 L1428,2159 L1241,2159 L1241,2117 Z" /></clipPath>
+<path d="M1250,2118 C1245.5820313,2118 1242,2121.5820313 1242,2126 L1242,2149 C1242,2153.4179688 1245.5820313,2157 1250,2157 L1418,2157 C1422.4179688,2157 1426,2153.4179688 1426,2149 L1426,2126 C1426,2121.5820313 1422.4179688,2118 1418,2118 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip14)" />
+<text x="1255" y="2140" style="font:13px Open Sans">send a notification</text>
+<clipPath id="clip15"><path d="M190,1937 L410,1937 L410,1979 L190,1979 L190,1937 Z" /></clipPath>
+<path d="M199,1938 C194.5820313,1938 191,1941.5820313 191,1946 L191,1969 C191,1973.4179688 194.5820313,1977 199,1977 L400,1977 C404.4179688,1977 408,1973.4179688 408,1969 L408,1946 C408,1941.5820313 404.4179688,1938 400,1938 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip15)" />
+<text x="205" y="1960" style="font:13px Open Sans">delete the intro of Bob</text>
+<clipPath id="clip16"><path d="M156,14 L512,14 L512,125 L156,125 L156,14 Z" /></clipPath>
+<path d="M165,15 C160.5820313,15 157,18.5820313 157,23 L157,115 C157,119.4179688 160.5820313,123 165,123 L502,123 C506.4179688,123 510,119.4179688 510,115 L510,23 C510,18.5820313 506.4179688,15 502,15 Z" style="fill:rgb(255,255,255);stroke:none" clip-path="url(#clip16)" />
+<text x="171" y="38" style="font:13px Open Sans">Note: this chart respects only dfrn </text>
+<text x="171" y="61" style="font:13px Open Sans">contacts and focuses on key exchange </text>
+<text x="171" y="84" style="font:13px Open Sans">(for other areas it might be very </text>
+<text x="171" y="106" style="font:13px Open Sans">incomplete)</text>
+<clipPath id="clip17"><path d="M266,361 L341,361 L341,414 L266,414 L266,361 Z" /></clipPath>
+<path d="M302.4140625,365 L303.1328125,410" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip17)" />
+<clipPath id="clip18"><path d="M266,361 L341,361 L341,414 L266,414 L266,361 Z" /></clipPath>
+<path d="M297.9960938,401.421875 L303.1328125,410 L307.9960938,401.2617188 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip18)" />
+<clipPath id="clip19"><path d="M266,361 L341,361 L341,414 L266,414 L266,361 Z" /></clipPath>
+<path d="M297.9960938,401.421875 L303.1328125,410 L307.9960938,401.2617188 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip19)" />
+<clipPath id="clip20"><path d="M271,676 L346,676 L346,703 L271,703 L271,676 Z" /></clipPath>
+<path d="M308.3515625,680 L308.6445313,699" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip20)" />
+<clipPath id="clip21"><path d="M271,676 L346,676 L346,703 L271,703 L271,676 Z" /></clipPath>
+<path d="M303.5117188,690.4179688 L308.6445313,699 L313.5078125,690.265625 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip21)" />
+<clipPath id="clip22"><path d="M271,676 L346,676 L346,703 L271,703 L271,676 Z" /></clipPath>
+<path d="M303.5117188,690.4179688 L308.6445313,699 L313.5078125,690.265625 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip22)" />
+<clipPath id="clip23"><path d="M270,560 L345,560 L345,645 L270,645 L270,560 Z" /></clipPath>
+<path d="M306.4921875,564 L308.1054688,641" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip23)" />
+<clipPath id="clip24"><path d="M270,560 L345,560 L345,645 L270,645 L270,560 Z" /></clipPath>
+<path d="M302.9257813,632.4453125 L308.1054688,641 L312.9257813,632.2382813 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip24)" />
+<clipPath id="clip25"><path d="M270,560 L345,560 L345,645 L270,645 L270,560 Z" /></clipPath>
+<path d="M302.9257813,632.4453125 L308.1054688,641 L312.9257813,632.2382813 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip25)" />
+<clipPath id="clip26"><path d="M588,1338 L1046,1338 L1046,1770 L588,1770 L588,1338 Z" /></clipPath>
+<path d="M592,1766.2265625 L1042,1342.65625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip26)" />
+<clipPath id="clip27"><path d="M588,1338 L1046,1338 L1046,1770 L588,1770 L588,1338 Z" /></clipPath>
+<path d="M1039.1210938,1352.2304688 L1042,1342.65625 L1032.265625,1344.9492188 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip27)" />
+<clipPath id="clip28"><path d="M588,1338 L1046,1338 L1046,1770 L588,1770 L588,1338 Z" /></clipPath>
+<path d="M1039.1210938,1352.2304688 L1042,1342.65625 L1032.265625,1344.9492188 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip28)" />
+<clipPath id="clip29"><path d="M263,1792 L338,1792 L338,1846 L263,1846 L263,1792 Z" /></clipPath>
+<path d="M300.4296875,1796 L300.1992188,1842" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip29)" />
+<clipPath id="clip30"><path d="M263,1792 L338,1792 L338,1846 L263,1846 L263,1792 Z" /></clipPath>
+<path d="M295.2421875,1833.3164063 L300.1992188,1842 L305.2421875,1833.3632813 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip30)" />
+<clipPath id="clip31"><path d="M263,1792 L338,1792 L338,1846 L263,1846 L263,1792 Z" /></clipPath>
+<path d="M295.2421875,1833.3164063 L300.1992188,1842 L305.2421875,1833.3632813 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip31)" />
+<clipPath id="clip32"><path d="M1295,1907 L1370,1907 L1370,1955 L1295,1955 L1295,1907 Z" /></clipPath>
+<path d="M1332.9140625,1911 L1333.4453125,1951" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip32)" />
+<clipPath id="clip33"><path d="M1295,1907 L1370,1907 L1370,1955 L1295,1955 L1295,1907 Z" /></clipPath>
+<path d="M1328.3320313,1942.40625 L1333.4453125,1951 L1338.328125,1942.2734375 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip33)" />
+<clipPath id="clip34"><path d="M1295,1907 L1370,1907 L1370,1955 L1295,1955 L1295,1907 Z" /></clipPath>
+<path d="M1328.3320313,1942.40625 L1333.4453125,1951 L1338.328125,1942.2734375 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip34)" />
+<clipPath id="clip35"><path d="M1296,2055 L1371,2055 L1371,2122 L1296,2122 L1296,2055 Z" /></clipPath>
+<path d="M1334,2059 L1334,2118" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip35)" />
+<clipPath id="clip36"><path d="M1296,2055 L1371,2055 L1371,2122 L1296,2122 L1296,2055 Z" /></clipPath>
+<path d="M1329,2109.3398438 L1334,2118 L1339,2109.3398438 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip36)" />
+<clipPath id="clip37"><path d="M1296,2055 L1371,2055 L1371,2122 L1296,2122 L1296,2055 Z" /></clipPath>
+<path d="M1329,2109.3398438 L1334,2118 L1339,2109.3398438 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip37)" />
+<clipPath id="clip38"><path d="M263,1900 L338,1900 L338,1942 L263,1942 L263,1900 Z" /></clipPath>
+<path d="M300,1904 L299.6171875,1938" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip38)" />
+<clipPath id="clip39"><path d="M263,1900 L338,1900 L338,1942 L263,1942 L263,1900 Z" /></clipPath>
+<path d="M294.7148438,1929.2851563 L299.6171875,1938 L304.7148438,1929.3984375 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip39)" />
+<clipPath id="clip40"><path d="M263,1900 L338,1900 L338,1942 L263,1942 L263,1900 Z" /></clipPath>
+<path d="M294.7148438,1929.2851563 L299.6171875,1938 L304.7148438,1929.3984375 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip40)" />
+</svg>
diff --git a/spec/dfrn2_contact_request.png b/spec/dfrn2_contact_request.png
new file mode 100644 (file)
index 0000000..cf60094
Binary files /dev/null and b/spec/dfrn2_contact_request.png differ
diff --git a/spec/dfrn2_contact_request.svg b/spec/dfrn2_contact_request.svg
new file mode 100644 (file)
index 0000000..d813234
--- /dev/null
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="1458" height="2526" viewBox="0 0 1458 2526">
+<style type="text/css"><![CDATA[
+text { font:12px Dialog; }
+]]></style>
+<rect x="-485" y="-485" width="2428" height="3496" style="fill:rgb(255,255,255);stroke:none" />
+<clipPath id="clip1"><path d="M468,32 L867,32 L867,101 L468,101 L468,32 Z" /></clipPath>
+<path d="M470,34 L470,98 L864,98 L864,34 Z" style="fill:rgb(202,221,254);stroke:none" clip-path="url(#clip1)" />
+<clipPath id="clip2"><path d="M468,32 L867,32 L867,101 L468,101 L468,32 Z" /></clipPath>
+<path d="M470,34 L470,98 L864,98 L864,34 Z" style="fill:none;stroke:rgb(61,83,127)" clip-path="url(#clip2)" />
+<text x="503" y="71" style="font:18px Open Sans">Friendica - Contact request</text>
+<image x="0" y="0" width="834" height="74" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA0IAAABKCAYAAACW5eSEAAAEYElEQVR42u3dyW+VVRjAYRKNf4BSRFwwCImEQEAs2tpbCjIoIkJLC1KMgGAISlBQDGPgKhWQWKCATG3BtiiiRGIMCw0gaQspCGUokxJKyz+AsuiGvt7WIcatq9s8T/Iubr6czdn9cr7v3G7dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKBLi4j/NQAAAGkfQnkHrndPHGgqyam5cjE1bZ1z4GpjouZKsuOZEAIAALpUCD1fc2F6VsWFexnD58Xgov0xeevVmFR6JfJWHY2hi/dETlXT3UR101QhBAAAdIkQGrWvsShRdbl92LzD8djEszF8YVMU7WqJop0tUZiagu3NMXL1D5Fbfbl9VNWlIiEEAACkdQglKs5lJCov/pb9/tGYVHorxpfcjGm7W2L6npaYUd4aeWtuRL+ZjTFkflP0G1sZo6qbfs/+/EIPIQQAAKRvCO1pTA55a0dkL70W+WW349W9ralJRVBFa+Rvb46cVdej/+wL0XPK2XhkXEMMLF4fid3nS4QQAACQtiGUs/NcY9+RZfHMkiudr8LNKG+J4srWmLmvNcZtvBkjP7wReclr8UTxieg57lD0yV4RmSXfX00tf8gOAgAA6RlC2862Zb7dGJO3Nv/5OlxFa7y2vzVer7oTOWtvxMubf40Ri09G1pIvYumpulh25lTk7/rqfmp5LzsIAACkZwhtaWh7cf31f74LKu4MoTuRv6M5esz6OTKmnYin3zkUyxpSAbSpOp6du6Ezhgbk5ubaQQAAID1D6NPTjYn3jkT+9ttRtOt25wUJHSdChbtuRt/Zx+PJOdUxfl1NjF9dGbkLK+Kl5Lb44FRde/f+/Z+ygwAAQFqGUGJDfXLo3K0xJvlLDJp3KV7ZciuKy29FQWlD5G/6OlY01Mfcg0fizYPfxpSN+2JZ6vcL67bXp5Zn2EEAACAtQyj7k7oeOR/X3s1acCQeHncmBsxqjILN56Ow9HCsTEXPmBV7Ykb5NzH/8HedETT2o4q2xzMnD00tf9AOAgAAaRlCnadCH56c+lzyp/Y+OTtixLtNMSH5Yyw/XZuKoeroN3Fb5CzaGwWllZG7vLx90JzN8zoiyPXZAABAWodQ57dCa08UZq06dm/YG2WRveCzWHmmPsYuLY2Ja8piRUNdjFm7v23o/N2zUsse+HsNAABAWodQx+StOd49seZYSeaiL68WbKm53xFDy0/Xtk9IltU+OnzC4G5/nQQJIQAAoMuE0L8Cp+PPUnsNHD06t3vv3h23w2X8N4I65g/3mXiK17zpCgAAAABJRU5ErkJggg==" /><clipPath id="clip3"><path d="M1006,236 L1266,236 L1266,278 L1006,278 L1006,236 Z" /></clipPath>
+<path d="M1016,238 C1011.5820313,238 1008,241.5820313 1008,246 L1008,267 C1008,271.4179688 1011.5820313,275 1016,275 L1255,275 C1259.4179688,275 1263,271.4179688 1263,267 L1263,246 C1263,241.5820313 1259.4179688,238 1255,238 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip3)" />
+<clipPath id="clip4"><path d="M1006,236 L1266,236 L1266,278 L1006,278 L1006,236 Z" /></clipPath>
+<path d="M1016,238 C1011.5820313,238 1008,241.5820313 1008,246 L1008,267 C1008,271.4179688 1011.5820313,275 1016,275 L1255,275 C1259.4179688,275 1263,271.4179688 1263,267 L1263,246 C1263,241.5820313 1259.4179688,238 1255,238 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip4)" />
+<text x="1021" y="259" style="font:13px Tahoma">karenn@karenhompage.com</text>
+<image x="0" y="0" width="1252" height="265" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABOQAAAEJCAYAAAA0I/jnAAAIjElEQVR42u3d3ZPNdRzAcTMZf0Ah6cJDzGQMQ6Jse9aSh5LErl2ymhCNUUZRGo/DkQ2ZFos87S7ZVVIm0zQuapBhmSXWw3oqg13/gHKxN/bTOac0xt1hpqvXa+Zzceacz8338j2/3/m2agUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/ysiHmkAAAAAgCw8GNjyd19pm9jdUJpbc/Fcapozs/tSfaLmYjL9nSAHAAAAAI/g/rj2cs3ZCQMrz95p12969CreGWPWX4rRZRcjf/GB6DNnW+TuaridqG4YJ8gBAAAAwEO6F9YG76gvTuy60NJ3+r54atSp6DerIYq3NEbx5sYoSk3hxhsxaMnPkVd9oWXwrvPFghwAAAAAPIR0VEtUnm6XqDr3Z87HB2J02fUYUXotxm9tjAnbGmNiRVPkL70aXSfVR+8ZDdF1WFUMrm74K+ers+0FOQAAAADIUibIbatP9n5vU+TMuxwF5Tfjze1NqWmMiZVNUbDxRuQuvhLdppyNDmNPxRPD66JHycpIbD1TKsgBAAAAQJbSUS138+n6LoPK44W5FzOvqE6saIySqqaYtKMphq++FoOWX4385OV4puRwdBi+NzrnLIz+pT9dSq23cYIAAAAAkIVMkNtwqrn/+/UxZv2Nf15TrWyKt3Y2xdu7bkXusqvx+to/YsCcIzFw7tcx7/ixmH/yeBRs+fZuar2jEwQAAACALGSC3Lq65ldXXvnvf+NKMkHuVhRsuhHtJ/8W7cYfjuc/2Bvz645HwZrqeHHaqkyU656Xl+cEAQAAACALmSD3xYn6xEf7o2DjzSjecjNzkUP6CbmiLdeiy5RD8ezU6hixoiZGLKmKvFmV8VpyQ3xy/FhL227dnnOCAAAAAJCFzKUOq2qTfaatj6HJ36Pn9PPxxrrrUVJxPQrL6qJgzXexsK42pu3ZH+/u+SHGrt4R81OfX1mxsTa13s4JAgAAAEAW0kEu5/Nj7XM/O3p74Mz98fjwk9F9cn0Urj0TRWX7YlFdbQxduC0mVnwfM/b9mIlxwz6tbH66/5g+qfXWThAAAAAAspAOcpmn5JYfGfdS8teWzrmbYsCHDTEy+UssOHE0isqqo+uoDZE7e3sUllVF3oKKlp5T105PrbZO7wEAAAAAWbgX5DL/JbfscNHAxQfv9H2nPHJmfhmLTtbGsHllMWppeSysOxZDl+1s7jNj6+TU2mP3dgAAAACALNwf5NKTv/RQ28TSg6X9Z39zqXBdzd10lFtw4mjLyGT50Sf7jezV6t8n4wQ5AAAAAHgIDwa5+0Jbm9R07DFkSF7bTp3St6mmL3Bo/eDv/gYwZniKtpg81wAAAABJRU5ErkJggg==" /><clipPath id="clip5"><path d="M235,234 L425,234 L425,276 L235,276 L235,234 Z" /></clipPath>
+<path d="M245,236 C240.5820313,236 237,239.5820313 237,244 L237,265 C237,269.4179688 240.5820313,273 245,273 L414,273 C418.4179688,273 422,269.4179688 422,265 L422,244 C422,239.5820313 418.4179688,236 414,236 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip5)" />
+<clipPath id="clip6"><path d="M235,234 L425,234 L425,276 L235,276 L235,234 Z" /></clipPath>
+<path d="M245,236 C240.5820313,236 237,239.5820313 237,244 L237,265 C237,269.4179688 240.5820313,273 245,273 L414,273 C418.4179688,273 422,269.4179688 422,265 L422,244 C422,239.5820313 418.4179688,236 414,236 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip6)" />
+<text x="251" y="257" style="font:13px Tahoma">bob@example.com</text>
+<image x="0" y="0" width="411" height="263" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZsAAAEHCAYAAAB4POvAAAAFDElEQVR42u3c3ZOOZRzAcTM1/QG1K+nAS8xkDEOibPusl1glFYslqwnRGGUUpWExPLKhpsUir7tkV0mZTNM4qEHGLrPELtaiDHb9A8rBnthf9z5NTdPR4rDPZ+Y6euY6uU6+87vv67k7dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+H+LiPtaAHDXsRm693JWam9DSW7VxXPJasmsvY11qaqL6bbfxAaA+4rN81X1kweX19/OHjAr+hTujrEbGuOV0osxdOmh6Dd/e+TuabiVqmyYIDYA3FNshu2qK0ztudDaf9aBeGzM6RgwtyEKtzZF4ZammJis8Zuux5BlP0Ze5YXWYXvOF4oNAHcVm1T5mexUxbnfcz44lEwy12JUydWYtK0pJm9viik7m2Po8ivRfWpd9J3dEN1HVsSwyoY/cr6o7yg2ALQ/Ntvr0n3f3hw5Cy9FQdmNeG1Hc7KS0JQ3R0Ey0eQuvRw9ptdHp3Gn45H82uhVtDpS286WiA0A7Y5N7pYzdd2GlMUzCy5mHptN2dkURRXNMXVXc+SvvRpDVl6JoelL8UTR0eiUvz+65hTHwJIfGpPtDzlBANoXm42nWwa+UxdjN1z/69FZMtG8vrs53thzM3JXXImX1/0Wg+Yfi8ELvoyFJ6pj0akTUbD16zvJ9s5OEID2xWZ9bcuLqy//856mKBObm1Gw+Xp0nPZLZE86Gk+/uz8W1SaR+bQynp25JhOcnnl5eU4QgPbF5rOTdan3D0bBphtRuPVG5lJA22QzcevV6Db9SDw5ozJGraqKUcsqIm9uebyU3hgfnqhuzerR4yknCEC7YpNaU5PuN3NDjEj/Gr1nnY9X11+Lop3XYnxpbTLJfBPFtTUxc9/BeGvfdzFu7a5kwqmJF1Ztqkm2ZztBANoVm5xPqjvmfnz81uA5B+Ph/FPRc1pdjF93NiaWHoglSVhGFG9Ppp1vY/aB7zOhGflRecvjA8f2S7Y/6AQBaFdsMtPNymMTnkv/3No1d3MMeq8hRqd/isUnjyfBqYzuYzZG7rwdyaRTEXmLd7b2nrFuVltoXH0G4K5ik3l3s+LoxMFLD9/u/2ZZ5Mz5PJacSqaYhaUxZnlZFNdWx4gVu1v6zd42Ldn2gC8IAHBPscl8iHP5kazU8sMlA+d91Th+fdWdtuAkE07r6HTZ8UcHjO7z90QjNgDcc2z+FZG2P2x27jV8eF5Wly5tt86y/xuatvUnRFJ4iu/wPU8AAAAASUVORK5CYII=" /><clipPath id="clip7"><path d="M953,363 L1344,363 L1344,451 L953,451 L953,363 Z" /></clipPath>
+<path d="M962,364 C957.5820313,364 954,367.5820313 954,372 L954,441 C954,445.4179688 957.5820313,449 962,449 L1334,449 C1338.4179688,449 1342,445.4179688 1342,441 L1342,372 C1342,367.5820313 1338.4179688,364 1334,364 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip7)" />
+<text x="1073" y="386" style="font:13px Open Sans"> dfrn_request.php</text>
+<text x="1146" y="409" style="font:13px Open Sans">-</text>
+<text x="968" y="432" style="font:13px Open Sans">https://karenhompage/dfrn_request/karin</text>
+<clipPath id="clip8"><path d="M890,808 L1416,808 L1416,1448 L890,1448 L890,808 Z" /></clipPath>
+<path d="M899,809 C894.5820313,809 891,812.5820313 891,817 L891,1438 C891,1442.4179688 894.5820313,1446 899,1446 L1406,1446 C1410.4179688,1446 1414,1442.4179688 1414,1438 L1414,817 C1414,812.5820313 1410.4179688,809 1406,809 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip8)" />
+<text x="904" y="831" style="font:13px Open Sans">dfrn_request_post - SCENARIO 1</text>
+<text x="904" y="854" style="font:13px Open Sans">----------------------------------------------</text>
+<text x="904" y="900" style="font:13px Open Sans">- Cleanup old introductions that remain blocked + Cleanup </text>
+<text x="904" y="923" style="font:13px Open Sans">any old email intros - which will have a greater lifetime</text>
+<text x="904" y="969" style="font:13px Open Sans">- probe_url Bobs posted dfrn_url and get the network with </text>
+<text x="904" y="992" style="font:13px Open Sans">webfinger_dfrn</text>
+<text x="904" y="1038" style="font:13px Open Sans">- try to select all contact data of Bob (contact table) by the </text>
+<text x="904" y="1061" style="font:13px Open Sans">url ($_POST['dfrn_url] and profile uid ($a-&gt;profile['uid']) </text>
+<text x="904" y="1084" style="font:13px Open Sans">where self = 0 to look if this contact is already there (if </text>
+<text x="904" y="1107" style="font:13px Open Sans">issued-id or rel is already available return here because it </text>
+<text x="904" y="1130" style="font:13px Open Sans">seems that we are already connected)</text>
+<text x="904" y="1176" style="font:13px Open Sans">- create a issued-id with $issued_id = random_string();</text>
+<text x="904" y="1222" style="font:13px Open Sans">- if we already found a contact record above update the </text>
+<text x="904" y="1245" style="font:13px Open Sans">issued-id with the one we have created</text>
+<text x="904" y="1291" style="font:13px Open Sans">- otherwise if Bob is not already in the contact table scrape </text>
+<text x="904" y="1314" style="font:13px Open Sans">Bobs profile and create a new contact with this data (e.g. </text>
+<text x="904" y="1337" style="font:13px Open Sans">the scraped issued-id / profiles pubkey becomes contacts </text>
+<text x="904" y="1360" style="font:13px Open Sans">site-pubkey) in the contact table (blocked = 1, pending = 1)</text>
+<text x="904" y="1406" style="font:13px Open Sans">- select this created contact from contact table and create </text>
+<text x="904" y="1429" style="font:13px Open Sans">an intro in the intro table (blocked = 1)</text>
+<clipPath id="clip9"><path d="M925,693 L1374,693 L1374,735 L925,735 L925,693 Z" /></clipPath>
+<path d="M934,694 C929.5820313,694 926,697.5820313 926,702 L926,725 C926,729.4179688 929.5820313,733 934,733 L1364,733 C1368.4179688,733 1372,729.4179688 1372,725 L1372,702 C1372,697.5820313 1368.4179688,694 1364,694 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip9)" />
+<text x="939" y="716" style="font:13px Open Sans">$_POST['dfrn_url'] is transmited and is Bobs profile url</text>
+<clipPath id="clip10"><path d="M888,1557 L1418,1557 L1418,1852 L888,1852 L888,1557 Z" /></clipPath>
+<path d="M897,1558 C892.5820313,1558 889,1561.5820313 889,1566 L889,1842 C889,1846.4179688 892.5820313,1850 897,1850 L1408,1850 C1412.4179688,1850 1416,1846.4179688 1416,1842 L1416,1566 C1416,1561.5820313 1412.4179688,1558 1408,1558 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip10)" />
+<text x="902" y="1580" style="font:13px Open Sans">redirect to Bobs request page</text>
+<text x="902" y="1626" style="font:13px Open Sans">goaway($parms['dfrn-request'] . "?dfrn_url=$dfrn_url"</text>
+<text x="902" y="1649" style="font:13px Open Sans">                            . '&amp;dfrn_version=' . </text>
+<text x="902" y="1672" style="font:13px Open Sans">DFRN_PROTOCOL_VERSION</text>
+<text x="902" y="1695" style="font:13px Open Sans">                            . '&amp;confirm_key='  . $hash</text>
+<text x="902" y="1718" style="font:13px Open Sans">                            . (($aes_allow) ? "&amp;aes_allow=1" : "")</text>
+<text x="902" y="1741" style="font:13px Open Sans">                    );</text>
+<text x="902" y="1787" style="font:13px Open Sans">http://example.com/dfrn_request/bob?dfrn_url=6874747</text>
+<text x="902" y="1810" style="font:13px Open Sans">03a2f2f6b6172656e686f6d65706167652e636f6d2f70726f66</text>
+<text x="902" y="1833" style="font:13px Open Sans">696c652f6b6172656e&amp;aes_allow=1&amp;confirm_key=”ABC123”</text>
+<clipPath id="clip11"><path d="M287,1180 L464,1180 L464,1222 L287,1222 L287,1180 Z" /></clipPath>
+<path d="M296,1181 C291.5820313,1181 288,1184.5820313 288,1189 L288,1212 C288,1216.4179688 291.5820313,1220 296,1220 L454,1220 C458.4179688,1220 462,1216.4179688 462,1212 L462,1189 C462,1184.5820313 458.4179688,1181 454,1181 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip11)" />
+<text x="302" y="1203" style="font:13px Open Sans">dfrn_request.php</text>
+<clipPath id="clip12"><path d="M134,1399 L624,1399 L624,2315 L134,2315 L134,1399 Z" /></clipPath>
+<path d="M143,1400 C138.5820313,1400 135,1403.5820313 135,1408 L135,2305 C135,2309.4179688 138.5820313,2313 143,2313 L614,2313 C618.4179688,2313 622,2309.4179688 622,2305 L622,1408 C622,1403.5820313 618.4179688,1400 614,1400 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip12)" />
+<text x="149" y="1422" style="font:13px Open Sans">http://example.com/dfrn_request/bob?</text>
+<text x="149" y="1445" style="font:13px Open Sans">dfrn_url=</text>
+<text x="149" y="1468" style="font:13px Open Sans">687474703a2f2f6b6172656e686f6d65706167652e</text>
+<text x="149" y="1491" style="font:13px Open Sans">636f6d2f70726f66696c652f6b6172656e&amp;aes_allow=1&amp;</text>
+<text x="149" y="1514" style="font:13px Open Sans">confirm_key=”ABC123”</text>
+<text x="149" y="1560" style="font:13px Open Sans">dfrn_request_content()</text>
+<text x="149" y="1583" style="font:13px Open Sans">------------------------------------------</text>
+<text x="149" y="1606" style="font:13px Open Sans">- copy the posted parameters (dfrn_url, key and so on) </text>
+<text x="149" y="1629" style="font:13px Open Sans">to $_POST</text>
+<text x="149" y="1698" style="font:13px Open Sans"> dfrn_request_post() - SCENARIO 2 </text>
+<text x="149" y="1721" style="font:13px Open Sans">($_POST['localconfirm'] == 1)</text>
+<text x="149" y="1744" style="font:13px Open Sans">-----------------------------------------------------------------------</text>
+<text x="149" y="1767" style="font:13px Open Sans">- if(local_user() &amp;&amp; ($a-&gt;user['nickname'] == $a-</text>
+<text x="149" y="1790" style="font:13px Open Sans">&gt;argv[1]) &amp;&amp; (x($_POST,'dfrn_url')))</text>
+<text x="149" y="1813" style="font:13px Open Sans">-&gt;</text>
+<text x="149" y="1859" style="font:13px Open Sans">- $confirm_key comes from $_POST</text>
+<text x="149" y="1905" style="font:13px Open Sans">- get data for contact Karen (contact table) by </text>
+<text x="149" y="1928" style="font:13px Open Sans">$dfrn_url (contacts url and nurl) -&gt; if contact Karen </text>
+<text x="149" y="1951" style="font:13px Open Sans">does already have a dfrn-id Bob seems already </text>
+<text x="149" y="1974" style="font:13px Open Sans">connected with Karen (abort here)</text>
+<text x="149" y="2020" style="font:13px Open Sans">- if this contact (Karen) isn't available in the contact </text>
+<text x="149" y="2043" style="font:13px Open Sans">tabel, scrape Karens profile page to pick up the dfrn </text>
+<text x="149" y="2066" style="font:13px Open Sans">links, key, fn, and photo</text>
+<text x="149" y="2112" style="font:13px Open Sans">- create a contact for Karen in the contact table with </text>
+<text x="149" y="2135" style="font:13px Open Sans">the scraped data with blocked = 1 and pending = 1 </text>
+<text x="149" y="2158" style="font:13px Open Sans">(Karens pubkey becomes the contact site-pubkey)</text>
+<text x="149" y="2204" style="font:13px Open Sans">- fetch_url($dfrn_request . '?confirm_key=' . </text>
+<text x="149" y="2227" style="font:13px Open Sans">$confirm_key);</text>
+<text x="149" y="2273" style="font:13px Open Sans">- fetch_url(http://karenhomepage.com/dfrn_request?</text>
+<text x="149" y="2296" style="font:13px Open Sans">confirm_key=”ABC123”)</text>
+<clipPath id="clip13"><path d="M1061,2027 L1238,2027 L1238,2069 L1061,2069 L1061,2027 Z" /></clipPath>
+<path d="M1070,2028 C1065.5820313,2028 1062,2031.5820313 1062,2036 L1062,2059 C1062,2063.4179688 1065.5820313,2067 1070,2067 L1228,2067 C1232.4179688,2067 1236,2063.4179688 1236,2059 L1236,2036 C1236,2031.5820313 1232.4179688,2028 1228,2028 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip13)" />
+<text x="1075" y="2050" style="font:13px Open Sans">dfrn_request.php</text>
+<clipPath id="clip14"><path d="M857,2205 L1444,2205 L1444,2454 L857,2454 L857,2205 Z" /></clipPath>
+<path d="M866,2206 C861.5820313,2206 858,2209.5820313 858,2214 L858,2444 C858,2448.4179688 861.5820313,2452 866,2452 L1434,2452 C1438.4179688,2452 1442,2448.4179688 1442,2444 L1442,2214 C1442,2209.5820313 1438.4179688,2206 1434,2206 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip14)" />
+<text x="871" y="2228" style="font:13px Open Sans">http://karenhomepage.com/dfrn_request?confirm_key=”ABC123”</text>
+<text x="871" y="2274" style="font:13px Open Sans">dfrn_request_content() -</text>
+<text x="871" y="2297" style="font:13px Open Sans">(elseif((x($_GET,'confirm_key')) &amp;&amp; strlen($_GET['confirm_key'])) )</text>
+<text x="871" y="2320" style="font:13px Open Sans">----------------------------------------------------------------------------------------------</text>
+<text x="871" y="2366" style="font:13px Open Sans">- select the intro by confirm_key (intro table) -&gt; get contact id</text>
+<text x="871" y="2389" style="font:13px Open Sans">- use the intro contact id to get the contact in the contact table</text>
+<text x="871" y="2412" style="font:13px Open Sans">- build a notification package ( notification(array.....) )</text>
+<text x="871" y="2435" style="font:13px Open Sans">- update intro in intro table (blocked = 0)</text>
+<clipPath id="clip15"><path d="M227,2424 L531,2424 L531,2512 L227,2512 L227,2424 Z" /></clipPath>
+<path d="M236,2425 C231.5820313,2425 228,2428.5820313 228,2433 L228,2502 C228,2506.4179688 231.5820313,2510 236,2510 L521,2510 C525.4179688,2510 529,2506.4179688 529,2502 L529,2433 C529,2428.5820313 525.4179688,2425 521,2425 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip15)" />
+<text x="242" y="2447" style="font:13px Open Sans">Bob stays on his Friendica server</text>
+<text x="242" y="2493" style="font:13px Open Sans">- goaway($forwardurl);</text>
+<clipPath id="clip16"><path d="M14,14 L370,14 L370,125 L14,125 L14,14 Z" /></clipPath>
+<path d="M23,15 C18.5820313,15 15,18.5820313 15,23 L15,115 C15,119.4179688 18.5820313,123 23,123 L360,123 C364.4179688,123 368,119.4179688 368,115 L368,23 C368,18.5820313 364.4179688,15 360,15 Z" style="fill:rgb(255,255,255);stroke:none" clip-path="url(#clip16)" />
+<text x="29" y="38" style="font:13px Open Sans">Note: this chart respects only dfrn </text>
+<text x="29" y="61" style="font:13px Open Sans">contacts and focuses on key exchange </text>
+<text x="29" y="83" style="font:13px Open Sans">(for other areas it might be very </text>
+<text x="29" y="106" style="font:13px Open Sans">incomplete)</text>
+<clipPath id="clip17"><path d="M871,491 L1431,491 L1431,648 L871,648 L871,491 Z" /></clipPath>
+<path d="M880,492 C875.5820313,492 872,495.5820313 872,500 L872,638 C872,642.4179688 875.5820313,646 880,646 L1421,646 C1425.4179688,646 1429,642.4179688 1429,638 L1429,500 C1429,495.5820313 1425.4179688,492 1421,492 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip17)" />
+<text x="885" y="514" style="font:13px Open Sans">dfrn_request_content()</text>
+<text x="885" y="537" style="font:13px Open Sans">------------------------------------</text>
+<text x="885" y="583" style="font:13px Open Sans">- the page for the on Katrins server where Bob do a connection </text>
+<text x="885" y="606" style="font:13px Open Sans">request</text>
+<text x="885" y="629" style="font:13px Open Sans">- the form transmit on submit Bobs profile url as dfrn_url</text>
+<clipPath id="clip18"><path d="M402,267 L974,267 L974,313 L402,313 L402,267 Z" /></clipPath>
+<path d="M422,271.734375 L954,370.5703125" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip18)" />
+<clipPath id="clip19"><path d="M402,329 L974,329 L974,377 L402,377 L402,329 Z" /></clipPath>
+<path d="M422,271.734375 L954,370.5703125" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip19)" />
+<clipPath id="clip20"><path d="M402,311 L974,311 L974,331 L402,331 L402,311 Z" /></clipPath>
+<path d="M422,271.734375 L954,370.5703125" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip20)" />
+<clipPath id="clip21"><path d="M402,267 L974,267 L974,377 L402,377 L402,267 Z" /></clipPath>
+<path d="M944.5703125,373.9023438 L954,370.5703125 L946.3984375,364.0703125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip21)" />
+<clipPath id="clip22"><path d="M402,267 L974,267 L974,377 L402,377 L402,267 Z" /></clipPath>
+<path d="M944.5703125,373.9023438 L954,370.5703125 L946.3984375,364.0703125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip22)" />
+<text x="405" y="323" style="font:10px Georgia">bob wants to make a request and is directed from karens profile page to karens dfrn-request page</text>
+<clipPath id="clip23"><path d="M1111,729 L1186,729 L1186,813 L1111,813 L1111,729 Z" /></clipPath>
+<path d="M1149.1875,733 L1149.4335938,763.3984375 L1149.5585938,778.6015625 L1149.8046875,809" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip23)" />
+<clipPath id="clip24"><path d="M1111,729 L1186,729 L1186,813 L1111,813 L1111,729 Z" /></clipPath>
+<path d="M1144.734375,800.3789063 L1149.8046875,809 L1154.734375,800.3007813 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip24)" />
+<clipPath id="clip25"><path d="M1111,729 L1186,729 L1186,813 L1111,813 L1111,729 Z" /></clipPath>
+<path d="M1144.734375,800.3789063 L1149.8046875,809 L1154.734375,800.3007813 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip25)" />
+<clipPath id="clip26"><path d="M1115,1442 L1190,1442 L1190,1562 L1115,1562 L1115,1442 Z" /></clipPath>
+<path d="M1152.7773438,1446 L1152.625,1558" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip26)" />
+<clipPath id="clip27"><path d="M1115,1442 L1190,1442 L1190,1562 L1115,1562 L1115,1442 Z" /></clipPath>
+<path d="M1147.6367188,1549.3320313 L1152.625,1558 L1157.6367188,1549.3476563 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip27)" />
+<clipPath id="clip28"><path d="M1115,1442 L1190,1442 L1190,1562 L1115,1562 L1115,1442 Z" /></clipPath>
+<path d="M1147.6367188,1549.3320313 L1152.625,1558 L1157.6367188,1549.3476563 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip28)" />
+<clipPath id="clip29"><path d="M458,1201 L893,1201 L893,1375 L458,1375 L458,1201 Z" /></clipPath>
+<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip29)" />
+<clipPath id="clip30"><path d="M458,1391 L893,1391 L893,1565 L458,1565 L458,1391 Z" /></clipPath>
+<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip30)" />
+<clipPath id="clip31"><path d="M458,1373 L575,1373 L575,1393 L458,1393 L458,1373 Z" /></clipPath>
+<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip31)" />
+<clipPath id="clip32"><path d="M776,1373 L893,1373 L893,1393 L776,1393 L776,1373 Z" /></clipPath>
+<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip32)" />
+<clipPath id="clip33"><path d="M573,1373 L778,1373 L778,1393 L573,1393 L573,1373 Z" /></clipPath>
+<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip33)" />
+<clipPath id="clip34"><path d="M458,1201 L893,1201 L893,1565 L458,1565 L458,1201 Z" /></clipPath>
+<path d="M471.8515625,1207.0664063 L462,1205.3515625 L465.4414063,1214.7421875 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip34)" />
+<clipPath id="clip35"><path d="M458,1201 L893,1201 L893,1565 L458,1565 L458,1201 Z" /></clipPath>
+<path d="M471.8515625,1207.0664063 L462,1205.3515625 L465.4414063,1214.7421875 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip35)" />
+<text x="576" y="1385" style="font:10px Georgia">redirict to bobs dfrn_request page</text>
+<clipPath id="clip36"><path d="M339,1216 L414,1216 L414,1404 L339,1404 L339,1216 Z" /></clipPath>
+<path d="M375.1171875,1220 L376.0625,1400" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip36)" />
+<clipPath id="clip37"><path d="M339,1216 L414,1216 L414,1404 L339,1404 L339,1216 Z" /></clipPath>
+<path d="M371.015625,1391.3671875 L376.0625,1400 L381.015625,1391.3125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip37)" />
+<clipPath id="clip38"><path d="M339,1216 L414,1216 L414,1404 L339,1404 L339,1216 Z" /></clipPath>
+<path d="M371.015625,1391.3671875 L376.0625,1400 L381.015625,1391.3125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip38)" />
+<clipPath id="clip39"><path d="M618,2024 L1072,2024 L1072,2158 L618,2158 L618,2024 Z" /></clipPath>
+<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip39)" />
+<clipPath id="clip40"><path d="M618,2174 L1072,2174 L1072,2309 L618,2309 L618,2174 Z" /></clipPath>
+<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip40)" />
+<clipPath id="clip41"><path d="M618,2156 L650,2156 L650,2176 L618,2176 L618,2156 Z" /></clipPath>
+<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip41)" />
+<clipPath id="clip42"><path d="M1041,2156 L1072,2156 L1072,2176 L1041,2176 L1041,2156 Z" /></clipPath>
+<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip42)" />
+<clipPath id="clip43"><path d="M648,2156 L1043,2156 L1043,2176 L648,2176 L648,2156 Z" /></clipPath>
+<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip43)" />
+<clipPath id="clip44"><path d="M618,2024 L1072,2024 L1072,2309 L618,2309 L618,2024 Z" /></clipPath>
+<path d="M1063.4804688,2036.8164063 L1068.1992188,2028 L1058.2070313,2028.3203125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip44)" />
+<clipPath id="clip45"><path d="M618,2024 L1072,2024 L1072,2309 L618,2309 L618,2024 Z" /></clipPath>
+<path d="M1063.4804688,2036.8164063 L1068.1992188,2028 L1058.2070313,2028.3203125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip45)" />
+<text x="651" y="2168" style="font:10px Georgia">http://karenhomepage.com/dfrn_request?confirm_key=”ABC123”</text>
+<clipPath id="clip46"><path d="M1111,2063 L1186,2063 L1186,2210 L1111,2210 L1111,2063 Z" /></clipPath>
+<path d="M1149.0703125,2067 L1149.5625,2206" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip46)" />
+<clipPath id="clip47"><path d="M1111,2063 L1186,2063 L1186,2210 L1111,2210 L1111,2063 Z" /></clipPath>
+<path d="M1144.53125,2197.359375 L1149.5625,2206 L1154.53125,2197.3203125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip47)" />
+<clipPath id="clip48"><path d="M1111,2063 L1186,2063 L1186,2210 L1111,2210 L1111,2063 Z" /></clipPath>
+<path d="M1144.53125,2197.359375 L1149.5625,2206 L1154.53125,2197.3203125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip48)" />
+<clipPath id="clip49"><path d="M342,2309 L417,2309 L417,2429 L342,2429 L342,2309 Z" /></clipPath>
+<path d="M378.875,2313 L378.5351563,2425" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip49)" />
+<clipPath id="clip50"><path d="M342,2309 L417,2309 L417,2429 L342,2429 L342,2309 Z" /></clipPath>
+<path d="M373.5625,2416.3242188 L378.5351563,2425 L383.5625,2416.3554688 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip50)" />
+<clipPath id="clip51"><path d="M342,2309 L417,2309 L417,2429 L342,2429 L342,2309 Z" /></clipPath>
+<path d="M373.5625,2416.3242188 L378.5351563,2425 L383.5625,2416.3554688 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip51)" />
+<clipPath id="clip52"><path d="M1111,445 L1186,445 L1186,496 L1111,496 L1111,445 Z" /></clipPath>
+<path d="M1148.7851563,449 L1149.3125,492" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip52)" />
+<clipPath id="clip53"><path d="M1111,445 L1186,445 L1186,496 L1111,496 L1111,445 Z" /></clipPath>
+<path d="M1144.2070313,483.4023438 L1149.3125,492 L1154.2070313,483.2773438 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip53)" />
+<clipPath id="clip54"><path d="M1111,445 L1186,445 L1186,496 L1111,496 L1111,445 Z" /></clipPath>
+<path d="M1144.2070313,483.4023438 L1149.3125,492 L1154.2070313,483.2773438 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip54)" />
+<clipPath id="clip55"><path d="M1026,642 L1272,642 L1272,662 L1026,662 L1026,642 Z" /></clipPath>
+<path d="M1149.703125,646 L1149.2695313,694" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip55)" />
+<clipPath id="clip56"><path d="M1026,678 L1272,678 L1272,698 L1026,698 L1026,678 Z" /></clipPath>
+<path d="M1149.703125,646 L1149.2695313,694" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip56)" />
+<clipPath id="clip57"><path d="M1026,660 L1272,660 L1272,680 L1026,680 L1026,660 Z" /></clipPath>
+<path d="M1149.703125,646 L1149.2695313,694" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip57)" />
+<clipPath id="clip58"><path d="M1026,642 L1272,642 L1272,698 L1026,698 L1026,642 Z" /></clipPath>
+<path d="M1144.3476563,685.296875 L1149.2695313,694 L1154.3476563,685.3867188 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip58)" />
+<clipPath id="clip59"><path d="M1026,642 L1272,642 L1272,698 L1026,698 L1026,642 Z" /></clipPath>
+<path d="M1144.3476563,685.296875 L1149.2695313,694 L1154.3476563,685.3867188 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip59)" />
+<text x="1029" y="672" style="font:10px Georgia">Bob fills request form and presses submit</text>
+</svg>
diff --git a/util/daemon.php b/util/daemon.php
new file mode 100644 (file)
index 0000000..266ddcd
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * @file util/daemon.php
+ * @brief Run the poller from a daemon.
+ *
+ * This script was taken from http://php.net/manual/en/function.pcntl-fork.php
+ */
+function shutdown() {
+       posix_kill(posix_getpid(), SIGHUP);
+}
+
+if (in_array("start", $_SERVER["argv"])) {
+       $mode = "start";
+}
+
+if (in_array("stop", $_SERVER["argv"])) {
+       $mode = "stop";
+}
+
+if (in_array("status", $_SERVER["argv"])) {
+       $mode = "status";
+}
+
+if (!isset($mode)) {
+       die("Please use either 'start', 'stop' or 'status'.\n");
+}
+
+@include(".htconfig.php");
+
+if (!isset($pidfile)) {
+       die('Please specify a pid file in the variable $pidfile in the .htconfig.php. For example:'."\n".
+               '$pidfile = "/path/to/daemon.pid";'."\n");
+}
+
+if (in_array($mode, array("stop", "status"))) {
+       $pid = @file_get_contents($pidfile);
+
+       if (!$pid) {
+               die("Pidfile wasn't found. Is the daemon running?\n");
+       }
+}
+
+if ($mode == "status") {
+       if (posix_kill($pid, 0)) {
+               die("Daemon process $pid is running.\n");
+       }
+
+       unlink($pidfile);
+
+       die("Daemon process $pid isn't running.\n");
+}
+
+if ($mode == "stop") {
+       posix_kill($pid, SIGTERM);
+
+       unlink($pidfile);
+
+       die("Worker daemon process $pid was killed.\n");
+}
+
+echo "Starting worker daemon.\n";
+
+if (isset($a->config['php_path'])) {
+       $php = $a->config['php_path'];
+} else {
+       $php = "php";
+}
+
+// Switch over to daemon mode.
+if ($pid = pcntl_fork())
+       return;     // Parent
+
+fclose(STDIN);  // Close all of the standard
+fclose(STDOUT); // file descriptors as we
+fclose(STDERR); // are running as a daemon.
+
+register_shutdown_function('shutdown');
+
+if (posix_setsid() < 0)
+       return;
+
+if ($pid = pcntl_fork())
+       return;     // Parent
+
+$pid = getmypid();
+file_put_contents($pidfile, $pid);
+
+// Now running as a daemon.
+while (true) {
+       // Just to be sure that this script really runs endlessly
+       set_time_limit(0);
+
+       // Call the poller
+       $cmdline = $php.' include/poller.php';
+
+       exec($cmdline);
+
+       // Now sleep for 5 minutes
+       sleep(300);
+}
+?>
index 335d54f4163100d815285fb6e374128ba150ca24..f020d68df1256700fabd0a695519e6295cfeca12 100644 (file)
@@ -64,8 +64,8 @@
                <div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
                        {{if $item.vote}}
                        <div class="wall-item-like-buttons" id="wall-item-like-buttons-{{$item.id}}">
-                               <a href="#" class="icon like" title="{{$item.vote.like.0|escape:'html'}}" onclick="dolike({{$item.id}},'like'); return false"></a>
-                               {{if $item.vote.dislike}}<a href="#" class="icon dislike" title="{{$item.vote.dislike.0|escape:'html'}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>{{/if}}
+                               <a href="#" class="icon like{{if $item.responses.like.self}} active{{/if}}" title="{{$item.vote.like.0|escape:'html'}}" onclick="dolike({{$item.id}},'like'); return false"></a>
+                               {{if $item.vote.dislike}}<a href="#" class="icon dislike{{if $item.responses.dislike.self}} active{{/if}}" title="{{$item.vote.dislike.0|escape:'html'}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>{{/if}}
                                {{if $item.vote.share}}<a href="#" class="icon recycle wall-item-share-buttons" title="{{$item.vote.share.0|escape:'html'}}" onclick="jotShare({{$item.id}}); return false"></a>{{/if}}
                                <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait|escape:'html'}}" title="{{$item.wait|escape:'html'}}" style="display: none;" />
                        </div>
@@ -88,9 +88,9 @@
                        {{/if}}
                        {{if $item.isevent }}
                        <div class="wall-item-attend-wrapper">
-                               <a href="#" id="attendyes-{{$item.id}}" class="icon attendyes" onclick="dolike({{$item.id}},'attendyes'); return false;" title="{{$item.attend.0|escape:'html'}}"></a>
-                               <a href="#" id="attendno-{{$item.id}}" class="icon attendno"  onclick="dolike({{$item.id}},'attendno'); return false;" title="{{$item.attend.1|escape:'html'}}"></a>
-                               <a href="#" id="attendmaybe-{{$item.id}}"  class="icon attendmaybe" onclick="dolike({{$item.id}},'attendmaybe'); return false;" title="{{$item.attend.2|escape:'html'}}"></a>
+                               <a href="#" id="attendyes-{{$item.id}}" class="icon attendyes{{if $item.responses.attendyes.self}} active{{/if}}" onclick="dolike({{$item.id}},'attendyes'); return false;" title="{{$item.attend.0|escape:'html'}}"></a>
+                               <a href="#" id="attendno-{{$item.id}}" class="icon attendno{{if $item.responses.attendno.self}} active{{/if}}"  onclick="dolike({{$item.id}},'attendno'); return false;" title="{{$item.attend.1|escape:'html'}}"></a>
+                               <a href="#" id="attendmaybe-{{$item.id}}"  class="icon attendmaybe{{if $item.responses.attendmaybe.self}} active{{/if}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;" title="{{$item.attend.2|escape:'html'}}"></a>
                        </div>
                        {{/if}}
                        <div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-{{$item.id}}" >
index 9732edb150448429a45801905a9677177e86f062..c1e8067443a3f35af95c939b74ad119669ba9bad 100644 (file)
@@ -1154,6 +1154,11 @@ input#dfrn-url {
        margin-right: 10px;
 }
 
+.wall-item-like-buttons > a.active,
+.wall-item-attend-wrapper > a.active {
+       background-color: rgba(52, 101, 164, .5);
+}
+
 .editpost {
        margin-left: 10px;
        float: left;
index 42946b6e138db7b6c880a0c62950e653c9fe3431..0dc3573beb79e3f49d1a034699b341fda70eed73 100644 (file)
@@ -1499,14 +1499,19 @@ code > .hl-main {
 /* item social action buttons */
 .wall-item-actions, .wall-item-actions a {
     font-size: 13px;
-    /*color: #aeaeae;*/
     color: #555;
     margin-top: 15px;
     margin-bottom: 0;
 }
+.wall-item-actions a.active {
+    font-weight: bold;
+}
 .wall-item-actions a:hover {
     color: #555;
 }
+.wall-item-actions a.active:hover {
+    color: $link_color;
+}
 .wall-item-actions-left {
     display: table-cell;
     vertical-align: middle;
@@ -2100,7 +2105,6 @@ ul li:hover .contact-wrapper a.contact-action-link:hover {
 
 /* Events page */
 
-
 .fc .fc-month-view .fc-content .fc-title .item-desc:hover {
     color: $link_hover_color;
 }
@@ -2300,6 +2304,39 @@ little modifications to emulate a standard page template */
     -moz-box-shadow: 0 0 3px #dadada;
 }
 
+/* Help Page */
+section.help-content-wrapper h1 {
+    padding-bottom: 0.3em;
+    font-size: 1.8em;
+    border-bottom: 1px solid #ddd;
+}
+section.help-content-wrapper h2 {
+    padding-bottom: 0.3em;
+    font-size: 1.5em;
+    border-bottom: 1px solid #ddd;
+}
+section.help-content-wrapper h3 {
+    font-size: 1.2em;
+}
+section.help-content-wrapper h1,
+section.help-content-wrapper h2,
+section.help-content-wrapper h3,
+section.help-content-wrapper h5,
+section.help-content-wrapper h6 {
+    margin-top: 24px;
+    margin-bottom: 16px;
+    font-weight: 600;
+    line-height: 1.25;
+}
+section.help-content-wrapper p {
+    margin: 0.4em 0;
+}
+section.help-content-wrapper p,
+section.help-content-wrapper a {
+    line-height: 1.6;
+    font-size: 0.96em;
+}
+
 /*
 * Overwriting for transparency and other colors
 */
index 82b1ebdb919db133baade1a63cf15efc32f9e09e..f657ff5f2314afd450d68718d3f82a9dd539d8b3 100644 (file)
@@ -90,7 +90,11 @@ $(document).ready(function(){
 });
 
 // overwrite Dialog.show from main js to load the filebrowser into a bs modal
-Dialog.show = function(url, title="") {
+Dialog.show = function(url, title) {
+       if (typeof(title) === 'undefined') {
+               title = "";
+       }
+
        var modal = $('#modal').modal();
        modal.find("#modal-header h4").html(title);
        modal
index 9722a6e1d44e4aa5c5bc63298be91adf96a171e8..90fbe03bbcac66305d366835959099455377272b 100644 (file)
@@ -7,7 +7,7 @@
 <!-- ./TODO => Unknow block -->
 
 
-<div class="panel">    
+<div class="panel">
        <div class="wall-item-container panel-body{{$item.indent}} {{$item.shiny}} {{$item.previewing}}" >
                <div class="media">
                        {{* Put additional actions in a top-right dropdown menu *}}
                                        {{* Buttons for like and dislike *}}
                                        {{if $item.vote}}
                                                {{if $item.vote.like}}
-                                               <a role="button" href="#" class="button-likes" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false;">{{$item.vote.like.0}}</a>
+                                               <a role="button" href="#" class="button-likes{{if $item.responses.like.self}} active{{/if}}" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false;">{{$item.vote.like.0}}</a>
                                                {{/if}}
 
                                                {{if $item.vote.like AND $item.vote.dislike}}
                                                {{/if}}
 
                                                {{if $item.vote.dislike}}
-                                               <a role="button" href="#" class="button-likes" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false;">{{$item.vote.dislike.0}}</a>
+                                               <a role="button" href="#" class="button-likes{{if $item.responses.like.self}} active{{/if}}" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false;">{{$item.vote.dislike.0}}</a>
                                                {{/if}}
 
                                                {{if ($item.vote.like OR $item.vote.dislike) AND $item.comment}}
                                        {{* Event attendance buttons *}}
                                        {{if $item.isevent}}
                                        <div class="vote-event">
-                                               <a role="button" href="#" class="button-event" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;"><i class="fa fa-check"><span class="sr-only">{{$item.attend.0}}</span></i></a>
-                                               <a role="button" href="#" class="button-event" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"><i class="fa fa-times"><span class="sr-only">{{$item.attend.1}}</span></i></a>
-                                               <a role="button" href="#" class="button-event" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"><i class="fa fa-question"><span class="sr-only">{{$item.attend.2}}</span></i></a>
+                                               <a role="button" href="#" class="button-event{{if $item.responses.attendyes.self}} active{{/if}}" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;"><i class="fa fa-check"><span class="sr-only">{{$item.attend.0}}</span></i></a>
+                                               <a role="button" href="#" class="button-event{{if $item.responses.attendno.self}} active{{/if}}" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"><i class="fa fa-times"><span class="sr-only">{{$item.attend.1}}</span></i></a>
+                                               <a role="button" href="#" class="button-event{{if $item.responses.attendmaybe.self}} active{{/if}}" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"><i class="fa fa-question"><span class="sr-only">{{$item.attend.2}}</span></i></a>
                                        </div>
                                        {{/if}}
 
index 25ad41bc3feb3098c7fdf980462b535937381e81..e71dc7b84c336fb3b2d3dcb7ee1216614449f40e 100644 (file)
@@ -61,7 +61,6 @@ as the value of $top_child_total (this is done at the end of this file)
        <span class="icon s22 star {{$item.isstarred}}" id="starred-{{$item.id}}" title="{{$item.star.starred}}">{{$item.star.starred}}</span>
        {{/if}}
        {{if $item.lock}}<span class="navicon lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}"></span><span class="fa fa-lock"></span>{{/if}}
-       <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
 </div>
 <!-- ./TODO => Unknow block -->
 
@@ -193,6 +192,7 @@ as the value of $top_child_total (this is done at the end of this file)
                        <div class="additional-info text-muted">
                                <div id="wall-item-ago-{{$item.id}}" class="wall-item-ago">
                                        <small><a href="{{$item.plink.orig}}"><span class="time" title="{{$item.localtime}}" data-toggle="tooltip"><time class="dt-published" datetime="{{$item.localtime}}">{{$item.ago}}</time></span></a></small>
+                                       <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
                                </div>
 
                                {{if $item.location}}
@@ -287,7 +287,7 @@ as the value of $top_child_total (this is done at the end of this file)
                                {{* Buttons for like and dislike *}}
                                {{if $item.vote}}
                                        {{if $item.vote.like}}
-                                       <a role="button" class="button-likes" id="like-{{$item.id}}" title="{{$item.vote.like.1}}" onclick="dolike({{$item.id}},'like'); return false;"><i class="fa fa-thumbs-up"></i>&nbsp;{{$item.vote.like.1}}</a>
+                                       <a role="button" class="button-likes{{if $item.responses.like.self}} active{{/if}}" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false;"><i class="fa fa-thumbs-up"></i>&nbsp;{{$item.vote.like.1}}</a>
                                        {{/if}}
 
                                        {{if $item.vote.like AND $item.vote.dislike}}
@@ -295,7 +295,7 @@ as the value of $top_child_total (this is done at the end of this file)
                                        {{/if}}
 
                                        {{if $item.vote.dislike}}
-                                       <a role="button" class="button-likes" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.1}}" onclick="dolike({{$item.id}},'dislike'); return false;"><i class="fa fa-thumbs-down"></i>&nbsp;{{$item.vote.dislike.1}}</a>
+                                       <a role="button" class="button-likes{{if $item.responses.dislike.self}} active{{/if}}" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false;"><i class="fa fa-thumbs-down"></i>&nbsp;{{$item.vote.dislike.1}}</a>
                                        {{/if}}
 
                                        {{if ($item.vote.like OR $item.vote.dislike) AND $item.comment}}
@@ -314,7 +314,7 @@ as the value of $top_child_total (this is done at the end of this file)
                                        <span role="presentation" class="separator">&nbsp;•&nbsp;</span>
                                        {{/if}}
                                        {{if $item.vote.share}}
-                                       <a role="button" class="button-votes" id="share-{{$item.id}}" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false;"><i class="fa fa-retweet"></i>&nbsp;{{$item.vote.share.0}}</a>
+                                       <a role="button" class="button-votes" id="share-{{$item.id}}" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false;"><i class="fa fa-retweet"></i>&nbsp;{{$item.vote.share.1}}</a>
                                        {{/if}}
                                {{/if}}
                        </div>
@@ -323,9 +323,9 @@ as the value of $top_child_total (this is done at the end of this file)
                                {{* Event attendance buttons *}}
                                {{if $item.isevent}}
                                <div class="vote-event">
-                                       <a role="button" class="button-event" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;"><i class="fa fa-check"><span class="sr-only">{{$item.attend.0}}</span></i></a>
-                                       <a role="button" class="button-event" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"><i class="fa fa-times"><span class="sr-only">{{$item.attend.1}}</span></i></a>
-                                       <a role="button" class="button-event" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"><i class="fa fa-question"><span class="sr-only">{{$item.attend.2}}</span></i></a>
+                                       <a role="button" class="button-event{{if $item.responses.attendyes.self}} active{{/if}}" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;"><i class="fa fa-check"><span class="sr-only">{{$item.attend.0}}</span></i></a>
+                                       <a role="button" class="button-event{{if $item.responses.attendno.self}} active{{/if}}" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"><i class="fa fa-times"><span class="sr-only">{{$item.attend.1}}</span></i></a>
+                                       <a role="button" class="button-event{{if $item.responses.attendmaybe.self}} active{{/if}}" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"><i class="fa fa-question"><span class="sr-only">{{$item.attend.2}}</span></i></a>
                                </div>
                                {{/if}}
 
index 36b621b76677247157cd45ea4dd4d7dbbcce0242..c005e838f163e44b56290cf891de8d7dc848c1c3 100644 (file)
@@ -1549,8 +1549,16 @@ input#dfrn-url {
        background-repeat: repeat-x;*/\r
        padding: 5px 5px 0px;\r
        height: 32px;\r
-\r
 }\r
+.wall-item-tools a {\r
+       border-radius: 8px;\r
+       padding: 2px;\r
+       background-position: center;\r
+}\r
+.wall-item-tools a.active {\r
+       background-color: rgba(59, 101, 164, 0.5);\r
+}\r
+\r
 .wall-item-author {\r
 /*     margin-top: 10px;*/\r
        margin-top: 0px;\r
@@ -3896,7 +3904,7 @@ aside input[type='text'] {
 .icon.like {\r
        display: block; width: 26px; height: 28px;/*31 33*/\r
        margin-right: 7px;\r
-       background-size: 100% 100%;\r
+       background-size: 26px 28px;\r
        background-image: url('images/approve.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
@@ -3904,7 +3912,7 @@ aside input[type='text'] {
 \r
 .icon.link {\r
     display: block;  width: 22px; height: 24px;\r
-    background-size: 100% 100%;\r
+    background-size: 22px 24px;\r
     background-image: url('images/link.png');\r
     background-repeat: no-repeat;\r
 \r
@@ -3913,14 +3921,14 @@ aside input[type='text'] {
 /*.globe { background-position: 0px -16px;}*/\r
 .icon.globe {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/globe.png');\r
        background-repeat: no-repeat;\r
 }\r
 /*.noglobe { background-position: -16px -16px;}*/\r
 .icon.noglobe {\r
        display: block; width: 24px; height: 24px;\r
-       background-size: 100% 100%;\r
+       background-size: 24px 24px;\r
        background-image: url('images/noglobe.png');\r
        background-repeat: no-repeat;\r
 }\r
@@ -3931,14 +3939,14 @@ aside input[type='text'] {
 .small-pencil { background-position: -96px -16px;}*/\r
 .icon.pencil {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/pencil.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
 }\r
 .icon.small-pencil {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/pencil.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
@@ -3947,7 +3955,7 @@ aside input[type='text'] {
 .icon.recycle {\r
        display: block;\r
        width: 28px; height: 27px;/*33 32*/\r
-       background-size: 100% 100%;\r
+       background-size: 28px 27px;\r
        background-image: url('images/recycle.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
@@ -3957,7 +3965,7 @@ aside input[type='text'] {
 /*     display: block;*/\r
        display: none;\r
        width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/remote-link.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
@@ -3969,7 +3977,7 @@ aside input[type='text'] {
 .icon.lock {\r
        display: block; width: 17px; height: 25px;\r
        margin-top: 1px;\r
-       background-size: 100% 100%;\r
+       background-size: 17px 25px;\r
        background-image: url('images/lock.png');\r
        background-repeat: no-repeat;\r
 }\r
@@ -3977,7 +3985,7 @@ aside input[type='text'] {
 .icon.unlock {\r
        display: block; width: 17px; height: 28px;\r
        margin-top: -2px;\r
-       background-size: 100% 100%;\r
+       background-size: 17px 28px;\r
        background-image: url('images/unlock.png');\r
        background-repeat: no-repeat;\r
 }\r
@@ -3987,7 +3995,7 @@ aside input[type='text'] {
 /*.attach { background-position: -80px -32px; }*/\r
 .icon.attach {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/paperclip.png');\r
        background-repeat: no-repeat;\r
 }\r
@@ -4000,14 +4008,14 @@ aside input[type='text'] {
 /*.starred { background-position: -16px -48px; }*/\r
 .icon.starred {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/star-yellow.png');\r
        background-repeat: no-repeat;\r
 }\r
 /*.unstarred { background-position: -32px -48px; }*/\r
 .icon.unstarred {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/star.png');\r
        background-repeat: no-repeat;\r
 \r
@@ -4016,7 +4024,7 @@ aside input[type='text'] {
 /*.tagged { background-position: -48px -48px; }*/\r
 .icon.tagged {\r
        display: block; width: 28px; height: 28px;\r
-       background-size: 100% 100%;\r
+       background-size: 28px 28px;\r
        background-image: url('images/tag.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
@@ -4026,7 +4034,7 @@ aside input[type='text'] {
 \r
 .filer-icon {\r
        display: block; width: 24px; height: 24px;\r
-       background-size: 100% 100%;\r
+       background-size: 24px 24px;\r
        background-image: url('images/folder.png');\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
@@ -4034,7 +4042,7 @@ aside input[type='text'] {
 \r
 .event-icon {\r
        display: block; width: 33px; height: 33px;\r
-       background-size: 100% 100%;\r
+       background-size: 33px 33px;\r
        background-repeat: no-repeat;\r
        opacity: 0.5;\r
 }\r
index 1223919fa5bca668f5ae880bd6bc7704de99bccc..3a68b2739f93624671f8b29d7a416b2e4b837148 100644 (file)
@@ -18,7 +18,7 @@
                        </div>
                        <div class="wall-item-arrowphoto-wrapper" ><img src="images/larrow.gif" alt="{{$item.wall}}" /></div>
                        {{/if}}
-                       {{*<!--<div class="wall-item-photo-wrapper wwfrom" id="wall-item-photo-wrapper-{{$item.id}}" 
+                       {{*<!--<div class="wall-item-photo-wrapper wwfrom" id="wall-item-photo-wrapper-{{$item.id}}"
                                onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
                 onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">-->*}}
                        {{*<!--<div class="wall-item-photo-wrapper{{if $item.owner_url}} wwfrom{{/if}}" id="wall-item-photo-wrapper-{{$item.id}}">-->*}}
@@ -38,7 +38,7 @@
                        {{*<!--<div class="wall-item-photo-end"></div>-->*}}
                        <div class="wall-item-wrapper" id="wall-item-wrapper-{{$item.id}}" >
                                {{if $item.lock}}{{*<!--<div class="wall-item-lock">-->*}}<img src="images/lock_icon.gif" class="wall-item-lock lockview" alt="{{$item.lock}}" onclick="lockview(event,{{$item.id}});" />{{*<!--</div>-->*}}
-                               {{else}}<div class="wall-item-lock"></div>{{/if}}       
+                               {{else}}<div class="wall-item-lock"></div>{{/if}}
                                <div class="wall-item-location" id="wall-item-location-{{$item.id}}">{{$item.location}}</div>
                        </div>
                </div>
@@ -71,9 +71,9 @@
                <div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
                        {{if $item.vote}}
                        <div class="wall-item-like-buttons" id="wall-item-like-buttons-{{$item.id}}">
-                               <a href="#" class="icon like" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"></a>
+                               <a href="#" class="icon like{{if $item.responses.like.self}} active{{/if}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"></a>
                                {{if $item.vote.dislike}}
-                               <a href="#" class="icon dislike" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>
+                               <a href="#" class="icon dislike{{if $item.responses.dislike.self}} active{{/if}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>
                                {{/if}}
                                {{if $item.vote.share}}<a href="#" class="icon recycle wall-item-share-buttons" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false"></a>{{/if}}
                                <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
@@ -85,7 +85,7 @@
                        {{if $item.edpost}}
                                <a class="editpost icon pencil" href="{{$item.edpost.0}}" title="{{$item.edpost.1}}"></a>
                        {{/if}}
-                        
+
                        {{if $item.star}}
                        <a href="#" id="starred-{{$item.id}}" onclick="dostar({{$item.id}}); return false;" class="star-item icon {{$item.isstarred}}" title="{{$item.star.toggle}}"></a>
                        {{/if}}
                        {{/if}}
                        {{if $item.filer}}
                        <a href="#" id="filer-{{$item.id}}" onclick="itemFiler({{$item.id}}); return false;" class="filer-item filer-icon" title="{{$item.filer}}"></a>
-                       {{/if}}                 
-                       
+                       {{/if}}
+
                        {{if $item.isevent}}
-                               <a href="#" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;" class="event-item event-icon event-attend-icon"></a>
-                               <a href="#" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"  class="event-item event-icon event-dontattend-icon"></a>
-                               <a href="#" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"  class="event-item event-icon event-maybeattend-icon"></a>
+                               <a href="#" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;" class="event-item event-icon event-attend-icon{{if $item.responses.attendyes.self}} active{{/if}}"></a>
+                               <a href="#" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"  class="event-item event-icon event-dontattend-icon{{if $item.responses.attendno.self}} active{{/if}}"></a>
+                               <a href="#" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"  class="event-item event-icon event-maybeattend-icon{{if $item.responses.attendmaybe.self}} active{{/if}}"></a>
                        {{/if}}
-                       
+
                        {{*<!--<div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-{{$item.id}}" >-->*}}
                                {{if $item.drop.dropping}}<a href="item/drop/{{$item.id}}" onclick="return confirmDelete();" class="wall-item-delete-wrapper icon drophide" title="{{$item.drop.delete}}" id="wall-item-delete-wrapper-{{$item.id}}" {{*onmouseover="imgbright(this);" onmouseout="imgdull(this);" *}}></a>{{/if}}
                        {{*<!--</div>-->*}}
                                {{if $item.drop.pagedrop}}<input type="checkbox" onclick="checkboxhighlight(this);" title="{{$item.drop.select}}" class="item-select" name="itemselected[]" value="{{$item.id}}" />{{/if}}
                        {{*<!--<div class="wall-item-delete-end"></div>-->*}}
                </div>
-       </div>  
+       </div>
        {{*<!--<div class="wall-item-wrapper-end"></div>-->*}}
        {{if $item.responses}}
                {{foreach $item.responses as $verb=>$response}}
index 0912311dad201961589604a8f2ef8c04d2686b3b..46eb650ec1db93278ff68c9b1955acd2f18cf26c 100644 (file)
@@ -1391,6 +1391,17 @@ input#dfrn-url {
        cursor: pointer;
 }
 
+.wall-item-tools a {
+       border-radius: 4px;
+       padding: 2px;
+       background-position: center;
+       background-size: initial !important;
+}
+
+.wall-item-tools a.active {
+       background-color: rgba(59, 101, 164, 0.5);
+}
+
 .wall-item-share-buttons {
        margin-left: 10px;
        margin-right: 10px;
@@ -3896,7 +3907,7 @@ aside input[type='text'] {
 .event-maybeattend-icon { background-image: url('images/event-maybeattend-16.png'); }
 .event-dontattend-icon { background-image: url('images/event-dontattend-16.png'); }
 
-.filer-icon:hover {
+.event-icon:hover {
        opacity: 1.0;
 }
 
index ef18d479c6e669c62c1bb10cbc2e235fca31ae70..498bab323f80a4749882423ceb9135312a73a9b7 100644 (file)
@@ -18,7 +18,7 @@
                        </div>
                        <div class="wall-item-arrowphoto-wrapper" ><img src="images/larrow.gif" alt="{{$item.wall}}" /></div>
                        {{/if}}
-                       <div class="wall-item-photo-wrapper wwfrom p-author h-card" id="wall-item-photo-wrapper-{{$item.id}}" 
+                       <div class="wall-item-photo-wrapper wwfrom p-author h-card" id="wall-item-photo-wrapper-{{$item.id}}"
                                onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
                 onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">
                                <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-photo-link u-url" id="wall-item-photo-link-{{$item.id}}">
@@ -35,7 +35,7 @@
                        {{*<!--<div class="wall-item-photo-end"></div>-->*}}
                        <div class="wall-item-wrapper" id="wall-item-wrapper-{{$item.id}}" >
                                {{if $item.lock}}{{*<!--<div class="wall-item-lock">-->*}}<img src="images/lock_icon.gif" class="wall-item-lock lockview" alt="{{$item.lock}}" onclick="lockview(event,{{$item.id}});" />{{*<!--</div>-->*}}
-                               {{else}}<div class="wall-item-lock"></div>{{/if}}       
+                               {{else}}<div class="wall-item-lock"></div>{{/if}}
                                <div class="wall-item-location" id="wall-item-location-{{$item.id}}">{{$item.location}}</div>
                        </div>
                </div>
@@ -66,9 +66,9 @@
                <div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
                        {{if $item.vote}}
                        <div class="wall-item-like-buttons" id="wall-item-like-buttons-{{$item.id}}">
-                               <a href="#" class="tool like" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"></a>
+                               <a href="#" class="tool like{{if $item.responses.like.self}} active{{/if}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"></a>
                                {{if $item.vote.dislike}}
-                               <a href="#" class="tool dislike" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>
+                               <a href="#" class="tool dislike{{if $item.responses.dislike.self}} active{{/if}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>
                                {{/if}}
                                {{if $item.vote.share}}<a href="#" class="tool recycle wall-item-share-buttons" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false"></a>{{/if}}
                                <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
@@ -80,7 +80,7 @@
                        {{if $item.edpost}}
                                <a class="editpost tool pencil" href="{{$item.edpost.0}}" title="{{$item.edpost.1}}"></a>
                        {{/if}}
-                        
+
                        {{if $item.star}}
                        <a href="#" id="starred-{{$item.id}}" onclick="dostar({{$item.id}}); return false;" class="star-item tool {{$item.isstarred}}" title="{{$item.star.toggle}}"></a>
                        {{/if}}
                        {{/if}}
                        {{if $item.filer}}
                        <a href="#" id="filer-{{$item.id}}" onclick="itemFiler({{$item.id}}); return false;" class="filer-item filer-icon" title="{{$item.filer}}"></a>
-                       {{/if}}                 
+                       {{/if}}
 
                        {{if $item.isevent}}
-                               <a href="#" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;" class="event-item event-icon event-attend-icon"></a>
-                               <a href="#" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"  class="event-item event-icon event-dontattend-icon"></a>
-                               <a href="#" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"  class="event-item event-icon event-maybeattend-icon"></a>
+                               <a href="#" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;" class="event-item event-icon event-attend-icon{{if $item.responses.attendyes.self}} active{{/if}}"></a>
+                               <a href="#" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"  class="event-item event-icon event-dontattend-icon{{if $item.responses.attendno.self}} active{{/if}}"></a>
+                               <a href="#" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"  class="event-item event-icon event-maybeattend-icon{{if $item.responses.attendmaybe.self}} active{{/if}}"></a>
                        {{/if}}
 
 
                        {{*<!--</div>-->*}}
                                {{if $item.drop.pagedrop}}<input type="checkbox" onclick="checkboxhighlight(this);" title="{{$item.drop.select}}" class="item-select" name="itemselected[]" value="{{$item.id}}" />{{/if}}
                        {{*<!--<div class="wall-item-delete-end"></div>-->*}}
-                       
-                       
+
+
                </div>
-       </div>  
+       </div>
        {{*<!--<div class="wall-item-wrapper-end"></div>-->*}}
        {{if $item.responses}}
                {{foreach $item.responses as $verb=>$response}}
index 53864c12f513830156bcd38a7101e8bccca4d3f6..0e5c394394370a186bcd1663264732166da1a2f8 100644 (file)
@@ -1210,6 +1210,9 @@ section {
 .wall-item-container .wall-item-actions-social a {
   margin-right: 3em;
 }
+.wall-item-container .wall-item-actions-social a.active {
+  font-weight: bold;
+}
 .wall-item-container .wall-item-actions-tools {
   float: right;
   width: 15%;
index e099a31d6e50bea409cfd16f79c001da013db17f..0532bc1ed153ac52b89874ad0dfedc4f9d27503c 100644 (file)
@@ -1210,6 +1210,9 @@ section {
 .wall-item-container .wall-item-actions-social a {
   margin-right: 3em;
 }
+.wall-item-container .wall-item-actions-social a.active {
+  font-weight: bold;
+}
 .wall-item-container .wall-item-actions-tools {
   float: right;
   width: 15%;
index 631b0233d652bdb4dcf32ac64baad4b6ab1a2578..a982c6e59c37ff5703430b8ecccf3b6c52cbdd14 100644 (file)
@@ -1210,6 +1210,9 @@ section {
 .wall-item-container .wall-item-actions-social a {
   margin-right: 3em;
 }
+.wall-item-container .wall-item-actions-social a.active {
+  font-weight: bold;
+}
 .wall-item-container .wall-item-actions-tools {
   float: right;
   width: 15%;
index 5d25b0fb4096b2357ad65202b9cda9e1394d3c59..25a524043bdf1a28ae3d7f7693c2a210bad16833 100644 (file)
@@ -575,7 +575,9 @@ section {
                a { margin-right: 3em; }
         }
        .wall-item-actions-social { float: left; margin-top: 0.5em;
-               a { margin-right: 3em; }
+               a { margin-right: 3em;
+                       .active { font-weight: bold;}
+               }
         }
        .wall-item-actions-tools { float: right; width: 15%;
                a { float: right; }
index 12c43eb0b2aa25ebf7cfb120d7b7f92c2ef8d05e..6dfacdb78c680632e27d048867ed883109461806 100644 (file)
@@ -6,7 +6,7 @@
                                        <img src="{{$thumb}}" class="contact-photo{{$sparkle}}" id="wall-item-photo-{{$id}}" alt="{{$name}}" />
                                </a>
                        </div>
-                       <div class="wall-item-location">{{$location}}</div>     
+                       <div class="wall-item-location">{{$location}}</div>
                </div>
                <div class="wall-item-content">
                        {{if $title}}<h2><a href="{{$plink.href}}">{{$title}}</a></h2>{{/if}}
                        <div class="wall-item-actions-author">
                                <a href="{{$profile_url}}" target="redir" title="{{$linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$sparkle}}">{{$name}}</span></a> <span class="wall-item-ago" title="{{$localtime}}">{{$ago}}</span>
                        </div>
-                       
+
                        <div class="wall-item-actions-social">
                        {{if $star}}
                                <a href="#" id="star-{{$id}}" onclick="dostar({{$id}}); return false;"  class="{{$star.classdo}}"  title="{{$star.do}}">{{$star.do}}</a>
                                <a href="#" id="unstar-{{$id}}" onclick="dostar({{$id}}); return false;"  class="{{$star.classundo}}"  title="{{$star.undo}}">{{$star.undo}}</a>
                                <a href="#" id="tagger-{{$id}}" onclick="itemTag({{$id}}); return false;" class="{{$star.classtagger}}" title="{{$star.tagger}}">{{$star.tagger}}</a>
                        {{/if}}
-                       
+
                        {{if $vote}}
-                               <a href="#" id="like-{{$id}}" title="{{$vote.like.0}}" onclick="dolike({{$id}},'like'); return false">{{$vote.like.1}}</a>
-                               <a href="#" id="dislike-{{$id}}" title="{{$vote.dislike.0}}" onclick="dolike({{$id}},'dislike'); return false">{{$vote.dislike.1}}</a>
+                               <a href="#" id="like-{{$id}}"{{if $item.responses.like.self}} class="active{{/if}}" title="{{$vote.like.0}}" onclick="dolike({{$id}},'like'); return false">{{$vote.like.1}}</a>
+                               <a href="#" id="dislike-{{$id}}"{{if $item.responses.dislike.self}} class="active{{/if}}" title="{{$vote.dislike.0}}" onclick="dolike({{$id}},'dislike'); return false">{{$vote.dislike.1}}</a>
                        {{/if}}
-                                               
+
                        {{if $vote.share}}
                                <a href="#" id="share-{{$id}}" title="{{$vote.share.0}}" onclick="jotShare({{$id}}); return false">{{$vote.share.1}}</a>
-                       {{/if}}                 
+                       {{/if}}
                        </div>
-                       
+
                        <div class="wall-item-actions-tools">
 
                                {{if $drop.pagedrop}}
@@ -60,7 +60,7 @@
                                        <a class="icon edit s16" href="{{$edpost.0}}" title="{{$edpost.1}}"></a>
                                {{/if}}
                        </div>
-                       
+
                </div>
        </div>
        <div class="wall-item-bottom">
@@ -73,7 +73,7 @@
                </div>
                {{/if}}
        </div>
-       
-       
+
+
 </div>
 
index 8c9cf22e9f259eda3ac3bbe59798bad59aa27872..512df75ef96d91c8d5415008a674a04acb6ec917 100644 (file)
@@ -1,6 +1,6 @@
 <div class="wall-item-decor">
        {{if $item.star}}<span class="icon s22 star {{$item.isstarred}}" id="starred-{{$item.id}}" title="{{$item.star.starred}}">{{$item.star.starred}}</span>{{/if}}
-       {{if $item.lock}}<span class="icon s22 lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}">{{$item.lock}}</span>{{/if}}       
+       {{if $item.lock}}<span class="icon s22 lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}">{{$item.lock}}</span>{{/if}}
        <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
 </div>
 
@@ -8,7 +8,7 @@
        <div class="wall-item-item">
                <div class="wall-item-info">
                        <div class="contact-photo-wrapper"
-                               onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')" 
+                               onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
                                onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">
                                <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-photo-link" id="wall-item-photo-link-{{$item.id}}">
                                        <img src="{{$item.thumb}}" class="contact-photo{{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
@@ -17,9 +17,9 @@
                                <ul class="wall-item-menu menu-popup" id="wall-item-photo-menu-{{$item.id}}">
                                {{$item.item_photo_menu}}
                                </ul>
-                               
+
                        </div>
-                       <div class="wall-item-location">{{$item.location}}</div>        
+                       <div class="wall-item-location">{{$item.location}}</div>
                </div>
                <div class="wall-item-content">
                        {{if $item.title}}<h2><a href="{{$item.plink.href}}">{{$item.title}}</a></h2>{{/if}}
                        <div class="wall-item-actions-author">
                                <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.sparkle}}">{{$item.name}}</span></a> <span class="wall-item-ago" title="{{$item.localtime}}">{{$item.ago}}</span>
                        </div>
-                       
+
                        <div class="wall-item-actions-social">
                        {{if $item.star}}
                                <a href="#" id="star-{{$item.id}}" onclick="dostar({{$item.id}}); return false;"  class="{{$item.star.classdo}}"  title="{{$item.star.do}}">{{$item.star.do}}</a>
                                <a href="#" id="unstar-{{$item.id}}" onclick="dostar({{$item.id}}); return false;"  class="{{$item.star.classundo}}"  title="{{$item.star.undo}}">{{$item.star.undo}}</a>
                                <a href="#" id="tagger-{{$item.id}}" onclick="itemTag({{$item.id}}); return false;" class="{{$item.star.classtagger}}" title="{{$item.star.tagger}}">{{$item.star.tagger}}</a>
                        {{/if}}
-                       
+
                        {{if $item.vote}}
-                               <a href="#" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false">{{$item.vote.like.1}}</a>
-                               <a href="#" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false">{{$item.vote.dislike.1}}</a>
+                               <a href="#" id="like-{{$item.id}}"{{if $item.responses.like.self}} class="active{{/if}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false">{{$item.vote.like.1}}</a>
+                               <a href="#" id="dislike-{{$item.id}}"{{if $item.responses.dislike.self}} class="active{{/if}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false">{{$item.vote.dislike.1}}</a>
                        {{/if}}
-                                               
+
                        {{if $item.vote.share}}
                                <a href="#" id="share-{{$item.id}}" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false">{{$item.vote.share.1}}</a>
-                       {{/if}}                 
+                       {{/if}}
                        </div>
-                       
+
                        <div class="wall-item-actions-tools">
 
                                {{if $item.drop.pagedrop}}
@@ -73,7 +73,7 @@
                                        <a class="icon edit s16" href="{{$item.edpost.0}}" title="{{$item.edpost.1}}"></a>
                                {{/if}}
                        </div>
-                       
+
                </div>
        </div>
        <div class="wall-item-bottom">
@@ -86,7 +86,7 @@
                </div>
                {{/if}}
        </div>
-       
-       
+
+
 </div>
 
index 247bd16c9f8bec76d0e2149075fceb2de6f63db4..2ec43c0ce51587733a46958980f0c3c5a7eb17a4 100644 (file)
@@ -2,12 +2,12 @@
 {{else}}
 {{if $item.comment_firstcollapsed}}
        <div class="hide-comments-outer">
-               <span id="hide-comments-total-{{$item.id}}" 
+               <span id="hide-comments-total-{{$item.id}}"
                        class="hide-comments-total">{{$item.num_comments}}</span>
-                       <span id="hide-comments-{{$item.id}}" 
-                               class="hide-comments fakelink" 
+                       <span id="hide-comments-{{$item.id}}"
+                               class="hide-comments fakelink"
                                onclick="showHideComments({{$item.id}});">{{$item.hide_text}}</span>
-                       {{if $item.thread_level==3}} - 
+                       {{if $item.thread_level==3}} -
                        <span id="hide-thread-{{$item}}-id"
                                class="fakelink"
                                onclick="showThread({{$item.id}});">expand</span> /
@@ -23,7 +23,7 @@
 
 <div class="wall-item-decor">
        {{if $item.star}}<span class="icon s22 star {{$item.isstarred}}" id="starred-{{$item.id}}" title="{{$item.star.starred}}">{{$item.star.starred}}</span>{{/if}}
-       {{if $item.lock}}<span class="icon s22 lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}">{{$item.lock}}</span>{{/if}}       
+       {{if $item.lock}}<span class="icon s22 lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}">{{$item.lock}}</span>{{/if}}
        <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
 </div>
 
@@ -31,7 +31,7 @@
        <div class="wall-item-item">
                <div class="wall-item-info">
                        <div class="contact-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}} p-author h-card"
-                               onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')" 
+                               onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
                                onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">
                                <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="contact-photo-link u-url" id="wall-item-photo-link-{{$item.id}}">
                                        <img src="{{$item.thumb}}" class="contact-photo {{$item.sparkle}} p-name u-photo" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
                                <ul class="contact-menu menu-popup" id="wall-item-photo-menu-{{$item.id}}">
                                {{$item.item_photo_menu}}
                                </ul>
-                               
-                       </div>  
+
+                       </div>
                        {{if $item.owner_url}}
                        <div class="contact-photo-wrapper mframe wwto" id="wall-item-ownerphoto-wrapper-{{$item.id}}" >
                                <a href="{{$item.owner_url}}" target="redir" title="{{$item.olinktitle}}" class="contact-photo-link" id="wall-item-ownerphoto-link-{{$item.id}}">
                                        <img src="{{$item.owner_photo}}" class="contact-photo {{$item.osparkle}}" id="wall-item-ownerphoto-{{$item.id}}" alt="{{$item.owner_name}}" />
                                </a>
                        </div>
-                       {{/if}}                 
-                       <div class="wall-item-location">{{$item.location}}</div>        
+                       {{/if}}
+                       <div class="wall-item-location">{{$item.location}}</div>
                </div>
                <div class="wall-item-content">
                        {{if $item.title}}<h2><a href="{{$item.plink.href}}" class="{{$item.sparkle}} p-name">{{$item.title}}</a></h2>{{/if}}
@@ -73,7 +73,7 @@
                     <span class='category p-category'>{{$cat.name}}</a>{{if $cat.removeurl}} (<a href="{{$cat.removeurl}}" title="{{$remove}}">x</a>) {{/if}} </span>
                 {{/foreach}}
                </div>
-       </div>  
+       </div>
        <div class="wall-item-bottom">
                <div class="wall-item-links">
                        {{if $item.plink}}<a class="icon s16 link{{$item.sparkle}} u-url" title="{{$item.plink.title}}" href="{{$item.plink.href}}">{{$item.plink.title}}</a>{{/if}}
@@ -88,7 +88,7 @@
                                 {{if $item.owner_url}}<br/>{{$item.to}} <a href="{{$item.owner_url}}" target="redir" title="{{$item.olinktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.osparkle}}" id="wall-item-ownername-{{$item.id}}">{{$item.owner_name}}</span></a> {{$item.vwall}}
                                 {{/if}}
                        </div>
-                       
+
                        <div class="wall-item-actions-social">
                        {{if $item.star}}
                                <a href="#" id="star-{{$item.id}}" onclick="dostar({{$item.id}}); return false;"  class="{{$item.star.classdo}}"  title="{{$item.star.do}}">{{$item.star.do}}</a>
                        {{/if}}
                        {{if $item.filer}}
                                 <a href="#" id="filer-{{$item.id}}" onclick="itemFiler({{$item.id}}); return false;" class="filer-item filer-icon" title="{{$item.filer}}">{{$item.filer}}</a>
-                       {{/if}}                 
-                       
+                       {{/if}}
+
                        {{if $item.vote}}
-                               <a href="#" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false">{{$item.vote.like.1}}</a>
+                               <a href="#" id="like-{{$item.id}}"{{if $item.responses.like.self}} class="active{{/if}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false">{{$item.vote.like.1}}</a>
                                {{if $item.vote.dislike}}
-                               <a href="#" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false">{{$item.vote.dislike.1}}</a>
+                               <a href="#" id="dislike-{{$item.id}}"{{if $item.responses.dislike.self}} class="active{{/if}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false">{{$item.vote.dislike.1}}</a>
                                {{/if}}
                            {{if $item.vote.share}}
                                    <a href="#" id="share-{{$item.id}}" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false">{{$item.vote.share.1}}</a>
-                           {{/if}}                     
+                           {{/if}}
                        {{/if}}
                        {{if $item.isevent}}
                        <div class="clear"></div>
                        <div class="wall-item-actions-isevent">
-                               <a href="#" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;">{{$item.attend.0}}</a>
-                               <a href="#" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;">{{$item.attend.1}}</a>
-                               <a href="#" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;">{{$item.attend.2}}</a>
+                               <a href="#" id="attendyes-{{$item.id}}"{{if $item.responses.attendyes.self}} class="active{{/if}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;">{{$item.attend.0}}</a>
+                               <a href="#" id="attendno-{{$item.id}}"{{if $item.responses.attendno.self}} class="active{{/if}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;">{{$item.attend.1}}</a>
+                               <a href="#" id="attendmaybe-{{$item.id}}"{{if $item.responses.attendmaybe.self}} class="active{{/if}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;">{{$item.attend.2}}</a>
                        </div>
                        {{/if}}
-                                               
+
                        </div>
-                       
+
                        <div class="wall-item-actions-tools">
 
                                {{if $item.drop.pagedrop}}
                                        <a class="icon edit s16" href="{{$item.edpost.0}}" title="{{$item.edpost.1}}"></a>
                                {{/if}}
                        </div>
-                       
+
                </div>
        </div>
        <div class="wall-item-bottom">
                        {{/foreach}}
                {{/if}}
        </div>
-       
+
        {{if $item.threaded}}{{if $item.comment}}{{if $item.indent==comment}}
        <div class="wall-item-bottom commentbox">
                <div class="wall-item-links"></div>
index e38a7ef6dcf929438034239512f61877e3f6a2d4..e91eccfe174e5e3af54d5de4c915968e7b6ab802 100644 (file)
@@ -1586,6 +1586,10 @@ ul .sidebar-group-li .icon {
        margin-right: 10px;
        display: inline;
 }
+.wall-item-like-buttons a.self {
+       background-color: rgba(52, 101, 164, .5);
+       border-radius: 6px;
+}
 
 .wall-item-links-wrapper {
        width: 30px;
index 743612054fc85ded3025196abbc0925399315fa8..134052b9f5c7863a0458cfc647a20c2650fbe637 100644 (file)
@@ -1,7 +1,7 @@
 
 {{if $item.comment_firstcollapsed}}
        <div class="hide-comments-outer">
-               <span id="hide-comments-total-{{$item.id}}" class="hide-comments-total">{{$item.num_comments}}</span> 
+               <span id="hide-comments-total-{{$item.id}}" class="hide-comments-total">{{$item.num_comments}}</span>
                <span id="hide-comments-{{$item.id}}" class="hide-comments fakelink" onclick="showHideComments({{$item.id}});">{{$item.hide_text}}</span>
        </div>
        <div id="collapsed-comments-{{$item.id}}" class="collapsed-comments" style="display: none;">
@@ -19,7 +19,7 @@
                        </div>
                        <div class="wall-item-arrowphoto-wrapper" ><img src="view/theme/smoothly/images/larrow.gif" alt="{{$item.wall}}" /></div>
                        {{/if}}
-                       <div class="wall-item-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}} p-author h-card" id="wall-item-photo-wrapper-{{$item.id}}" 
+                       <div class="wall-item-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}} p-author h-card" id="wall-item-photo-wrapper-{{$item.id}}"
                                onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
                 onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">
                                <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-photo-link u-url" id="wall-item-photo-link-{{$item.id}}">
@@ -51,7 +51,7 @@
                        </a>
                        <div class="wall-item-ago">&bull;</div>
                        <div class="wall-item-ago" id="wall-item-ago-{{$item.id}}" title="{{$item.localtime}}"><time class="dt-published" datetime="{{$item.localtime}}">{{$item.ago}}</time></div>
-               </div>  
+               </div>
 
                <div>
                <hr class="line-dots">
                                </div>
 
                                {{if $item.has_cats}}
-                               <div class="categorytags"><span>{{$item.txt_cats}} {{foreach $item.categories as $cat}}<span class="p-category">{{$cat.name}}</span> 
-                               <a href="{{$cat.removeurl}}" title="{{$remove}}">[{{$remove}}]</a> 
+                               <div class="categorytags"><span>{{$item.txt_cats}} {{foreach $item.categories as $cat}}<span class="p-category">{{$cat.name}}</span>
+                               <a href="{{$cat.removeurl}}" title="{{$remove}}">[{{$remove}}]</a>
                                {{if $cat.last}}{{else}}, {{/if}}{{/foreach}}
                                </div>
                                {{/if}}
 
                                {{if $item.has_folders}}
-                               <div class="filesavetags"><span>{{$item.txt_folders}} {{foreach $item.folders as $cat}}<span class="p-category">{{$cat.name}}</span> 
-                               <a href="{{$cat.removeurl}}" title="{{$remove}}">[{{$remove}}]</a> 
+                               <div class="filesavetags"><span>{{$item.txt_folders}} {{foreach $item.folders as $cat}}<span class="p-category">{{$cat.name}}</span>
+                               <a href="{{$cat.removeurl}}" title="{{$remove}}">[{{$remove}}]</a>
                                {{if $cat.last}}{{else}}, {{/if}}{{/foreach}}
                                </div>
                                {{/if}}
@@ -85,9 +85,9 @@
 
                        {{if $item.vote}}
                        <div class="wall-item-like-buttons" id="wall-item-like-buttons-{{$item.id}}">
-                               <a href="#" class="icon like" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"></a>
+                               <a href="#" class="icon like{{if $item.responses.like.self}} self{{/if}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"></a>
                                {{if $item.vote.dislike}}
-                               <a href="#" class="icon dislike" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>
+                               <a href="#" class="icon dislike{{if $item.responses.dislike.self}} self{{/if}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>
                                {{/if}}
                                {{if $item.vote.share}}
                                <a href="#" class="icon recycle wall-item-share-buttons" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false"></a>                             {{/if}}
                                <a href="{{$item.plink.href}}" title="{{$item.plink.title}}" target="external-link" class="icon remote-link u-url"></a>
                        </div>
                        {{/if}}
-                
+
                        {{if $item.star}}
                        <a href="#" id="starred-{{$item.id}}" onclick="dostar({{$item.id}}); return false;" class="star-item icon {{$item.isstarred}}" title="{{$item.star.toggle}}"></a>
                        {{/if}}
                        {{if $item.filer}}
                        <a href="#" id="filer-{{$item.id}}" onclick="itemFiler({{$item.id}}); return false;" class="filer-item filer-icon" title="{{$item.filer}}"></a>
                        {{/if}}
-       
+
                </div>
 
                <div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
                        <div class="wall-item-delete-end"></div>
                </div>
 
-       </div>  
+       </div>
        <div class="wall-item-wrapper-end"></div>
        <div class="wall-item-like" id="wall-item-like-{{$item.id}}">{{$item.like}}</div>
        <div class="wall-item-dislike" id="wall-item-dislike-{{$item.id}}">{{$item.dislike}}</div>
index d53c2f393f09504116eb740c5b31c6173a965a15..67bab16a1958b22e3e9112ddd8eefddabebfaabf 100644 (file)
@@ -1583,6 +1583,11 @@ section.minimal {
   margin-right: 1em;
   cursor: pointer;
 }
+.wall-item-container .wall-item-actions-social a.active,
+.wall-item-container .wall-item-actions-isevent a.active {
+       color: #36C;
+}
+
 .wall-item-container .wall-item-actions-tools {
   float: right;
   width: 80px;
@@ -1638,7 +1643,7 @@ section.minimal {
   max-width: calc(100% - 1px);
 }
 
-.children .wall-item-comment-wrapper textarea, 
+.children .wall-item-comment-wrapper textarea,
 .wall-item-container.thread_level_3 .wall-item-comment-wrapper textarea,
 .wall-item-container.thread_level_4 .wall-item-comment-wrapper textarea,
 .wall-item-container.thread_level_5 .wall-item-comment-wrapper textarea,
index 84783ae303bc272d6ec8bebdb5f097b98ccd18c2..bc77eaa9cd93ea182978902cd51ebb5552b01502 100644 (file)
@@ -8,7 +8,7 @@
                        </div>
                </div>
                <div class="wall-item-actions-author">
-                       <a href="{{$profile_url}}" target="redir" title="{{$linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$sparkle}}">{{$name}}</span></a> 
+                       <a href="{{$profile_url}}" target="redir" title="{{$linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$sparkle}}">{{$name}}</span></a>
                        <span class="wall-item-ago">
                                {{if $plink}}<a class="link" title="{{$plink.title}}" href="{{$plink.href}}" style="color: #999">{{$ago}}</a>{{else}} {{$ago}} {{/if}}
                                {{if $lock}}<span class="fakelink" style="color: #999" onclick="lockview(event,{{$id}});">{{$lock}}</span> {{/if}}
                </div>
                <div class="wall-item-actions">
 
-                       <div class="wall-item-location">{{$location}}&nbsp;</div>       
-                       
+                       <div class="wall-item-location">{{$location}}&nbsp;</div>
+
                        <div class="wall-item-actions-social">
                        {{if $star}}
                                <a href="#" id="star-{{$id}}" onclick="dostar({{$id}}); return false;"  class="{{$star.classdo}}"  title="{{$star.do}}">{{$star.do}}</a>
                                <a href="#" id="unstar-{{$id}}" onclick="dostar({{$id}}); return false;"  class="{{$star.classundo}}"  title="{{$star.undo}}">{{$star.undo}}</a>
                                <a href="#" id="tagger-{{$id}}" onclick="itemTag({{$id}}); return false;" class="{{$star.classtagger}}" title="{{$star.tagger}}">{{$star.tagger}}</a>
                        {{/if}}
-                       
+
                        {{if $vote}}
-                               <a href="#" id="like-{{$id}}" title="{{$vote.like.0}}" onclick="dolike({{$id}},'like'); return false">{{$vote.like.1}}</a>
-                               <a href="#" id="dislike-{{$id}}" title="{{$vote.dislike.0}}" onclick="dolike({{$id}},'dislike'); return false">{{$vote.dislike.1}}</a>
+                               <a href="#" id="like-{{$id}}"{{if $item.responses.like.self}} class="active"{{/if}} title="{{$vote.like.0}}" onclick="dolike({{$id}},'like'); return false">{{$vote.like.1}}</a>
+                               <a href="#" id="dislike-{{$id}}"{{if $item.responses.dislike.self}} class="active"{{/if}} title="{{$vote.dislike.0}}" onclick="dolike({{$id}},'dislike'); return false">{{$vote.dislike.1}}</a>
                        {{/if}}
-                                               
+
                        {{if $vote.share}}
                                <a href="#" id="share-{{$id}}" title="{{$vote.share.0}}" onclick="jotShare({{$id}}); return false">{{$vote.share.1}}</a>
-                       {{/if}}                 
+                       {{/if}}
                        </div>
-                       
+
                        <div class="wall-item-actions-tools">
 
                                {{if $drop.pagedrop}}
                                        <a class="icon edit s16" href="{{$edpost.0}}" title="{{$edpost.1}}"></a>
                                {{/if}}
                        </div>
-                       
+
                </div>
        </div>
        <div class="wall-item-bottom">
                <div class="wall-item-links"></div>
                <div class="wall-item-like" id="wall-item-like-{{$id}}">{{$like}}</div>
-               <div class="wall-item-dislike" id="wall-item-dislike-{{$id}}">{{$dislike}}</div>        
+               <div class="wall-item-dislike" id="wall-item-dislike-{{$id}}">{{$dislike}}</div>
        </div>
 </div>
index 73e37e5613deb499c3e359dcf8d2b02978675d1d..27ab78af2351af5d475dd217feef9cb9c6170afd 100644 (file)
@@ -2,7 +2,7 @@
 
 <div class="wall-item-decor">
        {{if $item.star}}<span class="icon star {{$item.isstarred}}" id="starred-{{$item.id}}" title="{{$item.star.starred}}">{{$item.star.starred}}</span>{{/if}}
-       {{if $item.lock}}<span class="icon lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}">{{$item.lock}}</span>{{/if}}   
+       {{if $item.lock}}<span class="icon lock fakelink" onclick="lockview(event,{{$item.id}});" title="{{$item.lock}}">{{$item.lock}}</span>{{/if}}
        <img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait}}" title="{{$item.wait}}" style="display: none;" />
 </div>
 
@@ -10,7 +10,7 @@
        <div class="wall-item-item">
                <div class="wall-item-info">
                        <div class="contact-photo-wrapper">
-                               <!-- onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')" 
+                               <!-- onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
                                onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)"> -->
                                <!-- <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-photo-link" id="wall-item-photo-link-{{$item.id}}"></a> -->
                                        <img src="{{$item.thumb}}" class="contact-photo{{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
                                <ul role="menu" aria-haspopup="true" class="wall-item-menu menu-popup" id="wall-item-photo-menu-{{$item.id}}">
                                {{$item.item_photo_menu}}
                                </ul>
-                               
+
                        </div>
                </div>
                <div class="wall-item-actions-author">
-                       <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.sparkle}}">{{$item.name}}</span></a> 
+                       <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.sparkle}}">{{$item.name}}</span></a>
                        <span class="wall-item-ago">
                                {{if $item.plink}}<a class="link" title="{{$item.plink.title}}" href="{{$item.plink.href}}" style="color: #999">{{$item.ago}}</a>{{else}} {{$item.ago}} {{/if}}
                                {{if $item.lock}}<span class="fakelink" style="color: #999" onclick="lockview(event,{{$item.id}});">{{$item.lock}}</span> {{/if}}
                </div>
                <div class="wall-item-actions">
 
-                       <div class="wall-item-location">{{$item.location}}&nbsp;</div>  
-                       
+                       <div class="wall-item-location">{{$item.location}}&nbsp;</div>
+
                        <div class="wall-item-actions-social">
                        {{if $item.star}}
                                <a href="#" id="star-{{$item.id}}" onclick="dostar({{$item.id}}); return false;"  class="{{$item.star.classdo}}"  title="{{$item.star.do}}">{{$item.star.do}}</a>
                                <a href="#" id="unstar-{{$item.id}}" onclick="dostar({{$item.id}}); return false;"  class="{{$item.star.classundo}}"  title="{{$item.star.undo}}">{{$item.star.undo}}</a>
                                <a href="#" id="tagger-{{$item.id}}" onclick="itemTag({{$item.id}}); return false;" class="{{$item.star.classtagger}}" title="{{$item.star.tagger}}">{{$item.star.tagger}}</a>
                        {{/if}}
-                       
+
                        {{if $item.vote}}
-                               <a href="#" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false">{{$item.vote.like.1}}</a>
-                               <a href="#" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false">{{$item.vote.dislike.1}}</a>
+                               <a href="#" id="like-{{$item.id}}"{{if $item.responses.like.self}} class="active"{{/if}} title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false">{{$item.vote.like.1}}</a>
+                               <a href="#" id="dislike-{{$item.id}}"{{if $item.responses.dislike.self}} class="active"{{/if}} title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false">{{$item.vote.dislike.1}}</a>
                        {{/if}}
-                                               
+
                        {{if $item.vote.share}}
                                <a href="#" id="share-{{$item.id}}" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false">{{$item.vote.share.1}}</a>
-                       {{/if}}                 
+                       {{/if}}
                        </div>
-                       
+
                        <div class="wall-item-actions-tools">
 
                                {{if $item.drop.pagedrop}}
                                        <a class="icon edit s16" href="{{$item.edpost.0}}" title="{{$item.edpost.1}}"></a>
                                {{/if}}
                        </div>
-                       
+
                </div>
        </div>
        <div class="wall-item-bottom">
                <div class="wall-item-links"></div>
                <div class="wall-item-like" id="wall-item-like-{{$item.id}}">{{$item.like}}</div>
-               <div class="wall-item-dislike" id="wall-item-dislike-{{$item.id}}">{{$item.dislike}}</div>      
+               <div class="wall-item-dislike" id="wall-item-dislike-{{$item.id}}">{{$item.dislike}}</div>
        </div>
 </div>
index 1f6032f4a55d1354f75484a438ae22ab59b3fb32..23adef340478f47a7036434178bbb0cc3157d129 100644 (file)
@@ -2,12 +2,12 @@
 {{if $mode == display}}
 {{else}}
 {{if $item.comment_firstcollapsed}}
-       {{if $item.thread_level<3}} 
+       {{if $item.thread_level<3}}
                <div class="hide-comments-outer">
-                       <span id="hide-comments-total-{{$item.id}}" 
+                       <span id="hide-comments-total-{{$item.id}}"
                                class="hide-comments-total">{{$item.num_comments}}</span>
-                       <span id="hide-comments-{{$item.id}}" 
-                               class="hide-comments fakelink" 
+                       <span id="hide-comments-{{$item.id}}"
+                               class="hide-comments fakelink"
                                onclick="showHideComments({{$item.id}});">{{$item.hide_text}}</span>
                </div>
                <div id="collapsed-comments-{{$item.id}}" class="collapsed-comments" style="display: none;">
@@ -36,7 +36,7 @@
                                <ul role="menu" aria-haspopup="true" class="contact-menu menu-popup" id="wall-item-photo-menu-{{$item.id}}">
                                {{$item.item_photo_menu}}
                                </ul>
-                               
+
                        </div>
                        {{if $item.owner_url}}
                        <div aria-hidden="true" class="contact-photo-wrapper mframe wwto" id="wall-item-ownerphoto-wrapper-{{$item.id}}" >
@@ -44,7 +44,7 @@
                                        <img src="{{$item.owner_photo}}" class="contact-photo {{$item.osparkle}} p-name u-photo" id="wall-item-ownerphoto-{{$item.id}}" alt="{{$item.owner_name}}" />
                                </a>
                        </div>
-                       {{/if}}                 
+                       {{/if}}
                </div>
                <div role="heading" aria-level="{{$item.thread_level}}" class="wall-item-actions-author">
                        <a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.sparkle}}">{{$item.name}}</span></a>
@@ -81,7 +81,7 @@
                     <span class='category p-category'>{{$cat.name}}</a>{{if $cat.removeurl}} (<a href="{{$cat.removeurl}}" title="{{$remove}}">x</a>) {{/if}} </span>
                 {{/foreach}}
                </div>
-       </div>  
+       </div>
        <div class="wall-item-bottom">
                <div class="wall-item-links">
                        {{if $item.plink}}<a role="button" title="{{$item.plink.orig_title}}" href="{{$item.plink.orig}}"><i class="icon-link icon-large"><span class="sr-only">{{$item.plink.orig_title}}</span></i></a>{{/if}}
                        {{/if}}
 
                        {{if $item.isevent}}
-                               <a role="button" id="attendyes-{{$item.id}}" title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;"><i class="icon-ok icon-large"><span class="sr-only">{{$item.attend.0}}</span></i></a>
-                               <a role="button" id="attendno-{{$item.id}}" title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"><i class="icon-remove icon-large"><span class="sr-only">{{$item.attend.1}}</span></i></a>
-                               <a role="button" id="attendmaybe-{{$item.id}}" title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"><i class="icon-question icon-large"><span class="sr-only">{{$item.attend.2}}</span></i></a>
+                               <a role="button" id="attendyes-{{$item.id}}"{{if $item.responses.attendyes.self}} class="active"{{/if}} title="{{$item.attend.0}}" onclick="dolike({{$item.id}},'attendyes'); return false;"><i class="icon-ok icon-large"><span class="sr-only">{{$item.attend.0}}</span></i></a>
+                               <a role="button" id="attendno-{{$item.id}}"{{if $item.responses.attendno.self}} class="active"{{/if}} title="{{$item.attend.1}}" onclick="dolike({{$item.id}},'attendno'); return false;"><i class="icon-remove icon-large"><span class="sr-only">{{$item.attend.1}}</span></i></a>
+                               <a role="button" id="attendmaybe-{{$item.id}}"{{if $item.responses.attendmaybe.self}} class="active"{{/if}} title="{{$item.attend.2}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;"><i class="icon-question icon-large"><span class="sr-only">{{$item.attend.2}}</span></i></a>
                        {{/if}}
 
                        {{if $item.vote}}
                                {{if $item.vote.like}}
-                               <a role="button" id="like-{{$item.id}}" title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"><i class="icon-thumbs-up icon-large"><span class="sr-only">{{$item.vote.like.0}}</span></i></a>
+                               <a role="button" id="like-{{$item.id}}"{{if $item.responses.like.self}} class="active"{{/if}} title="{{$item.vote.like.0}}" onclick="dolike({{$item.id}},'like'); return false"><i class="icon-thumbs-up icon-large"><span class="sr-only">{{$item.vote.like.0}}</span></i></a>
                                {{/if}}{{if $item.vote.dislike}}
-                               <a role="button" id="dislike-{{$item.id}}" title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"><i class="icon-thumbs-down icon-large"><span class="sr-only">{{$item.vote.dislike.0}}</span></i></a>
+                               <a role="button" id="dislike-{{$item.id}}"{{if $item.responses.dislike.self}} class="active"{{/if}} title="{{$item.vote.dislike.0}}" onclick="dolike({{$item.id}},'dislike'); return false"><i class="icon-thumbs-down icon-large"><span class="sr-only">{{$item.vote.dislike.0}}</span></i></a>
                                {{/if}}
                            {{if $item.vote.share}}
                                    <a role="button" id="share-{{$item.id}}" title="{{$item.vote.share.0}}" onclick="jotShare({{$item.id}}); return false"><i class="icon-retweet icon-large"><span class="sr-only">{{$item.vote.share.0}}</span></i></a>
                                        <a role="button" href="{{$item.edpost.0}}" title="{{$item.edpost.1}}"><i class="icon-edit icon-large"><span class="sr-only">{{$item.edpost.1}}</span></i></a>
                                {{/if}}
                        </div>
-                       
+
                </div>
        </div>
        <div class="wall-item-bottom">
                                <div class="wall-item-{{$verb}}" id="wall-item-{{$verb}}-{{$item.id}}">{{$response.output}}</div>
                        {{/foreach}}
                {{/if}}
-               
+
        </div>
-       
+
        {{if $item.threaded}}{{if $item.comment}}
        <div class="wall-item-bottom">
                <div class="wall-item-links">