diff --git a/INSTALL.txt b/INSTALL.txt index 4a88ac841..bc0f4824a 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -102,17 +102,17 @@ tables, so that you can start fresh. **************************************************************************** **************************************************************************** -8. Set up a cron job or scheduled task to run the poller once every 5-10 +8. Set up a cron job or scheduled task to run the worker once every 5-10 minutes to pick up the recent "public" postings of your friends. Example: - cd /base/directory; /path/to/php include/poller.php + cd /base/directory; /path/to/php scripts/worker.php Change "/base/directory", and "/path/to/php" as appropriate for your situation. If you are using a Linux server, run "crontab -e" and add a line like the one shown, substituting for your unique paths and settings: -*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php include/poller.php +*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php You can generally find the location of PHP by executing "which php". If you have troubles with this section please contact your hosting provider for @@ -285,14 +285,14 @@ cron by using something like */10 * * * * cd /var/www/friendica/friendica/ && sudo -u www-data /usr/bin/php -d suhosin.executor.func.blacklist=none -d suhosin.executor.eval.blacklist=none --f include/poller.php +-f scripts/worker.php This worked well for simple test cases, but the friendica-cron still failed with a fatal error: suhosin[22962]: ALERT - function within blacklist called: proc_open() (attacker 'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php', line 1341) -After a while I noticed, that include/poller.php calls further php script via +After a while I noticed, that scripts/worker.php calls further php script via proc_open. These scripts themselves also use proc_open and fail, because they are NOT called with -d suhosin.executor.func.blacklist=none. diff --git a/boot.php b/boot.php index 4e20058bc..9cdaefb21 100644 --- a/boot.php +++ b/boot.php @@ -27,6 +27,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Object\Contact; use Friendica\Util\Lock; require_once 'include/network.php'; @@ -39,7 +40,6 @@ require_once 'include/features.php'; require_once 'include/identity.php'; require_once 'update.php'; require_once 'include/dbstructure.php'; -require_once 'include/poller.php'; define('FRIENDICA_PLATFORM', 'Friendica'); define('FRIENDICA_CODENAME', 'Asparagus'); @@ -619,7 +619,7 @@ function is_ajax() /** * @brief Function to check if request was an AJAX (xmlhttprequest) request. * - * @param boolean $via_worker boolean Is the check run via the poller? + * @param boolean $via_worker boolean Is the check run via the worker? */ function check_db($via_worker) { @@ -630,7 +630,7 @@ function check_db($via_worker) } if ($build != DB_UPDATE_VERSION) { // When we cannot execute the database update via the worker, we will do it directly - if (!Worker::add(PRIORITY_CRITICAL, 'dbupdate') && $via_worker) { + if (!Worker::add(PRIORITY_CRITICAL, 'DBUpdate') && $via_worker) { update_db(get_app()); } } @@ -984,10 +984,10 @@ function public_contact() if (!$public_contact_id && x($_SESSION, 'authenticated')) { if (x($_SESSION, 'my_address')) { // Local user - $public_contact_id = intval(get_contact($_SESSION['my_address'], 0)); + $public_contact_id = intval(Contact::getIdForURL($_SESSION['my_address'], 0)); } elseif (x($_SESSION, 'visitor_home')) { // Remote user - $public_contact_id = intval(get_contact($_SESSION['visitor_home'], 0)); + $public_contact_id = intval(Contact::getIdForURL($_SESSION['visitor_home'], 0)); } } elseif (!x($_SESSION, 'authenticated')) { $public_contact_id = false; @@ -1065,18 +1065,6 @@ function get_max_import_size() return ((x($a->config, 'max_import_size')) ? $a->config['max_import_size'] : 0 ); } -/** - * @brief compatibilty wrapper for Worker::add function - * - * @param (integer|array) priority or parameter array, strings are deprecated and are ignored - * - * @return boolean "false" if proc_run couldn't be executed - */ -function proc_run() -{ - $proc_args = func_get_args(); - call_user_func_array('Friendica\Core\Worker::add', $proc_args); -} function current_theme() { @@ -1527,15 +1515,6 @@ function get_spoolpath() return ""; } -/// @deprecated -function set_template_engine(App $a, $engine = 'internal') -{ - /// @note This function is no longer necessary, but keep it as a wrapper to the class method - /// to avoid breaking themes again unnecessarily - /// @TODO maybe output a warning here so the theme developer can see it? PHP won't show such warnings like Java does. - - $a->set_template_engine($engine); -} if (!function_exists('exif_imagetype')) { function exif_imagetype($file) diff --git a/composer.json b/composer.json index eb739a8cd..d0014aee1 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "league/html-to-markdown": "~4.4.1", "defuse/php-encryption": "1.*", "pear/Text_LanguageDetect": "1.*", - "pear-pear.php.net/Text_Highlighter": "*" + "pear-pear.php.net/Text_Highlighter": "*", + "paragonie/random_compat": "^2.0" }, "repositories": [ { diff --git a/composer.lock b/composer.lock index 1d59865b9..3c35c7c1a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "a6a3dae4b15752d8f377b1fc1e5a2b47", + "content-hash": "a5c0c297b0e8185f2bcd3aad20ec5acc", "packages": [ { "name": "defuse/php-encryption", @@ -211,6 +211,54 @@ ], "time": "2017-08-29T18:23:54+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v2.0.11", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2017-09-27T21:40:39+00:00" + }, { "name": "pear-pear.php.net/Archive_Tar", "version": "1.4.3", diff --git a/doc/Developers-Intro.md b/doc/Developers-Intro.md index be44e8187..0707d5ba5 100644 --- a/doc/Developers-Intro.md +++ b/doc/Developers-Intro.md @@ -126,7 +126,7 @@ If you want to get involved here: * Look at the first steps that were made (e.g. the clean theme). Ask us to find out whom to talk to about their experiences. * Talk to design people if you know any. -* Let us know about your plans [in the dev forum](https://forum.friendi.ca/profile/developers) and the [theme developer forum](https://friendica.eu/profile/ftdevs). +* Let us know about your plans [in the dev forum](https://forum.friendi.ca/profile/developers) or the [theme developer forum](https://friendica.eu/profile/ftdevs). Do not worry about cross-posting. ###Client software diff --git a/doc/FAQ.md b/doc/FAQ.md index 22adba54b..32c5f74cd 100644 --- a/doc/FAQ.md +++ b/doc/FAQ.md @@ -157,7 +157,7 @@ Friendica is using a [Twitter/GNU Social compatible API](help/api), which means Here is a list of known working clients: * Android - * [Friendiqa](https://github.com/lubuwest/friendiqa) (you can find the APK file in the listed files in the repository) + * [Friendiqa](https://github.com/lubuwest/friendiqa) (available in Google Playstore or from a binary repository you can add to [F-Droid](https://freunde.ma-nic.de/display/3e98eba8185a13c5bdbf3d1539646854)) * AndStatus * Twidere * Mustard and Mustard-Mod diff --git a/doc/Install.md b/doc/Install.md index 9b7b5a947..8f6067a87 100644 --- a/doc/Install.md +++ b/doc/Install.md @@ -94,19 +94,19 @@ Registration errors should all be recoverable automatically. If you get any *critical* failure at this point, it generally indicates the database was not installed correctly. You might wish to move/rename .htconfig.php to another name and empty (called 'dropping') the database tables, so that you can start fresh. -###Set up the poller +###Set up the worker -Set up a cron job or scheduled task to run the poller once every 5-10 minutes in order to perform background processing. +Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing. Example: - cd /base/directory; /path/to/php include/poller.php + cd /base/directory; /path/to/php scripts/worker.php Change "/base/directory", and "/path/to/php" as appropriate for your situation. If you are using a Linux server, run "crontab -e" and add a line like the one shown, substituting for your unique paths and settings: - */10 * * * * cd /home/myname/mywebsite; /usr/bin/php include/poller.php + */10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php You can generally find the location of PHP by executing "which php". If you run into trouble with this section please contact your hosting provider for assistance. diff --git a/doc/Message-Flow.md b/doc/Message-Flow.md index 9a6785d59..9692ae88c 100644 --- a/doc/Message-Flow.md +++ b/doc/Message-Flow.md @@ -19,7 +19,7 @@ Salmon notifications arrive via mod/salmon.php. 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. +DFRN-poll feed imports arrive via src/Worker/OnePoll.php as a scheduled task, this implements the local side of the DFRN-poll protocol. ### Scenario #1. Bob posts a public status message @@ -28,7 +28,7 @@ There are two paths it can take - as a bbcode path to DFRN clients, and converte When a PuSH hub is operational, dfrn-poll clients prefer to receive their information through the PuSH channel. They will fall back on a daily poll in case the hub has delivery issues (this is quite common when using the default Google reference hub). 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. +Feeds retrieved via dfrn-poll are bbcode and may also contain private conversations which the worker has permissions to see. ### Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network. diff --git a/doc/SSL.md b/doc/SSL.md index 95de83305..9d2bee775 100644 --- a/doc/SSL.md +++ b/doc/SSL.md @@ -69,30 +69,28 @@ If you can successfully access your Friendica instance through https, there are This is the simplest way to enforce site-wide secure access. Every time a user tries to access any Friendica page by any mean (manual address bar entry or link), the web server issues a Permanent Redirect response with the secure protocol prepended to the requested URL. -With Apache, simply add the following lines to the [code].htaccess[/code] file in the root folder of your Friendica instance (thanks to [url=https://github.com/AlfredSK]AlfredSK[/url]): +With Apache, enable the modules rewrite and ssl (with a shared hosting provider, this should be enabled already): -[code] -#Force SSL connections + sudo a2enmod rewrite ssl -RewriteEngine On -RewriteCond %{SERVER_PORT} 80 -RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] -[/code] +Add the following lines to the .htaccess file in the root folder of your Friendica instance (thanks to [url=https://github.com/AlfredSK]AlfredSK[/url]): -With nginx, configure your [code]server[/code] directive this way (thanks to [url=https://bjornjohansen.no/redirect-to-https-with-nginx/]Bjørn Johansen[/url]): + RewriteEngine On + RewriteCond %{SERVER_PORT} 80 + RewriteRule ^(.*)$ https://your.friendica.domain/$1 [R=301,L] -[code] -server { - listen 80; - listen [::]:80; - server_name your.friendica.domain; - return 301 https://$server_name$request_uri; -} -[/code] +With nginx, configure your server directive this way ([documentation](https://www.nginx.com/blog/creating-nginx-rewrite-rules/)): + + server { + listen 80; + server_name your.friendica.domain; + return 301 https://$server_name$request_uri; + } ### SSL Settings In the Admin Settings, there are three SSL-related settings: -- **SSL link policy**: this affects how Friendica generates internal links. If your SSL installation was successful, we recommend "Force all links to SSL" just in case your web server configuration can't be altered like described above. -- **Force SSL**: This forces all external links to HTTPS, which may solve Mixed-Content issues, but not all websites support HTTPS yet. Use at your own risk. -- **Verify SSL**: Enabling this will prevent Friendica to interact with self-signed SSL sites. We recommend you leave it on as a self-signed SSL certificate can be a vectorfor a man-in-the-middle attack. \ No newline at end of file + +1. **SSL link policy**: this affects how Friendica generates internal links. If your SSL installation was successful, we recommend "Force all links to SSL" just in case your web server configuration can't be altered like described above. +2. **Force SSL**: This forces all external links to HTTPS, which may solve Mixed-Content issues, but not all websites support HTTPS yet. Use at your own risk. +3. **Verify SSL**: Enabling this will prevent Friendica to interact with self-signed SSL sites. We recommend you leave it on as a self-signed SSL certificate can be a vectorfor a man-in-the-middle attack. diff --git a/doc/de/FAQ.md b/doc/de/FAQ.md index 3507efc5a..2464ec1e0 100644 --- a/doc/de/FAQ.md +++ b/doc/de/FAQ.md @@ -171,7 +171,7 @@ Das bedeutet, dass du jeden Twitter/GNU Social Client verwenden kannst in dem du Hier ist eine Liste von Clients bei denen dies möglich ist, bzw. die speziell für Friendica entwickelt werden: * Android - * [Friendiqa](https://github.com/lubuwest/friendiqa) (ydie APK Datei findest du in den gelisteten Dateien im Repository) + * [Friendiqa](https://github.com/lubuwest/friendiqa) (Gibt es im Google Playstore oder als [binary Repository](https://freunde.ma-nic.de/display/3e98eba8185a13c5bdbf3d1539646854) für F-Droid) * AndStatus * Twidere * Mustard and Mustard-Mod diff --git a/doc/de/Home.md b/doc/de/Home.md index c76a91f53..4ddc1e918 100644 --- a/doc/de/Home.md +++ b/doc/de/Home.md @@ -11,7 +11,7 @@ Friendica - Dokumentation und Ressourcen * [Beiträge kommentieren, einordnen und löschen](help/Text_comment) * [Profile](help/Profiles) * [Referenz der Accesskeys](help/Accesskeys) - * [Veranstaltungen](help/events) (EN) + * [Veranstaltungen](help/events) * Du und andere Nutzer * [Konnektoren (Connectors)](help/Connectors) * [Freunde finden](help/Making-Friends) diff --git a/doc/de/Install.md b/doc/de/Install.md index 2c06d797c..20c479e1c 100644 --- a/doc/de/Install.md +++ b/doc/de/Install.md @@ -84,13 +84,13 @@ Wenn du irgendwelche **kritischen** Fehler zu diesen Zeitpunkt erhalten solltest 7. Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen. Beispiel: - `cd /base/directory; /path/to/php include/poller.php` + `cd /base/directory; /path/to/php scripts/worker.php` Ändere "/base/directory" und "/path/to/php" auf deine Systemvorgaben. Wenn du einen Linux-Server nutzt, benutze den Befehl "crontab -e" und ergänze eine Zeile wie die Folgende; angepasst an dein System -`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php include/poller.php` +`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php` Du kannst den PHP-Pfad finden, indem du den Befehl „which php“ ausführst. Wenn du Schwierigkeiten mit diesem Schritt hast, kannst du deinen Hosting-Anbieter kontaktieren. diff --git a/doc/de/Message-Flow.md b/doc/de/Message-Flow.md index 3d4c912cc..8ef8704d1 100644 --- a/doc/de/Message-Flow.md +++ b/doc/de/Message-Flow.md @@ -21,7 +21,7 @@ Salmon-Benachrichtigungen kommen via mod/salmon.php an. 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. +DFRN-poll Feed-Imports kommen via src/Worker/OnePoll.php als geplanter Task an, das implementiert die lokale Bearbeitung (local side) des DFRN-Protokolls. ### Szenario #1. Bob schreibt eine öffentliche Statusnachricht diff --git a/doc/de/events.md b/doc/de/events.md new file mode 100644 index 000000000..b4979da1d --- /dev/null +++ b/doc/de/events.md @@ -0,0 +1,60 @@ +# Veranstaltungen + +* [Zur Startseite der Hilfe](help) + +Veranstaltungen sind spezielle Postings. +Die Veranstaltungen, die Du und deine Kontakte teilen, können unter [/events](/events) auf deiner Instanz aufgefunden werden. +Um da hinzukommen gehe über den Tab "Veranstalltungen", abhänig von dem Theme, das du benutzt, ist der eventuell ein zusätzlicher link im Navigationsmenü der Seite vorhanden. + + +## Veranstaltungsübersicht + +Die Übersichtsseite zeigt den Kalender des aktuellen Monats an, plus einige Tage am Beginn und am Ende. +Angezeit werden alle Veranstalltungen des aktuellen Monats, die von dir angelegt wurden oder die von deinen Kontakten geteilt wurden. +Dies beinhaltet auch Geburstagserinnerungen, welche mit dir geteilt wurden. + +Es gibt Buttons mit denen die Ansicht zwischen Monatlich/Wöchentlich und Täglich wechseln kann. +Um eine neue Veranstaltung anzulegen, kannst du dem Link "Veranstaltung erstellen" folgen oder einen Doppel-Klick in das Kalenderfeld, in dem die Veranstalltung stehen soll, machen. +Mit einem Klick auf eine bereits existierende Veranstalltung, öffnet sich ein Pop-up Fenster, welches dir die Veranstaltung anzeigt. + +## Erstelle eine neue Veranstaltung + +Folge einer der oben beschriebenen Methoden, dann erreichst du das Formular um die Veranstaltungsdaten einzutragen. Felder mit *** müsen ausgefüllt werden. + +* **Veranstaltungsbeginn**: trage den Anfang der Veranstaltung ein. +* **Veranstaltungsende**: trage das Ende der Veranstaltung ein. + +Wenn du in eines dieser Felder klickst, wird sich ein Popup Fesnster öffnen, wo du Tag und Uhrzeit eintragen kannst. +Wenn du einen Doppel-Klick auf die Box im Kalender machst, werden diese Felder automatisch ausgefüllt. +Das Veranstaltungsende muss nach dem Veranstaltungsanfang liegen. +Aber du musst es nicht angeben. Wenn eine Veranstaltung ein offenes Ende hat oder das Veranstaltungsende nicht wichtig ist, klicke in die Box zwei Felder darunter. + +* **An Zeitzone des Betrachters anpassen**: Wenn du die Box anklickst, wird die Anfangs und Endzeit der Veranstaltung automatisch an die lokale Zeitzone, wie in den Zeitzonen-Einstellung angepasst. + +Dies vermeidet verfrühte Geburstagsglückwünsche, oder die Beführchtung, das du den Geburstag deines Freundes auf der anderen Seite der Welt vergisst und ähnliche Ereignisse. + +* **Titel**: Titel der Veranstaltung +* **Beschreibung**: eine längere Beschreibung der Veranstaltung +* **Ort**: Ort, wo die Veranstaltung stattfinden wird + +Diese 3 Felder beschreiben deine Veranstaltung. +Im Beschreibungs- und Orts-Feld kannst du BBCode zum formatieren des Textes verwenden. + +* **Veranstaltung teilen**: wenn diese Box aktiviert wird, kannst du in der ACL auswählen mit wem du diese Veranstaltung teilen willst. Dies funktioniert wie die Kontrolle jedes anderen Postings. + +Wenn du Veranstaltungen teilst, werden diese auf deine Pinnwand gepostet mit den Zugriffsberechtigungen, die du ausgewählt hast. Bevor du das machst, kannst du dir die Veranstaltung als Vorschau in einem Popup-Fenster anzeigen lassen. + +### Interaktionen mit Veranstaltungen + +Wenn du eine Veranstaltung veröffendlichst, kannst du auswählen, wer sie bekommen wird, wie bei einem normalen Posting. +Die Empfänger sehen deine Veranstaltung in einem Posting in ihrem Network-Stream. +Zusätzlich wird die Veranstaltung zu ihrem Kalender hinzugefügt und somit in ihrer Veranstaltungsübersicht angezeigt. + +Empfänger von einem Veranstaltungs-Posting, können dies kommentieren oder dis-/liken, wie bei einem normalen Posting. +Zusätzlich können sie sagen ob sie teilnehmen, oder vielleicht teilnehmen an der Veranstaltung mit einem einzigen Klick. + +### Kalender exportieren + +Wenn du deine öffentlichen Kalender Einträge exportieren möchtest, kannst du dies in den Einstellungen aktivieren (Einstellungen -> Zusätzliche Features -> Allgemeine Features -> Öffentlichen Kalender exportieren). +Im Anschluss sind auf der Veranstaltungs-Übersichtsseite zwei Links zu den exportierten Einträgen (im ical oder csv Format) verfügbar. + diff --git a/doc/events.md b/doc/events.md index 63944964f..be0040d29 100644 --- a/doc/events.md +++ b/doc/events.md @@ -62,14 +62,8 @@ Additionally it will be added to their calendar and thus be shown in their event Recipients of the event-posting can comment or dis-/like the event, as with a regular posting. Furthermore they can announce that they will attend, not attend or may-be attend the event with a single click. -### Addons +### Calendar Export -#### OpenStreetMap +If you want to export your public events to ical or csv, you can activate an additional feature in your user settings (Additional features -> General Features -> Export Public Calendar). +Afterwards a link will be shown in the events page of your profile to access the calendar. -If this addon is activated on your friendica node, the content of the location field will be matched with the identification service of OSM when you submit the event. -Should OSM find anything matching, a map for the location will be embedded automatically at the end of the events view. - -#### Calendar Export - -If this addon is activated the public events you have created will be published in ical or csv file. -The URL of the published file is ``example.com/cal/nickname/export/format`` (where format is either ical of csv). diff --git a/doc/htconfig.md b/doc/htconfig.md index 684be22fb..3f5b28b91 100644 --- a/doc/htconfig.md +++ b/doc/htconfig.md @@ -23,6 +23,7 @@ Example: To set the directory value please add this line to your .htconfig.php: ## system ## * **allowed_link_protocols** (Array) - Allowed protocols in links URLs, add at your own risk. http is always allowed. +* **always_show_preview** (Boolean) - Only show small preview picures. Default value is false. * **birthday_input_format** - Default value is "ymd". * **block_local_dir** (Boolean) - Blocks the access to the directory of the local users. * **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7. @@ -50,8 +51,8 @@ Example: To set the directory value please add this line to your .htconfig.php: * **local_block** (Boolean) - Used in conjunction with "block_public". * **local_search** (Boolean) - Blocks search for users who are not logged in to prevent crawlers from blocking your system. * **local_tags** (Boolean) - If activated, all hashtags will point to the local server. -* **max_connections** - The maximum number of database connections which can be in use before the poller process is deferred to it's next interval. When the system can't detect the maximum numbers of connection then this value can be used. -* **max_connections_level** - The maximum level of connections that are allowed to let the poller start. It is a percentage value. Default value is 75. +* **max_connections** - The maximum number of database connections which can be in use before the worker process is deferred to it's next interval. When the system can't detect the maximum numbers of connection then this value can be used. +* **max_connections_level** - The maximum level of connections that are allowed to let the worker start. It is a percentage value. Default value is 75. * **max_contact_queue** - Default value is 500. * **max_batch_queue** - Default value is 1000. * **max_processes_backend** - Maximum number of concurrent database processes for background tasks. Default value is 5. diff --git a/doc/themes.md b/doc/themes.md index fc21b19d6..531ff9c16 100644 --- a/doc/themes.md +++ b/doc/themes.md @@ -172,7 +172,7 @@ The content of this file should be something like $a-> theme_info = array( 'extends' => 'duepuntozero'. ); - set_template_engine($a, 'smarty3'); + $a->set_template_engine('smarty3'); /* and more stuff e.g. the JavaScript function for the header */ } @@ -253,7 +253,7 @@ So in the case of quattro it is function quattro_init(App $a) { $a->theme_info = array(); - set_template_engine($a, 'smarty3'); + $a->set_template_engine('smarty3'); } Here we have set the basic theme information, in this case they are empty. diff --git a/include/Contact.php b/include/Contact.php deleted file mode 100644 index cd77bb3bb..000000000 --- a/include/Contact.php +++ /dev/null @@ -1,900 +0,0 @@ - $uid), array("limit" => 1)); - - call_hooks('remove_user',$r); - - // save username (actually the nickname as it is guaranteed - // unique), so it cannot be re-registered in the future. - - dba::insert('userd', array('username' => $r['nickname'])); - - // The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php) - q("UPDATE `user` SET `account_removed` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d", intval($uid)); - Worker::add(PRIORITY_HIGH, "notifier", "removeme", $uid); - - // Send an update to the directory - Worker::add(PRIORITY_LOW, "directory", $r['url']); - - if($uid == local_user()) { - unset($_SESSION['authenticated']); - unset($_SESSION['uid']); - goaway(System::baseUrl()); - } -} - - -function contact_remove($id) { - - // We want just to make sure that we don't delete our "self" contact - $r = q("SELECT `uid` FROM `contact` WHERE `id` = %d AND NOT `self` LIMIT 1", - intval($id) - ); - if (!DBM::is_result($r) || !intval($r[0]['uid'])) { - return; - } - - $archive = PConfig::get($r[0]['uid'], 'system','archive_removed_contacts'); - if ($archive) { - q("update contact set `archive` = 1, `network` = 'none', `writable` = 0 where id = %d", - intval($id) - ); - return; - } - - dba::delete('contact', array('id' => $id)); - - // Delete the rest in the background - Worker::add(PRIORITY_LOW, 'remove_contact', $id); -} - - -// sends an unfriend message. Does not remove the contact - -function terminate_friendship($user,$self,$contact) { - - /// @TODO Get rid of this, include/datetime.php should care about it by itself - $a = get_app(); - - require_once 'include/datetime.php'; - - if ($contact['network'] === NETWORK_OSTATUS) { - - require_once 'include/ostatus.php'; - - // create an unfollow slap - $item = array(); - $item['verb'] = NAMESPACE_OSTATUS."/unfollow"; - $item['follow'] = $contact["url"]; - $slap = ostatus::salmon($item, $user); - - if ((x($contact,'notify')) && (strlen($contact['notify']))) { - require_once 'include/salmon.php'; - slapper($user,$contact['notify'],$slap); - } - } elseif ($contact['network'] === NETWORK_DIASPORA) { - Diaspora::send_unshare($user,$contact); - } elseif ($contact['network'] === NETWORK_DFRN) { - DFRN::deliver($user,$contact,'placeholder', 1); - } - -} - - -// Contact has refused to recognise us as a friend. We will start a countdown. -// If they still don't recognise us in 32 days, the relationship is over, -// and we won't waste any more time trying to communicate with them. -// This provides for the possibility that their database is temporarily messed -// up or some other transient event and that there's a possibility we could recover from it. - -function mark_for_death($contact) { - - if($contact['archive']) - return; - - if ($contact['term-date'] <= NULL_DATE) { - q("UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d", - dbesc(datetime_convert()), - intval($contact['id']) - ); - - if ($contact['url'] != '') { - q("UPDATE `contact` SET `term-date` = '%s' - WHERE `nurl` = '%s' AND `term-date` <= '1000-00-00'", - dbesc(datetime_convert()), - dbesc(normalise_link($contact['url'])) - ); - } - } else { - - /// @todo - /// We really should send a notification to the owner after 2-3 weeks - /// so they won't be surprised when the contact vanishes and can take - /// remedial action if this was a serious mistake or glitch - - /// @todo - /// Check for contact vitality via probing - - $expiry = $contact['term-date'] . ' + 32 days '; - if(datetime_convert() > datetime_convert('UTC','UTC',$expiry)) { - - // relationship is really truly dead. - // archive them rather than delete - // though if the owner tries to unarchive them we'll start the whole process over again - - q("UPDATE `contact` SET `archive` = 1 WHERE `id` = %d", - intval($contact['id']) - ); - - if ($contact['url'] != '') { - q("UPDATE `contact` SET `archive` = 1 WHERE `nurl` = '%s'", - dbesc(normalise_link($contact['url'])) - ); - } - } - } - -} - -function unmark_for_death($contact) { - - $r = q("SELECT `term-date` FROM `contact` WHERE `id` = %d AND (`term-date` > '%s' OR `archive`)", - intval($contact['id']), - dbesc('1000-00-00 00:00:00') - ); - - // We don't need to update, we never marked this contact as dead - if (!DBM::is_result($r)) { - return; - } - - // It's a miracle. Our dead contact has inexplicably come back to life. - $fields = array('term-date' => NULL_DATE, 'archive' => false); - dba::update('contact', $fields, array('id' => $contact['id'])); - - if ($contact['url'] != '') { - dba::update('contact', $fields, array('nurl' => normalise_link($contact['url']))); - } -} - -/** - * @brief Get contact data for a given profile link - * - * The function looks at several places (contact table and gcontact table) for the contact - * It caches its result for the same script execution to prevent duplicate calls - * - * @param string $url The profile link - * @param int $uid User id - * @param array $default If not data was found take this data as default value - * - * @return array Contact data - */ -function get_contact_details_by_url($url, $uid = -1, $default = array()) { - static $cache = array(); - - if ($url == '') { - return $default; - } - - if ($uid == -1) { - $uid = local_user(); - } - - if (isset($cache[$url][$uid])) { - return $cache[$url][$uid]; - } - - $ssl_url = str_replace('http://', 'https://', $url); - - // Fetch contact data from the contact table for the given user - $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `nurl` = ? AND `uid` = ?", - normalise_link($url), $uid); - $r = dba::inArray($s); - - // Fetch contact data from the contact table for the given user, checking with the alias - if (!DBM::is_result($r)) { - $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", - normalise_link($url), $url, $ssl_url, $uid); - $r = dba::inArray($s); - } - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!DBM::is_result($r)) { - $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `nurl` = ? AND `uid` = 0", - normalise_link($url)); - $r = dba::inArray($s); - } - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - checked with the alias - if (!DBM::is_result($r)) { - $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", - normalise_link($url), $url, $ssl_url); - $r = dba::inArray($s); - } - - // Fetch the data from the gcontact table - if (!DBM::is_result($r)) { - $s = dba::p("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` - FROM `gcontact` WHERE `nurl` = ?", - normalise_link($url)); - $r = dba::inArray($s); - } - - if (DBM::is_result($r)) { - // If there is more than one entry we filter out the connector networks - if (count($r) > 1) { - foreach ($r AS $id => $result) { - if ($result["network"] == NETWORK_STATUSNET) { - unset($r[$id]); - } - } - } - - $profile = array_shift($r); - - // "bd" always contains the upcoming birthday of a contact. - // "birthday" might contain the birthday including the year of birth. - if ($profile["birthday"] > '0001-01-01') { - $bd_timestamp = strtotime($profile["birthday"]); - $month = date("m", $bd_timestamp); - $day = date("d", $bd_timestamp); - - $current_timestamp = time(); - $current_year = date("Y", $current_timestamp); - $current_month = date("m", $current_timestamp); - $current_day = date("d", $current_timestamp); - - $profile["bd"] = $current_year."-".$month."-".$day; - $current = $current_year."-".$current_month."-".$current_day; - - if ($profile["bd"] < $current) { - $profile["bd"] = (++$current_year)."-".$month."-".$day; - } - } else { - $profile["bd"] = '0001-01-01'; - } - } else { - $profile = $default; - } - - if (($profile["photo"] == "") && isset($default["photo"])) { - $profile["photo"] = $default["photo"]; - } - - if (($profile["name"] == "") && isset($default["name"])) { - $profile["name"] = $default["name"]; - } - - if (($profile["network"] == "") && isset($default["network"])) { - $profile["network"] = $default["network"]; - } - - if (($profile["thumb"] == "") && isset($profile["photo"])) { - $profile["thumb"] = $profile["photo"]; - } - - if (($profile["micro"] == "") && isset($profile["thumb"])) { - $profile["micro"] = $profile["thumb"]; - } - - if ((($profile["addr"] == "") || ($profile["name"] == "")) && ($profile["gid"] != 0) && - in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { - Worker::add(PRIORITY_LOW, "update_gcontact", $profile["gid"]); - } - - // Show contact details of Diaspora contacts only if connected - if (($profile["cid"] == 0) && ($profile["network"] == NETWORK_DIASPORA)) { - $profile["location"] = ""; - $profile["about"] = ""; - $profile["gender"] = ""; - $profile["birthday"] = '0001-01-01'; - } - - $cache[$url][$uid] = $profile; - - return $profile; -} - -/** - * @brief Get contact data for a given address - * - * The function looks at several places (contact table and gcontact table) for the contact - * - * @param string $addr The profile link - * @param int $uid User id - * - * @return array Contact data - */ -function get_contact_details_by_addr($addr, $uid = -1) { - static $cache = array(); - - if ($addr == '') { - return array(); - } - - if ($uid == -1) { - $uid = local_user(); - } - - // Fetch contact data from the contact table for the given user - $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` - FROM `contact` WHERE `addr` = '%s' AND `uid` = %d", - dbesc($addr), intval($uid)); - - // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!DBM::is_result($r)) - $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, - `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` - FROM `contact` WHERE `addr` = '%s' AND `uid` = 0", - dbesc($addr)); - - // Fetch the data from the gcontact table - if (!DBM::is_result($r)) - $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, - `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` - FROM `gcontact` WHERE `addr` = '%s'", - dbesc($addr)); - - if (!DBM::is_result($r)) { - $data = Probe::uri($addr); - - $profile = get_contact_details_by_url($data['url'], $uid); - } else { - $profile = $r[0]; - } - - return $profile; -} - -if (! function_exists('contact_photo_menu')) { -function contact_photo_menu($contact, $uid = 0) -{ - $a = get_app(); - - $contact_url = ''; - $pm_url = ''; - $status_link = ''; - $photos_link = ''; - $posts_link = ''; - $contact_drop_link = ''; - $poke_link = ''; - - if ($uid == 0) { - $uid = local_user(); - } - - if ($contact['uid'] != $uid) { - if ($uid == 0) { - $profile_link = zrl($contact['url']); - $menu = Array('profile' => array(t('View Profile'), $profile_link, true)); - - return $menu; - } - - $r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `network` = '%s' AND `uid` = %d", - dbesc($contact['nurl']), dbesc($contact['network']), intval($uid)); - if ($r) { - return contact_photo_menu($r[0], $uid); - } else { - $profile_link = zrl($contact['url']); - $connlnk = 'follow/?url='.$contact['url']; - $menu = array( - 'profile' => array(t('View Profile'), $profile_link, true), - 'follow' => array(t('Connect/Follow'), $connlnk, true) - ); - - return $menu; - } - } - - $sparkle = false; - if ($contact['network'] === NETWORK_DFRN) { - $sparkle = true; - $profile_link = System::baseUrl() . '/redir/' . $contact['id']; - } else { - $profile_link = $contact['url']; - } - - if ($profile_link === 'mailbox') { - $profile_link = ''; - } - - if ($sparkle) { - $status_link = $profile_link . '?url=status'; - $photos_link = $profile_link . '?url=photos'; - $profile_link = $profile_link . '?url=profile'; - } - - if (in_array($contact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA))) { - $pm_url = System::baseUrl() . '/message/new/' . $contact['id']; - } - - if ($contact['network'] == NETWORK_DFRN) { - $poke_link = System::baseUrl() . '/poke/?f=&c=' . $contact['id']; - } - - $contact_url = System::baseUrl() . '/contacts/' . $contact['id']; - - $posts_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/posts'; - $contact_drop_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/drop?confirm=1'; - - /** - * menu array: - * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ] - */ - $menu = array( - 'status' => array(t("View Status"), $status_link, true), - 'profile' => array(t("View Profile"), $profile_link, true), - 'photos' => array(t("View Photos"), $photos_link, true), - 'network' => array(t("Network Posts"), $posts_link, false), - 'edit' => array(t("View Contact"), $contact_url, false), - 'drop' => array(t("Drop Contact"), $contact_drop_link, false), - 'pm' => array(t("Send PM"), $pm_url, false), - 'poke' => array(t("Poke"), $poke_link, false), - ); - - - $args = array('contact' => $contact, 'menu' => &$menu); - - call_hooks('contact_photo_menu', $args); - - $menucondensed = array(); - - foreach ($menu AS $menuname => $menuitem) { - if ($menuitem[1] != '') { - $menucondensed[$menuname] = $menuitem; - } - } - - return $menucondensed; -}} - - -function random_profile() { - $r = q("SELECT `url` FROM `gcontact` WHERE `network` = '%s' - AND `last_contact` >= `last_failure` - AND `updated` > UTC_TIMESTAMP - INTERVAL 1 MONTH - ORDER BY rand() LIMIT 1", - dbesc(NETWORK_DFRN)); - - if (DBM::is_result($r)) - return dirname($r[0]['url']); - return ''; -} - - -function contacts_not_grouped($uid,$start = 0,$count = 0) { - - if(! $count) { - $r = q("select count(*) as total from contact where uid = %d and self = 0 and id not in (select distinct(`contact-id`) from group_member where uid = %d) ", - intval($uid), - intval($uid) - ); - - return $r; - - - } - - $r = q("select * from contact where uid = %d and self = 0 and id not in (select distinct(`contact-id`) from group_member where uid = %d) and blocked = 0 and pending = 0 limit %d, %d", - intval($uid), - intval($uid), - intval($start), - intval($count) - ); - - return $r; -} - -/** - * @brief Fetch the contact id for a given url and user - * - * First lookup in the contact table to find a record matching either `url`, `nurl`, - * `addr` or `alias`. - * - * If there's no record and we aren't looking for a public contact, we quit. - * If there's one, we check that it isn't time to update the picture else we - * directly return the found contact id. - * - * Second, we probe the provided $url wether it's http://server.tld/profile or - * nick@server.tld. We quit if we can't get any info back. - * - * Third, we create the contact record if it doesn't exist - * - * Fourth, we update the existing record with the new data (avatar, alias, nick) - * if there's any updates - * - * @param string $url Contact URL - * @param integer $uid The user id for the contact (0 = public contact) - * @param boolean $no_update Don't update the contact - * - * @return integer Contact ID - */ -function get_contact($url, $uid = 0, $no_update = false) { - logger("Get contact data for url ".$url." and user ".$uid." - ".System::callstack(), LOGGER_DEBUG); - - $data = array(); - $contact_id = 0; - - if ($url == '') { - return 0; - } - - // We first try the nurl (http://server.tld/nick), most common case - $contact = dba::select('contact', array('id', 'avatar-date'), array('nurl' => normalise_link($url), 'uid' => $uid), array('limit' => 1)); - - // Then the addr (nick@server.tld) - if (!DBM::is_result($contact)) { - $contact = dba::select('contact', array('id', 'avatar-date'), array('addr' => $url, 'uid' => $uid), array('limit' => 1)); - } - - // Then the alias (which could be anything) - if (!DBM::is_result($contact)) { - // The link could be provided as http although we stored it as https - $ssl_url = str_replace('http://', 'https://', $url); - $r = dba::p("SELECT `id`, `avatar-date` FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ? LIMIT 1", - $url, normalise_link($url), $ssl_url, $uid); - $contact = dba::fetch($r); - dba::close($r); - } - - if (DBM::is_result($contact)) { - $contact_id = $contact["id"]; - - // Update the contact every 7 days - $update_contact = ($contact['avatar-date'] < datetime_convert('','','now -7 days')); - - // We force the update if the avatar is empty - if ($contact['avatar'] == '') { - $update_contact = true; - } - - if (!$update_contact || $no_update) { - return $contact_id; - } - } elseif ($uid != 0) { - // Non-existing user-specific contact, exiting - return 0; - } - - $data = Probe::uri($url, "", $uid); - - // Last try in gcontact for unsupported networks - if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA, NETWORK_PUMPIO, NETWORK_MAIL))) { - if ($uid != 0) { - return 0; - } - - // Get data from the gcontact table - $gcontacts = dba::select('gcontact', array('name', 'nick', 'url', 'photo', 'addr', 'alias', 'network'), - array('nurl' => normalise_link($url)), array('limit' => 1)); - if (!DBM::is_result($gcontacts)) { - return 0; - } - - $data = array_merge($data, $gcontacts); - } - - if (!$contact_id && ($data["alias"] != '') && ($data["alias"] != $url)) { - $contact_id = get_contact($data["alias"], $uid, true); - } - - $url = $data["url"]; - if (!$contact_id) { - dba::insert('contact', array('uid' => $uid, 'created' => datetime_convert(), 'url' => $data["url"], - 'nurl' => normalise_link($data["url"]), 'addr' => $data["addr"], - 'alias' => $data["alias"], 'notify' => $data["notify"], 'poll' => $data["poll"], - 'name' => $data["name"], 'nick' => $data["nick"], 'photo' => $data["photo"], - 'keywords' => $data["keywords"], 'location' => $data["location"], 'about' => $data["about"], - 'network' => $data["network"], 'pubkey' => $data["pubkey"], - 'rel' => CONTACT_IS_SHARING, 'priority' => $data["priority"], - 'batch' => $data["batch"], 'request' => $data["request"], - 'confirm' => $data["confirm"], 'poco' => $data["poco"], - 'name-date' => datetime_convert(), 'uri-date' => datetime_convert(), - 'avatar-date' => datetime_convert(), 'writable' => 1, 'blocked' => 0, - 'readonly' => 0, 'pending' => 0)); - - $contacts = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d ORDER BY `id` LIMIT 2", - dbesc(normalise_link($data["url"])), - intval($uid)); - if (!DBM::is_result($contacts)) { - return 0; - } - - $contact_id = $contacts[0]["id"]; - - // Update the newly created contact from data in the gcontact table - $gcontact = dba::select('gcontact', array('location', 'about', 'keywords', 'gender'), - array('nurl' => normalise_link($data["url"])), array('limit' => 1)); - if (DBM::is_result($gcontact)) { - // Only use the information when the probing hadn't fetched these values - if ($data['keywords'] != '') { - unset($gcontact['keywords']); - } - if ($data['location'] != '') { - unset($gcontact['location']); - } - if ($data['about'] != '') { - unset($gcontact['about']); - } - dba::update('contact', $gcontact, array('id' => $contact_id)); - } - - if (count($contacts) > 1 && $uid == 0 && $contact_id != 0 && $data["url"] != "") { - dba::delete('contact', array("`nurl` = ? AND `uid` = 0 AND `id` != ? AND NOT `self`", - normalise_link($data["url"]), $contact_id)); - } - } - - require_once "Photo.php"; - - update_contact_avatar($data["photo"], $uid, $contact_id); - - $contact = dba::select('contact', array('url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date'), - array('id' => $contact_id), array('limit' => 1)); - - // This condition should always be true - if (!DBM::is_result($contact)) { - return $contact_id; - } - - $updated = array('addr' => $data['addr'], - 'alias' => $data['alias'], - 'url' => $data['url'], - 'nurl' => normalise_link($data['url']), - 'name' => $data['name'], - 'nick' => $data['nick']); - - if ($data['keywords'] != '') { - $updated['keywords'] = $data['keywords']; - } - if ($data['location'] != '') { - $updated['location'] = $data['location']; - } - if ($data['about'] != '') { - $updated['about'] = $data['about']; - } - - if (($data["addr"] != $contact["addr"]) || ($data["alias"] != $contact["alias"])) { - $updated['uri-date'] = datetime_convert(); - } - if (($data["name"] != $contact["name"]) || ($data["nick"] != $contact["nick"])) { - $updated['name-date'] = datetime_convert(); - } - - $updated['avatar-date'] = datetime_convert(); - - dba::update('contact', $updated, array('id' => $contact_id), $contact); - - return $contact_id; -} - -/** - * @brief Checks if the contact is blocked - * - * @param int $cid contact id - * - * @return boolean Is the contact blocked? - */ -function blockedContact($cid) { - if ($cid == 0) { - return false; - } - - $blocked = dba::select('contact', array('blocked'), array('id' => $cid), array('limit' => 1)); - if (!DBM::is_result($blocked)) { - return false; - } - return (bool)$blocked['blocked']; -} - -/** - * @brief Checks if the contact is hidden - * - * @param int $cid contact id - * - * @return boolean Is the contact hidden? - */ -function hiddenContact($cid) { - if ($cid == 0) { - return false; - } - - $hidden = dba::select('contact', array('hidden'), array('id' => $cid), array('limit' => 1)); - if (!DBM::is_result($hidden)) { - return false; - } - return (bool)$hidden['hidden']; -} - -/** - * @brief Returns posts from a given gcontact - * - * @param App $a argv application class - * @param int $gcontact_id Global contact - * - * @return string posts in HTML - */ -function posts_from_gcontact(App $a, $gcontact_id) { - - require_once 'include/conversation.php'; - - // There are no posts with "uid = 0" with connector networks - // This speeds up the query a lot - $r = q("SELECT `network` FROM `gcontact` WHERE `id` = %d", dbesc($gcontact_id)); - if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) - $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND `item`.`private`))"; - else - $sql = "`item`.`uid` = %d"; - - $r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`, - `author-name` AS `name`, `owner-avatar` AS `photo`, - `owner-link` AS `url`, `owner-avatar` AS `thumb` - FROM `item` - WHERE `gcontact-id` = %d AND $sql AND - NOT `deleted` AND NOT `moderated` AND `visible` - ORDER BY `item`.`created` DESC LIMIT %d, %d", - intval($gcontact_id), - intval(local_user()), - intval($a->pager['start']), - intval($a->pager['itemspage']) - ); - - $o = conversation($a, $r, 'community', false); - - $o .= alt_pager($a, count($r)); - - return $o; -} -/** - * @brief Returns posts from a given contact url - * - * @param App $a argv application class - * @param string $contact_url Contact URL - * - * @return string posts in HTML - */ -function posts_from_contact_url(App $a, $contact_url) { - - require_once 'include/conversation.php'; - - // There are no posts with "uid = 0" with connector networks - // This speeds up the query a lot - $r = q("SELECT `network`, `id` AS `author-id`, `contact-type` FROM `contact` - WHERE `contact`.`nurl` = '%s' AND `contact`.`uid` = 0", - dbesc(normalise_link($contact_url))); - - if (!DBM::is_result($r)) { - return ''; - } - - if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { - $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND NOT `item`.`global`))"; - } else { - $sql = "`item`.`uid` = %d"; - } - - $author_id = intval($r[0]["author-id"]); - - $contact = ($r[0]["contact-type"] == ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id'); - - $r = q(item_query()." AND `item`.`".$contact."` = %d AND ".$sql. - " ORDER BY `item`.`created` DESC LIMIT %d, %d", - intval($author_id), - intval(local_user()), - intval($a->pager['start']), - intval($a->pager['itemspage']) - ); - - $o = conversation($a, $r, 'community', false); - - $o .= alt_pager($a, count($r)); - - return $o; -} - -/** - * @brief Returns a formatted location string from the given profile array - * - * @param array $profile Profile array (Generated from the "profile" table) - * - * @return string Location string - */ -function formatted_location($profile) { - $location = ''; - - if($profile['locality']) - $location .= $profile['locality']; - - if($profile['region'] && ($profile['locality'] != $profile['region'])) { - if($location) - $location .= ', '; - - $location .= $profile['region']; - } - - if($profile['country-name']) { - if($location) - $location .= ', '; - - $location .= $profile['country-name']; - } - - return $location; -} - -/** - * @brief Returns the account type name - * - * The function can be called with either the user or the contact array - * - * @param array $contact contact or user array - */ -function account_type($contact) { - - // There are several fields that indicate that the contact or user is a forum - // "page-flags" is a field in the user table, - // "forum" and "prv" are used in the contact table. They stand for PAGE_COMMUNITY and PAGE_PRVGROUP. - // "community" is used in the gcontact table and is true if the contact is PAGE_COMMUNITY or PAGE_PRVGROUP. - if((isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_COMMUNITY)) - || (isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_PRVGROUP)) - || (isset($contact['forum']) && intval($contact['forum'])) - || (isset($contact['prv']) && intval($contact['prv'])) - || (isset($contact['community']) && intval($contact['community']))) - $type = ACCOUNT_TYPE_COMMUNITY; - else - $type = ACCOUNT_TYPE_PERSON; - - // The "contact-type" (contact table) and "account-type" (user table) are more general then the chaos from above. - if (isset($contact["contact-type"])) - $type = $contact["contact-type"]; - if (isset($contact["account-type"])) - $type = $contact["account-type"]; - - switch($type) { - case ACCOUNT_TYPE_ORGANISATION: - $account_type = t("Organisation"); - break; - case ACCOUNT_TYPE_NEWS: - $account_type = t('News'); - break; - case ACCOUNT_TYPE_COMMUNITY: - $account_type = t("Forum"); - break; - default: - $account_type = ""; - break; - } - - return $account_type; -} diff --git a/include/DirSearch.php b/include/DirSearch.php deleted file mode 100644 index 259e436cb..000000000 --- a/include/DirSearch.php +++ /dev/null @@ -1,64 +0,0 @@ - 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND - (`gcontact`.`addr` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`nick` LIKE '%s') $extra_sql - GROUP BY `gcontact`.`nurl` - ORDER BY `gcontact`.`nurl` DESC - LIMIT 1000", - intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND), - dbesc(NETWORK_DFRN), dbesc($ostatus), dbesc($diaspora), - dbesc(escape_tags($search)), dbesc(escape_tags($search)), dbesc(escape_tags($search))); - - return $results; - } - - } -} diff --git a/include/Emailer.php b/include/Emailer.php deleted file mode 100644 index 978b19218..000000000 --- a/include/Emailer.php +++ /dev/null @@ -1,85 +0,0 @@ -\n" . - "Reply-To: $fromName <{$params['replyTo']}>\n" . - "MIME-Version: 1.0\n" . - "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\""; - - // assemble the final multipart message body with the text and html types included - $textBody = chunk_split(base64_encode($params['textVersion'])); - $htmlBody = chunk_split(base64_encode($params['htmlVersion'])); - $multipartMessageBody = - "--" . $mimeBoundary . "\n" . // plain text section - "Content-Type: text/plain; charset=UTF-8\n" . - "Content-Transfer-Encoding: base64\n\n" . - $textBody . "\n"; - - if (!$email_textonly && !is_null($params['htmlVersion'])){ - $multipartMessageBody .= - "--" . $mimeBoundary . "\n" . // text/html section - "Content-Type: text/html; charset=UTF-8\n" . - "Content-Transfer-Encoding: base64\n\n" . - $htmlBody . "\n"; - } - $multipartMessageBody .= - "--" . $mimeBoundary . "--\n"; // message ending - - // send the message - $hookdata = array( - 'to' => $params['toEmail'], - 'subject' => $messageSubject, - 'body' => $multipartMessageBody, - 'headers' => $messageHeader - ); - //echo "
"; var_dump($hookdata); killme(); - call_hooks("emailer_send", $hookdata); - $res = mail( - $hookdata['to'], // send to address - $hookdata['subject'], // subject - $hookdata['body'], // message body - $hookdata['headers'] // message headers - ); - logger("header " . 'To: ' . $params['toEmail'] . "\n" . $messageHeader, LOGGER_DEBUG); - logger("return value " . (($res)?"true":"false"), LOGGER_DEBUG); - return $res; - } -} diff --git a/include/HTTPExceptions.php b/include/HTTPExceptions.php deleted file mode 100644 index 8571c99de..000000000 --- a/include/HTTPExceptions.php +++ /dev/null @@ -1,105 +0,0 @@ -httpdesc=="") { - $this->httpdesc = preg_replace("|([a-z])([A-Z])|",'$1 $2', str_replace("Exception","",get_class($this))); - } - parent::__construct($message, $code, $previous); - } -} - -// 4xx -class TooManyRequestsException extends HTTPException { - var $httpcode = 429; -} - -class UnauthorizedException extends HTTPException { - var $httpcode = 401; -} - -class ForbiddenException extends HTTPException { - var $httpcode = 403; -} - -class NotFoundException extends HTTPException { - var $httpcode = 404; -} - -class GoneException extends HTTPException { - var $httpcode = 410; -} - -class MethodNotAllowedException extends HTTPException { - var $httpcode = 405; -} - -class NonAcceptableException extends HTTPException { - var $httpcode = 406; -} - -class LenghtRequiredException extends HTTPException { - var $httpcode = 411; -} - -class PreconditionFailedException extends HTTPException { - var $httpcode = 412; -} - -class UnsupportedMediaTypeException extends HTTPException { - var $httpcode = 415; -} - -class ExpetationFailesException extends HTTPException { - var $httpcode = 417; -} - -class ConflictException extends HTTPException { - var $httpcode = 409; -} - -class UnprocessableEntityException extends HTTPException { - var $httpcode = 422; -} - -class ImATeapotException extends HTTPException { - var $httpcode = 418; - var $httpdesc = "I'm A Teapot"; -} - -class BadRequestException extends HTTPException { - var $httpcode = 400; -} - -// 5xx - -class ServiceUnavaiableException extends HTTPException { - var $httpcode = 503; -} - -class BadGatewayException extends HTTPException { - var $httpcode = 502; -} - -class GatewayTimeoutException extends HTTPException { - var $httpcode = 504; -} - -class NotImplementedException extends HTTPException { - var $httpcode = 501; -} - -class InternalServerErrorException extends HTTPException { - var $httpcode = 500; -} - - - diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 956c2a9f6..ef75d416f 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -7,10 +7,11 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; require_once "include/contact_selectors.php"; require_once "include/contact_widgets.php"; -require_once "include/DirSearch.php"; require_once "include/features.php"; require_once "mod/proxy.php"; @@ -59,10 +60,9 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) { return $o; } -/// @TODO after an optional parameter, no mandadory parameter can follow /// @TODO find proper type-hints -function contact_selector($selname, $selclass, $preselected = false, $options) { - +function contact_selector($selname, $selclass, $options, $preselected = false) +{ $a = get_app(); $mutual = false; @@ -692,7 +692,7 @@ function acl_lookup(App $a, $out_type = 'json') { ); if (DBM::is_result($r)) { foreach ($r as $row) { - $contact = get_contact_details_by_url($row['author-link']); + $contact = Contact::getDetailsByURL($row['author-link']); if (count($contact) > 0) { $unknown_contacts[] = array( @@ -779,7 +779,7 @@ function navbar_complete(App $a) { } if ($localsearch) { - $x = DirSearch::global_search_by_name($search, $mode); + $x = GlobalContact::searchByName($search, $mode); return $x; } diff --git a/include/api.php b/include/api.php index 33624dcf6..e0dc413c2 100644 --- a/include/api.php +++ b/include/api.php @@ -12,10 +12,20 @@ use Friendica\Core\Config; use Friendica\Core\NotificationsManager; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\User; +use Friendica\Network\HTTPException; +use Friendica\Network\HTTPException\BadRequestException; +use Friendica\Network\HTTPException\ForbiddenException; +use Friendica\Network\HTTPException\InternalServerErrorException; +use Friendica\Network\HTTPException\MethodNotAllowedException; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Network\HTTPException\NotImplementedException; +use Friendica\Network\HTTPException\UnauthorizedException; +use Friendica\Network\HTTPException\TooManyRequestsException; +use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; use Friendica\Util\XML; -require_once 'include/HTTPExceptions.php'; require_once 'include/bbcode.php'; require_once 'include/datetime.php'; require_once 'include/conversation.php'; @@ -181,7 +191,6 @@ function api_login(App $a) $user = $_SERVER['PHP_AUTH_USER']; $password = $_SERVER['PHP_AUTH_PW']; - $encrypted = hash('whirlpool', trim($password)); // allow "user@server" login (but ignore 'server' part) $at = strstr($user, "@", true); @@ -209,16 +218,9 @@ function api_login(App $a) if (($addon_auth['authenticated']) && (count($addon_auth['user_record']))) { $record = $addon_auth['user_record']; } else { - // process normal login request - $r = q( - "SELECT * FROM `user` WHERE (`email` = '%s' OR `nickname` = '%s') - AND `password` = '%s' AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1", - dbesc(trim($user)), - dbesc(trim($user)), - dbesc($encrypted) - ); - if (DBM::is_result($r)) { - $record = $r[0]; + $user_id = User::authenticate(trim($user), trim($password)); + if ($user_id) { + $record = dba::select('user', [], ['uid' => $user_id], ['limit' => 1]); } } @@ -649,7 +651,7 @@ function api_get_user(App $a, $contact_id = null, $type = "json") 'notifications' => false, 'statusnet_profile_url' => $r[0]["url"], 'uid' => 0, - 'cid' => get_contact($r[0]["url"], api_user(), true), + 'cid' => Contact::getIdForURL($r[0]["url"], api_user(), true), 'self' => 0, 'network' => $r[0]["network"], ); @@ -737,7 +739,7 @@ function api_get_user(App $a, $contact_id = null, $type = "json") $network_name = network_to_name($uinfo[0]['network'], $uinfo[0]['url']); - $pcontact_id = get_contact($uinfo[0]['url'], 0, true); + $pcontact_id = Contact::getIdForURL($uinfo[0]['url'], 0, true); $ret = array( 'id' => intval($pcontact_id), @@ -901,7 +903,7 @@ function api_create_xml($data, $root_element) $data3 = array($root_element => $data2); - $ret = XML::from_array($data3, $xml, false, $namespaces); + $ret = XML::fromArray($data3, $xml, false, $namespaces); return $ret; } @@ -3434,11 +3436,7 @@ function api_fr_photoalbum_delete($type) } // now let's delete all photos from the album - $result = q( - "DELETE FROM `photo` WHERE `uid` = %d AND `album` = '%s'", - intval(api_user()), - dbesc($album) - ); + $result = dba::delete('photo', array('uid' => api_user(), 'album' => $album)); // return success of deletion or error message if ($result) { @@ -3721,11 +3719,7 @@ function api_fr_photo_delete($type) throw new BadRequestException("photo not available"); } // now we can perform on the deletion of the photo - $result = q( - "DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'", - intval(api_user()), - dbesc($photo_id) - ); + $result = dba::delete('photo', array('uid' => api_user(), 'resource-id' => $photo_id)); // return success of deletion or error message if ($result) { @@ -3870,10 +3864,10 @@ function api_account_update_profile_image($type) //$user = api_get_user(get_app()); $url = System::baseUrl() . '/profile/' . get_app()->user['nickname']; if ($url && strlen(Config::get('system', 'directory'))) { - Worker::add(PRIORITY_LOW, "directory", $url); + Worker::add(PRIORITY_LOW, "Directory", $url); } - Worker::add(PRIORITY_LOW, 'profile_update', api_user()); + Worker::add(PRIORITY_LOW, 'ProfileUpdate', api_user()); // output for client if ($data) { @@ -4298,7 +4292,7 @@ function api_share_as_retweet(&$item) { $body = trim($item["body"]); - if (Diaspora::is_reshare($body, false)===false) { + if (Diaspora::isReshare($body, false)===false) { return false; } @@ -4306,7 +4300,7 @@ function api_share_as_retweet(&$item) $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body); /* * Skip if there is no shared message in there - * we already checked this in diaspora::is_reshare() + * we already checked this in diaspora::isReshare() * but better one more than one less... */ if ($body == $attributes) { diff --git a/include/auth.php b/include/auth.php index f852ea28a..a02c18d1d 100644 --- a/include/auth.php +++ b/include/auth.php @@ -4,22 +4,31 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Model\User; -require_once('include/security.php'); -require_once('include/datetime.php'); +require_once 'include/security.php'; +require_once 'include/datetime.php'; // When the "Friendica" cookie is set, take the value to authenticate and renew the cookie. if (isset($_COOKIE["Friendica"])) { $data = json_decode($_COOKIE["Friendica"]); if (isset($data->uid)) { - $r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey` - FROM `user` WHERE `uid` = %d AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1", - intval($data->uid) + + $user = dba::select('user', + [], + [ + 'uid' => $data->uid, + 'blocked' => false, + 'account_expired' => false, + 'account_removed' => false, + 'verified' => true, + ], + ['limit' => 1] ); - if ($r) { - if ($data->hash != cookie_hash($r[0])) { - logger("Hash for user ".$data->uid." doesn't fit."); + if (DBM::is_result($user)) { + if ($data->hash != cookie_hash($user)) { + logger("Hash for user " . $data->uid . " doesn't fit."); nuke_session(); goaway(System::baseUrl()); } @@ -28,14 +37,15 @@ if (isset($_COOKIE["Friendica"])) { // Expires after 7 days by default, // can be set via system.auth_cookie_lifetime $authcookiedays = Config::get('system', 'auth_cookie_lifetime', 7); - new_cookie($authcookiedays*24*60*60, $r[0]); + new_cookie($authcookiedays * 24 * 60 * 60, $user); // Do the authentification if not done by now if (!isset($_SESSION) || !isset($_SESSION['authenticated'])) { - authenticate_success($r[0]); + authenticate_success($user); - if (Config::get('system','paranoia')) + if (Config::get('system', 'paranoia')) { $_SESSION['addr'] = $data->ip; + } } } } @@ -44,18 +54,16 @@ if (isset($_COOKIE["Friendica"])) { // login/logout -if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params') || ($_POST['auth-params'] !== 'login'))) { - - if ((x($_POST,'auth-params') && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) { - +if (isset($_SESSION) && x($_SESSION, 'authenticated') && (!x($_POST, 'auth-params') || ($_POST['auth-params'] !== 'login'))) { + if ((x($_POST, 'auth-params') && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) { // process logout request call_hooks("logging_out"); nuke_session(); - info(t('Logged out.').EOL); + info(t('Logged out.') . EOL); goaway(System::baseUrl()); } - if (x($_SESSION,'visitor_id') && !x($_SESSION,'uid')) { + if (x($_SESSION, 'visitor_id') && !x($_SESSION, 'uid')) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($_SESSION['visitor_id']) ); @@ -64,25 +72,29 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' } } - if (x($_SESSION,'uid')) { - + if (x($_SESSION, 'uid')) { // already logged in user returning - - $check = Config::get('system','paranoia'); + $check = Config::get('system', 'paranoia'); // extra paranoia - if the IP changed, log them out if ($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) { - logger('Session address changed. Paranoid setting in effect, blocking session. '. - $_SESSION['addr'].' != '.$_SERVER['REMOTE_ADDR']); + logger('Session address changed. Paranoid setting in effect, blocking session. ' . + $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']); nuke_session(); goaway(System::baseUrl()); } - $r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey` - FROM `user` WHERE `uid` = %d AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1", - intval($_SESSION['uid']) + $user = dba::select('user', + [], + [ + 'uid' => $_SESSION['uid'], + 'blocked' => false, + 'account_expired' => false, + 'account_removed' => false, + 'verified' => true, + ], + ['limit' => 1] ); - - if (!DBM::is_result($r)) { + if (!DBM::is_result($user)) { nuke_session(); goaway(System::baseUrl()); } @@ -91,61 +103,57 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' // stays logged in for a long time, e.g. with "Remember Me" $login_refresh = false; if (!x($_SESSION['last_login_date'])) { - $_SESSION['last_login_date'] = datetime_convert('UTC','UTC'); + $_SESSION['last_login_date'] = datetime_convert('UTC', 'UTC'); } - if (strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0) { - - $_SESSION['last_login_date'] = datetime_convert('UTC','UTC'); + if (strcmp(datetime_convert('UTC', 'UTC', 'now - 12 hours'), $_SESSION['last_login_date']) > 0) { + $_SESSION['last_login_date'] = datetime_convert('UTC', 'UTC'); $login_refresh = true; } - authenticate_success($r[0], false, false, $login_refresh); + authenticate_success($user, false, false, $login_refresh); } } else { - session_unset(); + if ( + !(x($_POST, 'password') && strlen($_POST['password'])) + && ( + x($_POST, 'openid_url') && strlen($_POST['openid_url']) + || x($_POST, 'username') && strlen($_POST['username']) + ) + ) { + $noid = Config::get('system', 'no_openid'); - if (x($_POST,'password') && strlen($_POST['password'])) - $encrypted = hash('whirlpool',trim($_POST['password'])); - else { - if ((x($_POST,'openid_url')) && strlen($_POST['openid_url']) || - (x($_POST,'username')) && strlen($_POST['username'])) { + $openid_url = trim(strlen($_POST['openid_url']) ? $_POST['openid_url'] : $_POST['username']); - $noid = Config::get('system','no_openid'); + // validate_url alters the calling parameter - $openid_url = trim((strlen($_POST['openid_url'])?$_POST['openid_url']:$_POST['username'])); + $temp_string = $openid_url; - // validate_url alters the calling parameter + // if it's an email address or doesn't resolve to a URL, fail. - $temp_string = $openid_url; - - // if it's an email address or doesn't resolve to a URL, fail. - - if ($noid || strpos($temp_string,'@') || !validate_url($temp_string)) { - $a = get_app(); - notice(t('Login failed.').EOL); - goaway(System::baseUrl()); - // NOTREACHED - } - - // Otherwise it's probably an openid. - - try { - require_once('library/openid.php'); - $openid = new LightOpenID; - $openid->identity = $openid_url; - $_SESSION['openid'] = $openid_url; - $_SESSION['remember'] = $_POST['remember']; - $openid->returnUrl = System::baseUrl(true).'/openid'; - goaway($openid->authUrl()); - } catch (Exception $e) { - notice(t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'
'.t('The error message was:').' '.$e->getMessage()); - } + if ($noid || strpos($temp_string, '@') || !validate_url($temp_string)) { + $a = get_app(); + notice(t('Login failed.') . EOL); + goaway(System::baseUrl()); // NOTREACHED } + + // Otherwise it's probably an openid. + + try { + require_once('library/openid.php'); + $openid = new LightOpenID; + $openid->identity = $openid_url; + $_SESSION['openid'] = $openid_url; + $_SESSION['remember'] = $_POST['remember']; + $openid->returnUrl = System::baseUrl(true) . '/openid'; + goaway($openid->authUrl()); + } catch (Exception $e) { + notice(t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.') . '
' . t('The error message was:') . ' ' . $e->getMessage()); + } + // NOTREACHED } - if (x($_POST,'auth-params') && $_POST['auth-params'] === 'login') { - + if (x($_POST, 'auth-params') && $_POST['auth-params'] === 'login') { $record = null; $addon_auth = array( @@ -162,39 +170,30 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' * and later plugins should not interfere with an earlier one that succeeded. * */ - call_hooks('authenticate', $addon_auth); - if ($addon_auth['authenticated'] && count($addon_auth['user_record'])) + if ($addon_auth['authenticated'] && count($addon_auth['user_record'])) { $record = $addon_auth['user_record']; - else { - - // process normal login request - - $r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey` - FROM `user` WHERE (`email` = '%s' OR `nickname` = '%s') - AND `password` = '%s' AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1", - dbesc(trim($_POST['username'])), - dbesc(trim($_POST['username'])), - dbesc($encrypted) - ); - if (DBM::is_result($r)) - $record = $r[0]; + } else { + $user_id = User::authenticate(trim($_POST['username']), trim($_POST['password'])); + if ($user_id) { + $record = dba::select('user', [], ['uid' => $user_id], ['limit' => 1]); + } } if (!$record || !count($record)) { - logger('authenticate: failed login attempt: '.notags(trim($_POST['username'])).' from IP '.$_SERVER['REMOTE_ADDR']); - notice(t('Login failed.').EOL); + logger('authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR']); + notice(t('Login failed.') . EOL); goaway(System::baseUrl()); } - if (! $_POST['remember']) { + if (!$_POST['remember']) { new_cookie(0); // 0 means delete on browser exit } // if we haven't failed up this point, log them in. $_SESSION['remember'] = $_POST['remember']; - $_SESSION['last_login_date'] = datetime_convert('UTC','UTC'); + $_SESSION['last_login_date'] = datetime_convert('UTC', 'UTC'); authenticate_success($record, true, true); } } @@ -202,8 +201,8 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' /** * @brief Kills the "Friendica" cookie and all session data */ -function nuke_session() { - +function nuke_session() +{ new_cookie(-3600); // make sure cookie is deleted on browser close, as a security measure session_unset(); session_destroy(); diff --git a/include/auth_ejabberd.php b/include/auth_ejabberd.php deleted file mode 100755 index fff2bab32..000000000 --- a/include/auth_ejabberd.php +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/php - - * modified for Friendica by Michael Vogel- * published under GPL - * - * Latest version of the original script for joomla is available at: - * http://87.230.15.86/~dado/ejabberd/joomla-login - * - * Installation: - * - * - Change it's owner to whichever user is running the server, ie. ejabberd - * $ chown ejabberd:ejabberd /path/to/friendica/include/auth_ejabberd.php - * - * - Change the access mode so it is readable only to the user ejabberd and has exec - * $ chmod 700 /path/to/friendica/include/auth_ejabberd.php - * - * - Edit your ejabberd.cfg file, comment out your auth_method and add: - * {auth_method, external}. - * {extauth_program, "/path/to/friendica/include/auth_ejabberd.php"}. - * - * - Restart your ejabberd service, you should be able to login with your friendica auth info - * - * Other hints: - * - if your users have a space or a @ in their nickname, they'll run into trouble - * registering with any client so they should be instructed to replace these chars - * " " (space) is replaced with "%20" - * "@" is replaced with "(a)" - * - */ - -use Friendica\App; -use Friendica\Core\Config; -use Friendica\Database\DBM; - -if (sizeof($_SERVER["argv"]) == 0) - die(); - -$directory = dirname($_SERVER["argv"][0]); - -if (substr($directory, 0, 1) != "/") - $directory = $_SERVER["PWD"]."/".$directory; - -$directory = realpath($directory."/.."); - -chdir($directory); -require_once("boot.php"); - -global $a; - -if (empty($a)) { - $a = new App(dirname(__DIR__)); -} - -@include(".htconfig.php"); -require_once("include/dba.php"); -dba::connect($db_host, $db_user, $db_pass, $db_data); -unset($db_host, $db_user, $db_pass, $db_data); - -$oAuth = new exAuth(); - -class exAuth { - private $bDebug; - - /** - * @brief Create the class and do the authentification studd - * - * @param boolean $bDebug Debug mode - */ - public function __construct() { - // setter - $this->bDebug = (int)Config::get('jabber', 'debug'); - - - openlog('auth_ejabberd', LOG_PID, LOG_USER); - - $this->writeLog(LOG_NOTICE, "start"); - - // We are connected to the SQL server. - while (!feof(STDIN)) { - // Quit if the database connection went down - if (!dba::connected()) { - $this->writeLog(LOG_ERR, "the database connection went down"); - return; - } - - $iHeader = fgets(STDIN, 3); - $aLength = unpack("n", $iHeader); - $iLength = $aLength["1"]; - - // No data? Then quit - if ($iLength == 0) { - $this->writeLog(LOG_ERR, "we got no data, quitting"); - return; - } - - // Fetching the data - $sData = fgets(STDIN, $iLength + 1); - $this->writeLog(LOG_DEBUG, "received data: ". $sData); - $aCommand = explode(":", $sData); - if (is_array($aCommand)) { - switch ($aCommand[0]) { - case "isuser": - // Check the existance of a given username - $this->isuser($aCommand); - break; - case "auth": - // Check if the givven password is correct - $this->auth($aCommand); - break; - case "setpass": - // We don't accept the setting of passwords here - $this->writeLog(LOG_NOTICE, "setpass command disabled"); - fwrite(STDOUT, pack("nn", 2, 0)); - break; - default: - // We don't know the given command - $this->writeLog(LOG_NOTICE, "unknown command ". $aCommand[0]); - fwrite(STDOUT, pack("nn", 2, 0)); - break; - } - } else { - $this->writeLog(LOG_NOTICE, "invalid command string ".$sData); - fwrite(STDOUT, pack("nn", 2, 0)); - } - } - } - - /** - * @brief Check if the given username exists - * - * @param array $aCommand The command array - */ - private function isuser($aCommand) { - $a = get_app(); - - // Check if there is a username - if (!isset($aCommand[1])) { - $this->writeLog(LOG_NOTICE, "invalid isuser command, no username given"); - fwrite(STDOUT, pack("nn", 2, 0)); - return; - } - - // Now we check if the given user is valid - $sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]); - - // Does the hostname match? So we try directly - if ($a->get_hostname() == $aCommand[2]) { - $this->writeLog(LOG_INFO, "internal user check for ". $sUser."@".$aCommand[2]); - $sQuery = "SELECT `uid` FROM `user` WHERE `nickname`='".dbesc($sUser)."'"; - $this->writeLog(LOG_DEBUG, "using query ". $sQuery); - $r = q($sQuery); - $found = DBM::is_result($r); - } else { - $found = false; - } - - // If the hostnames doesn't match or there is some failure, we try to check remotely - if (!$found) { - $found = $this->check_user($aCommand[2], $aCommand[1], true); - } - - if ($found) { - // The user is okay - $this->writeLog(LOG_NOTICE, "valid user: ". $sUser); - fwrite(STDOUT, pack("nn", 2, 1)); - } else { - // The user isn't okay - $this->writeLog(LOG_WARNING, "invalid user: ". $sUser); - fwrite(STDOUT, pack("nn", 2, 0)); - } - } - - /** - * @brief Check remote user existance via HTTP(S) - * - * @param string $host The hostname - * @param string $user Username - * @param boolean $ssl Should the check be done via SSL? - * - * @return boolean Was the user found? - */ - private function check_user($host, $user, $ssl) { - - $this->writeLog(LOG_INFO, "external user check for ".$user."@".$host); - - $url = ($ssl ? "https":"http")."://".$host."/noscrape/".$user; - - $data = z_fetch_url($url); - - if (!is_array($data)) - return(false); - - if ($data["return_code"] != "200") - return(false); - - $json = @json_decode($data["body"]); - if (!is_object($json)) - return(false); - - return($json->nick == $user); - } - - /** - * @brief Authenticate the givven user and password - * - * @param array $aCommand The command array - */ - private function auth($aCommand) { - $a = get_app(); - - // check user authentication - if (sizeof($aCommand) != 4) { - $this->writeLog(LOG_NOTICE, "invalid auth command, data missing"); - fwrite(STDOUT, pack("nn", 2, 0)); - return; - } - - // We now check if the password match - $sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]); - - // Does the hostname match? So we try directly - if ($a->get_hostname() == $aCommand[2]) { - $this->writeLog(LOG_INFO, "internal auth for ".$sUser."@".$aCommand[2]); - - $sQuery = "SELECT `uid`, `password` FROM `user` WHERE `nickname`='".dbesc($sUser)."'"; - $this->writeLog(LOG_DEBUG, "using query ". $sQuery); - if ($oResult = q($sQuery)) { - $uid = $oResult[0]["uid"]; - $Error = ($oResult[0]["password"] != hash('whirlpool',$aCommand[3])); - } else { - $this->writeLog(LOG_WARNING, "invalid query: ". $sQuery); - $Error = true; - $uid = -1; - } - if ($Error) { - $oConfig = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = 'xmpp' AND `k`='password' LIMIT 1;", intval($uid)); - $this->writeLog(LOG_INFO, "check against alternate password for ".$sUser."@".$aCommand[2]); - $Error = ($aCommand[3] != $oConfig[0]["v"]); - } - } else { - $Error = true; - } - - // If the hostnames doesn't match or there is some failure, we try to check remotely - if ($Error) { - $Error = !$this->check_credentials($aCommand[2], $aCommand[1], $aCommand[3], true); - } - - if ($Error) { - $this->writeLog(LOG_WARNING, "authentification failed for user ".$sUser."@". $aCommand[2]); - fwrite(STDOUT, pack("nn", 2, 0)); - } else { - $this->writeLog(LOG_NOTICE, "authentificated user ".$sUser."@".$aCommand[2]); - fwrite(STDOUT, pack("nn", 2, 1)); - } - } - - /** - * @brief Check remote credentials via HTTP(S) - * - * @param string $host The hostname - * @param string $user Username - * @param string $password Password - * @param boolean $ssl Should the check be done via SSL? - * - * @return boolean Are the credentials okay? - */ - private function check_credentials($host, $user, $password, $ssl) { - $url = ($ssl ? "https":"http")."://".$host."/api/account/verify_credentials.json"; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); - curl_setopt($ch, CURLOPT_HEADER, true); - curl_setopt($ch, CURLOPT_NOBODY, true); - curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password); - - $header = curl_exec($ch); - $curl_info = @curl_getinfo($ch); - $http_code = $curl_info["http_code"]; - curl_close($ch); - - $this->writeLog(LOG_INFO, "external auth for ".$user."@".$host." returned ".$http_code); - - return ($http_code == 200); - } - - /** - * @brief write data to the syslog - * - * @param integer $loglevel The syslog loglevel - * @param string $sMessage The syslog message - */ - private function writeLog($loglevel, $sMessage) { - if (!$this->bDebug && ($loglevel >= LOG_DEBUG)) { - return; - } - syslog($loglevel, $sMessage); - } - - /** - * @brief destroy the class, close the syslog connection. - */ - public function __destruct() { - $this->writeLog(LOG_NOTICE, "stop"); - closelog(); - } -} diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index 20309b9d2..3b1540473 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Network\Probe; +use Friendica\Object\Contact; use League\HTMLToMarkdown\HtmlConverter; @@ -23,7 +24,7 @@ function diaspora_mention2bb($match) { return; } - $data = get_contact_details_by_addr($match[2]); + $data = Contact::getDetailsByAddr($match[2]); $name = $match[1]; @@ -96,7 +97,7 @@ function diaspora2bb($s) { */ function diaspora_mentions($match) { - $contact = get_contact_details_by_url($match[3]); + $contact = Contact::getDetailsByURL($match[3]); if (!x($contact, 'addr')) { $contact = Probe::uri($match[3]); diff --git a/include/bbcode.php b/include/bbcode.php index a61160547..196c3ca3c 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1,17 +1,17 @@ set_baseurl(Config::get('system','url')); - - load_hooks(); -} diff --git a/include/contact_widgets.php b/include/contact_widgets.php index d47cf86c3..5108eaf72 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -1,10 +1,10 @@ sprintf( tt("%d contact in common", "%d contacts in common", $t), $t), + '$desc' => sprintf(tt("%d contact in common", "%d contacts in common", $t), $t), '$base' => System::baseUrl(), '$uid' => $profile_uid, '$cid' => (($cid) ? $cid : '0'), '$linkmore' => (($t > 5) ? 'true' : ''), '$more' => t('show more'), - '$items' => $r - )); - -}; + '$items' => $r) + ); +} diff --git a/include/conversation.php b/include/conversation.php index 0e814c666..bba852e7a 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1,10 +1,15 @@ theme['template_engine'] === 'internal') { - $profile_name_e = template_escape($profile_name); - $item['title_e'] = template_escape($item['title']); - $body_e = template_escape($body); - $tags_e = template_escape($tags); - $hashtags_e = template_escape($hashtags); - $mentions_e = template_escape($mentions); - $location_e = template_escape($location); - $owner_name_e = template_escape($owner_name); - } else { - $profile_name_e = $profile_name; - $item['title_e'] = $item['title']; - $body_e = $body; - $tags_e = $tags; - $hashtags_e = $hashtags; - $mentions_e = $mentions; - $location_e = $location; - $owner_name_e = $owner_name; - } + $profile_name_e = $profile_name; + $item['title_e'] = $item['title']; + $body_e = $body; + $tags_e = $tags; + $hashtags_e = $hashtags; + $mentions_e = $mentions; + $location_e = $location; + $owner_name_e = $owner_name; if ($item['item_network'] == "") { $item['item_network'] = $item['network']; @@ -860,9 +853,6 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { // Normal View $page_template = get_markup_template("threaded_conversation.tpl"); - require_once 'object/Conversation.php'; - require_once 'object/Item.php'; - $conv = new Conversation($mode, $preview); /* @@ -904,11 +894,11 @@ function conversation(App $a, $items, $mode, $update, $preview = false) { if ($item['id'] == $item['parent']) { $item_object = new Item($item); - $conv->add_thread($item_object); + $conv->addThread($item_object); } } - $threads = $conv->get_template_data($conv_responses); + $threads = $conv->getTemplateData($conv_responses); if (!$threads) { logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG); @@ -1360,13 +1350,22 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false) { return $o; } - -function get_item_children($arr, $parent) { - $children = array(); - $a = get_app(); - foreach ($arr as $item) { +/** + * Plucks the children of the given parent from a given item list. + * + * @brief Plucks all the children in the given item list of the given parent + * + * @param array $item_list + * @param array $parent + * @param bool $recursive + * @return type + */ +function get_item_children(array &$item_list, array $parent, $recursive = true) +{ + $children = []; + foreach ($item_list as $i => $item) { if ($item['id'] != $item['parent']) { - if (Config::get('system', 'thread_allow') && $a->theme_thread_allow) { + if ($recursive) { // Fallback to parent-uri if thr-parent is not set $thr_parent = $item['thr-parent']; if ($thr_parent == '') { @@ -1374,65 +1373,141 @@ function get_item_children($arr, $parent) { } if ($thr_parent == $parent['uri']) { - $item['children'] = get_item_children($arr, $item); + $item['children'] = get_item_children($item_list, $item); $children[] = $item; + unset($item_list[$i]); } } elseif ($item['parent'] == $parent['id']) { $children[] = $item; + unset($item_list[$i]); } } } return $children; } -/// @TODO Add type-hint -function sort_item_children($items) { +/** + * @brief Recursively sorts a tree-like item array + * + * @param array $items + * @return array + */ +function sort_item_children(array $items) +{ $result = $items; usort($result, 'sort_thr_created_rev'); foreach ($result as $k => $i) { - if (count($result[$k]['children'])) { + if (isset($result[$k]['children'])) { $result[$k]['children'] = sort_item_children($result[$k]['children']); } } return $result; } -/// @TODO Add type-hint -function add_children_to_list($children, &$arr) { - foreach ($children as $y) { - $arr[] = $y; - if (count($y['children'])) { - add_children_to_list($y['children'], $arr); +/** + * @brief Recursively add all children items at the top level of a list + * + * @param array $children List of items to append + * @param array $item_list + */ +function add_children_to_list(array $children, array &$item_list) +{ + foreach ($children as $child) { + $item_list[] = $child; + if (isset($child['children'])) { + add_children_to_list($child['children'], $item_list); } } } -/// @TODO Add type-hint -function conv_sort($arr, $order) { - - if ((!(is_array($arr) && count($arr)))) { - return array(); +/** + * This recursive function takes the item tree structure created by conv_sort() and + * flatten the extraneous depth levels when people reply sequentially, removing the + * stairs effect in threaded conversations limiting the available content width. + * + * The basic principle is the following: if a post item has only one reply and is + * the last reply of its parent, then the reply is moved to the parent. + * + * This process is rendered somewhat more complicated because items can be either + * replies or likes, and these don't factor at all in the reply count/last reply. + * + * @brief Selectively flattens a tree-like item structure to prevent threading stairs + * + * @param array $parent A tree-like array of items + * @return array + */ +function smart_flatten_conversation(array $parent) +{ + if (! isset($parent['children']) || count($parent['children']) == 0) { + return $parent; } - $parents = array(); - $children = array(); - $newarr = array(); + // We use a for loop to ensure we process the newly-moved items + for ($i = 0; $i < count($parent['children']); $i++) { + $child = $parent['children'][$i]; - /* - * This is a preparation for having two different items with the same uri in one thread - * This will otherwise lead to an endless loop. - */ - foreach ($arr as $x) { - if (!isset($newarr[$x['uri']])) { - $newarr[$x['uri']] = $x; + if (isset($child['children']) && count($child['children'])) { + // This helps counting only the regular posts + $count_post_closure = function($var) { + return $var['verb'] === ACTIVITY_POST; + }; + + $child_post_count = count(array_filter($child['children'], $count_post_closure)); + + $remaining_post_count = count(array_filter(array_slice($parent['children'], $i), $count_post_closure)); + + // If there's only one child's children post and this is the last child post + if ($child_post_count == 1 && $remaining_post_count == 1) { + + // Searches the post item in the children + $j = 0; + while($child['children'][$j]['verb'] !== ACTIVITY_POST && $j < count($child['children'])) { + $j ++; + } + + $moved_item = $child['children'][$j]; + unset($parent['children'][$i]['children'][$j]); + $parent['children'][] = $moved_item; + } else { + $parent['children'][$i] = smart_flatten_conversation($child); + } } } - $arr = $newarr; + return $parent; +} - foreach ($arr as $x) { - if ($x['id'] == $x['parent']) { - $parents[] = $x; + +/** + * Expands a flat list of items into corresponding tree-like conversation structures, + * sort the top-level posts either on "created" or "commented", and finally + * append all the items at the top level (???) + * + * @brief Expands a flat item list into a conversation array for display + * + * @param array $item_list A list of items belonging to one or more conversations + * @param string $order Either on "created" or "commented" + * @return array + */ +function conv_sort(array $item_list, $order) +{ + $parents = []; + + if (!(is_array($item_list) && count($item_list))) { + return $parents; + } + + $item_array = []; + + // Dedupes the item list on the uri to prevent infinite loops + foreach ($item_list as $item) { + $item_array[$item['uri']] = $item; + } + + // Extract the top level items + foreach ($item_array as $item) { + if ($item['id'] == $item['parent']) { + $parents[] = $item; } } @@ -1442,73 +1517,73 @@ function conv_sort($arr, $order) { usort($parents, 'sort_thr_commented'); } - if (count($parents)) { - foreach ($parents as $i => $_x) { - $parents[$i]['children'] = get_item_children($arr, $_x); + /* + * Plucks children from the item_array, second pass collects eventual orphan + * items and add them as children of their top-level post. + */ + foreach ($parents as $i => $parent) { + $parents[$i]['children'] = + array_merge(get_item_children($item_array, $parent, true), + get_item_children($item_array, $parent, false)); + } + + foreach ($parents as $i => $parent) { + $parents[$i]['children'] = sort_item_children($parents[$i]['children']); + } + + if (PConfig::get(local_user(), 'system', 'smart_threading', 0)) { + foreach ($parents as $i => $parent) { + $parents[$i] = smart_flatten_conversation($parent); } } - /// @TODO Old-lost code? - /*foreach ($arr as $x) { - if ($x['id'] != $x['parent']) { - $p = find_thread_parent_index($parents,$x); - if ($p !== false) - $parents[$p]['children'][] = $x; - } - }*/ - if (count($parents)) { - foreach ($parents as $k => $v) { - if (count($parents[$k]['children'])) { - $parents[$k]['children'] = sort_item_children($parents[$k]['children']); - /// @TODO Old-lost code? - /*$y = $parents[$k]['children']; - usort($y,'sort_thr_created_rev'); - $parents[$k]['children'] = $y;*/ - } + /// @TODO: Stop recusrsively adding all children back to the top level (!!!) + /// However, this apparently ensures responses (likes, attendance) display (?!) + foreach ($parents as $parent) { + if (count($parent['children'])) { + add_children_to_list($parent['children'], $parents); } } - $ret = array(); - if (count($parents)) { - foreach ($parents as $x) { - $ret[] = $x; - if (count($x['children'])) { - add_children_to_list($x['children'], $ret); - /// @TODO Old-lost code? - /*foreach ($x['children'] as $y) - $ret[] = $y;*/ - } - } - } - - return $ret; + return $parents; } -/// @TODO Add type-hint -function sort_thr_created($a, $b) { +/** + * @brief usort() callback to sort item arrays by the created key + * + * @param array $a + * @param array $b + * @return int + */ +function sort_thr_created(array $a, array $b) +{ return strcmp($b['created'], $a['created']); } -/// @TODO Add type-hint -function sort_thr_created_rev($a, $b) { +/** + * @brief usort() callback to reverse sort item arrays by the created key + * + * @param array $a + * @param array $b + * @return int + */ +function sort_thr_created_rev(array $a, array $b) +{ return strcmp($a['created'], $b['created']); } -/// @TODO Add type-hint -function sort_thr_commented($a, $b) { +/** + * @brief usort() callback to sort item arrays by the commented key + * + * @param array $a + * @param array $b + * @return type + */ +function sort_thr_commented(array $a, array $b) +{ return strcmp($b['commented'], $a['commented']); } -/// @TODO Add type-hint -function find_thread_parent_index($arr, $x) { - foreach ($arr as $k => $v) { - if ($v['id'] == $x['parent']) { - return $k; - } - } - return false; -} - /// @TODO Add type-hint function render_location_dummy($item) { if ($item['location'] != "") { @@ -1531,7 +1606,7 @@ function get_responses($conv_responses, $response_verbs, $ob, $item) { 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'], '' . t('View all') . ''); + . (($ob) ? $ob->getId() : $item['id']) . '">' . t('View all') . ''); } else { $ret[$v]['list_part'] = ''; } diff --git a/include/create_shadowentry.php b/include/create_shadowentry.php deleted file mode 100644 index 29222de5e..000000000 --- a/include/create_shadowentry.php +++ /dev/null @@ -1,19 +0,0 @@ - 1) { - cron_poll_contacts($argc, $argv); - return; - } - - $last = Config::get('system', 'last_cron'); - - $poll_interval = intval(Config::get('system', 'cron_interval')); - if (! $poll_interval) { - $poll_interval = 10; - } - - if ($last) { - $next = $last + ($poll_interval * 60); - if ($next > time()) { - logger('cron intervall not reached'); - return; - } - } - - logger('cron: start'); - - // run queue delivery process in the background - Worker::add(PRIORITY_NEGLIGIBLE, "queue"); - - // run the process to discover global contacts in the background - Worker::add(PRIORITY_LOW, "discover_poco"); - - // run the process to update locally stored global contacts in the background - Worker::add(PRIORITY_LOW, "discover_poco", "checkcontact"); - - // Expire and remove user entries - Worker::add(PRIORITY_MEDIUM, "cronjobs", "expire_and_remove_users"); - - // Call possible post update functions - Worker::add(PRIORITY_LOW, "cronjobs", "post_update"); - - // update nodeinfo data - Worker::add(PRIORITY_LOW, "cronjobs", "nodeinfo"); - - // Clear cache entries - Worker::add(PRIORITY_LOW, "cronjobs", "clear_cache"); - - // Repair missing Diaspora values in contacts - Worker::add(PRIORITY_LOW, "cronjobs", "repair_diaspora"); - - // Repair entries in the database - Worker::add(PRIORITY_LOW, "cronjobs", "repair_database"); - - // once daily run birthday_updates and then expire in background - $d1 = Config::get('system', 'last_expire_day'); - $d2 = intval(datetime_convert('UTC', 'UTC', 'now', 'd')); - - if ($d2 != intval($d1)) { - - Worker::add(PRIORITY_LOW, "cronjobs", "update_contact_birthdays"); - - Worker::add(PRIORITY_LOW, "discover_poco", "update_server"); - - Worker::add(PRIORITY_LOW, "discover_poco", "suggestions"); - - Config::set('system', 'last_expire_day', $d2); - - Worker::add(PRIORITY_LOW, 'expire'); - - Worker::add(PRIORITY_MEDIUM, 'dbclean'); - - Worker::add(PRIORITY_LOW, "cronjobs", "update_photo_albums"); - - // Delete all done workerqueue entries - dba::delete('workerqueue', array('`done` AND `executed` < UTC_TIMESTAMP() - INTERVAL 12 HOUR')); - - // check upstream version? - Worker::add(PRIORITY_LOW, 'checkversion'); - } - - // Poll contacts - cron_poll_contacts($argc, $argv); - - logger('cron: end'); - - Config::set('system', 'last_cron', time()); - - return; -} - -/** - * @brief Poll contacts for unreceived messages - * - * @param Integer $argc Number of command line arguments - * @param Array $argv Array of command line arguments - */ -function cron_poll_contacts($argc, $argv) { - $manual_id = 0; - $generation = 0; - $force = false; - $restart = false; - - if (($argc > 1) && ($argv[1] == 'force')) { - $force = true; - } - if (($argc > 1) && ($argv[1] == 'restart')) { - $restart = true; - $generation = intval($argv[2]); - if (!$generation) { - killme(); - } - } - - if (($argc > 1) && intval($argv[1])) { - $manual_id = intval($argv[1]); - $force = true; - } - - $min_poll_interval = Config::get('system', 'min_poll_interval', 1); - - $sql_extra = (($manual_id) ? " AND `id` = $manual_id " : ""); - - reload_plugins(); - - $d = datetime_convert(); - - // Only poll from those with suitable relationships, - // and which have a polling address and ignore Diaspora since - // we are unable to match those posts with a Diaspora GUID and prevent duplicates. - - $abandon_days = intval(Config::get('system', 'account_abandon_days')); - if ($abandon_days < 1) { - $abandon_days = 0; - } - $abandon_sql = (($abandon_days) - ? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days)) - : '' - ); - - $contacts = q("SELECT `contact`.`id` FROM `user` - STRAIGHT_JOIN `contact` - ON `contact`.`uid` = `user`.`uid` AND `contact`.`rel` IN (%d, %d) AND `contact`.`poll` != '' - AND `contact`.`network` IN ('%s', '%s', '%s', '%s', '%s', '%s') $sql_extra - AND NOT `contact`.`self` AND NOT `contact`.`blocked` AND NOT `contact`.`readonly` - AND NOT `contact`.`archive` - WHERE NOT `user`.`account_expired` AND NOT `user`.`account_removed` $abandon_sql ORDER BY RAND()", - intval(CONTACT_IS_SHARING), - intval(CONTACT_IS_FRIEND), - dbesc(NETWORK_DFRN), - dbesc(NETWORK_ZOT), - dbesc(NETWORK_OSTATUS), - dbesc(NETWORK_FEED), - dbesc(NETWORK_MAIL), - dbesc(NETWORK_MAIL2) - ); - - if (!DBM::is_result($contacts)) { - return; - } - - foreach ($contacts as $c) { - - $res = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", - intval($c['id']) - ); - - if (!DBM::is_result($res)) { - continue; - } - - foreach ($res as $contact) { - - $xml = false; - - if ($manual_id) { - $contact['last-update'] = NULL_DATE; - } - - if (in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) { - $contact['priority'] = 2; - } - - if ($contact['subhub'] && in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) { - /* - * We should be getting everything via a hub. But just to be sure, let's check once a day. - * (You can make this more or less frequent if desired by setting 'pushpoll_frequency' appropriately) - * This also lets us update our subscription to the hub, and add or replace hubs in case it - * changed. We will only update hubs once a day, regardless of 'pushpoll_frequency'. - */ - $poll_interval = Config::get('system', 'pushpoll_frequency'); - $contact['priority'] = (($poll_interval !== false) ? intval($poll_interval) : 3); - } - - if (($contact['priority'] >= 0) && !$force) { - $update = false; - - $t = $contact['last-update']; - - /* - * Based on $contact['priority'], should we poll this site now? Or later? - */ - switch ($contact['priority']) { - case 5: - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 month")) { - $update = true; - } - break; - case 4: - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 week")) { - $update = true; - } - break; - case 3: - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 day")) { - $update = true; - } - break; - case 2: - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 12 hour")) { - $update = true; - } - break; - case 1: - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 hour")) { - $update = true; - } - break; - case 0: - default: - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + ".$min_poll_interval." minute")) { - $update = true; - } - break; - } - if (!$update) { - continue; - } - } - - logger("Polling " . $contact["network"] . " " . $contact["id"] . " " . $contact["nick"] . " " . $contact["name"]); - - if (($contact['network'] == NETWORK_FEED) && ($contact['priority'] <= 3)) { - $priority = PRIORITY_MEDIUM; - } else { - $priority = PRIORITY_LOW; - } - Worker::add(array('priority' => $priority, 'dont_fork' => true), 'onepoll', (int)$contact['id']); - } - } -} diff --git a/include/cronhooks.php b/include/cronhooks.php deleted file mode 100644 index 5f15c9379..000000000 --- a/include/cronhooks.php +++ /dev/null @@ -1,54 +0,0 @@ -hooks) && array_key_exists("cron", $a->hooks)) { - foreach ($a->hooks["cron"] as $hook) { - if ($hook[1] == $argv[1]) { - logger("Calling cron hook '" . $hook[1] . "'", LOGGER_DEBUG); - call_single_hook($a, $name, $hook, $data); - } - } - return; - } - - $last = Config::get('system', 'last_cronhook'); - - $poll_interval = intval(Config::get('system', 'cronhook_interval')); - if (! $poll_interval) { - $poll_interval = 9; - } - - if ($last) { - $next = $last + ($poll_interval * 60); - if ($next > time()) { - logger('cronhook intervall not reached'); - return; - } - } - - $a->set_baseurl(Config::get('system', 'url')); - - logger('cronhooks: start'); - - $d = datetime_convert(); - - if (is_array($a->hooks) && array_key_exists("cron", $a->hooks)) { - foreach ($a->hooks["cron"] as $hook) { - logger("Calling cronhooks for '" . $hook[1] . "'", LOGGER_DEBUG); - Worker::add(PRIORITY_MEDIUM, "cronhooks", $hook[1]); - } - } - - logger('cronhooks: end'); - - Config::set('system', 'last_cronhook', time()); - - return; -} diff --git a/include/cronjobs.php b/include/cronjobs.php deleted file mode 100644 index 00064b112..000000000 --- a/include/cronjobs.php +++ /dev/null @@ -1,278 +0,0 @@ - '%s' - AND `account_expires_on` < UTC_TIMESTAMP()", dbesc(NULL_DATE)); - - // delete user records for recently removed accounts - $r = q("SELECT * FROM `user` WHERE `account_removed` AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY"); - if (DBM::is_result($r)) { - foreach ($r as $user) { - dba::delete('user', array('uid' => $user['uid'])); - } - } -} - -/** - * @brief Clear cache entries - * - * @param App $a - */ -function cron_clear_cache(App $a) { - - $last = Config::get('system','cache_last_cleared'); - - if ($last) { - $next = $last + (3600); // Once per hour - $clear_cache = ($next <= time()); - } else { - $clear_cache = true; - } - - if (!$clear_cache) { - return; - } - - // clear old cache - Cache::clear(); - - // clear old item cache files - clear_cache(); - - // clear cache for photos - clear_cache($a->get_basepath(), $a->get_basepath()."/photo"); - - // clear smarty cache - clear_cache($a->get_basepath()."/view/smarty3/compiled", $a->get_basepath()."/view/smarty3/compiled"); - - // clear cache for image proxy - if (!Config::get("system", "proxy_disabled")) { - clear_cache($a->get_basepath(), $a->get_basepath()."/proxy"); - - $cachetime = Config::get('system','proxy_cache_time'); - if (!$cachetime) { - $cachetime = PROXY_DEFAULT_TIME; - } - q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime); - } - - // Delete the cached OEmbed entries that are older than one year - q("DELETE FROM `oembed` WHERE `created` < NOW() - INTERVAL 3 MONTH"); - - // Delete the cached "parse_url" entries that are older than one year - q("DELETE FROM `parsed_url` WHERE `created` < NOW() - INTERVAL 3 MONTH"); - - // Maximum table size in megabyte - $max_tablesize = intval(Config::get('system','optimize_max_tablesize')) * 1000000; - if ($max_tablesize == 0) { - $max_tablesize = 100 * 1000000; // Default are 100 MB - } - if ($max_tablesize > 0) { - // Minimum fragmentation level in percent - $fragmentation_level = intval(Config::get('system','optimize_fragmentation')) / 100; - if ($fragmentation_level == 0) { - $fragmentation_level = 0.3; // Default value is 30% - } - - // Optimize some tables that need to be optimized - $r = q("SHOW TABLE STATUS"); - foreach ($r as $table) { - - // Don't optimize tables that are too large - if ($table["Data_length"] > $max_tablesize) { - continue; - } - - // Don't optimize empty tables - if ($table["Data_length"] == 0) { - continue; - } - - // Calculate fragmentation - $fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]); - - logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG); - - // Don't optimize tables that needn't to be optimized - if ($fragmentation < $fragmentation_level) { - continue; - } - - // So optimize it - logger("Optimize Table ".$table["Name"], LOGGER_DEBUG); - q("OPTIMIZE TABLE `%s`", dbesc($table["Name"])); - } - } - - Config::set('system','cache_last_cleared', time()); -} - -/** - * @brief Repair missing values in Diaspora contacts - * - * @param App $a - */ -function cron_repair_diaspora(App $a) { - - $starttime = time(); - - $r = q("SELECT `id`, `url` FROM `contact` - WHERE `network` = '%s' AND (`batch` = '' OR `notify` = '' OR `poll` = '' OR pubkey = '') - ORDER BY RAND() LIMIT 50", dbesc(NETWORK_DIASPORA)); - if (!DBM::is_result($r)) { - return; - } - - foreach ($r AS $contact) { - // Quit the loop after 3 minutes - if (time() > ($starttime + 180)) { - return; - } - - if (!poco_reachable($contact["url"])) { - continue; - } - - $data = Probe::uri($contact["url"]); - if ($data["network"] != NETWORK_DIASPORA) { - continue; - } - - logger("Repair contact ".$contact["id"]." ".$contact["url"], LOGGER_DEBUG); - q("UPDATE `contact` SET `batch` = '%s', `notify` = '%s', `poll` = '%s', pubkey = '%s' WHERE `id` = %d", - dbesc($data["batch"]), dbesc($data["notify"]), dbesc($data["poll"]), dbesc($data["pubkey"]), - intval($contact["id"])); - } -} - -/** - * @brief Do some repairs in database entries - * - */ -function cron_repair_database() { - - // Sometimes there seem to be issues where the "self" contact vanishes. - // We haven't found the origin of the problem by now. - $r = q("SELECT `uid` FROM `user` WHERE NOT EXISTS (SELECT `uid` FROM `contact` WHERE `contact`.`uid` = `user`.`uid` AND `contact`.`self`)"); - if (DBM::is_result($r)) { - foreach ($r AS $user) { - logger('Create missing self contact for user '.$user['uid']); - user_create_self_contact($user['uid']); - } - } - - // Set the parent if it wasn't set. (Shouldn't happen - but does sometimes) - // This call is very "cheap" so we can do it at any time without a problem - q("UPDATE `item` INNER JOIN `item` AS `parent` ON `parent`.`uri` = `item`.`parent-uri` AND `parent`.`uid` = `item`.`uid` SET `item`.`parent` = `parent`.`id` WHERE `item`.`parent` = 0"); - - // There was an issue where the nick vanishes from the contact table - q("UPDATE `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` SET `nick` = `nickname` WHERE `self` AND `nick`=''"); - - // Update the global contacts for local users - $r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`"); - if (DBM::is_result($r)) { - foreach ($r AS $user) { - update_gcontact_for_user($user["uid"]); - } - } - - /// @todo - /// - remove thread entries without item - /// - remove sign entries without item - /// - remove children when parent got lost - /// - set contact-id in item when not present -} diff --git a/include/dba.php b/include/dba.php index 070722b9b..684f53ea4 100644 --- a/include/dba.php +++ b/include/dba.php @@ -93,18 +93,6 @@ class dba { } } - if (!self::$connected && function_exists('mysql_connect')) { - self::$driver = 'mysql'; - self::$db = mysql_connect($serveraddr, $user, $pass); - if (self::$db && mysql_select_db($db, self::$db)) { - self::$connected = true; - - if (isset($a->config["system"]["db_charset"])) { - mysql_set_charset($a->config["system"]["db_charset"], self::$db); - } - } - } - // No suitable SQL driver was found. if (!self::$connected) { self::$db = null; @@ -134,9 +122,6 @@ class dba { case 'mysqli': self::$_server_info = self::$db->server_info; break; - case 'mysql': - self::$_server_info = mysql_get_server_info(self::$db); - break; } } return self::$_server_info; @@ -216,8 +201,6 @@ class dba { return substr(@self::$db->quote($str, PDO::PARAM_STR), 1, -1); case 'mysqli': return @self::$db->real_escape_string($str); - case 'mysql': - return @mysql_real_escape_string($str,self::$db); } } @@ -235,9 +218,6 @@ class dba { case 'mysqli': $connected = self::$db->ping(); break; - case 'mysql': - $connected = mysql_ping(self::$db); - break; } return $connected; } @@ -485,22 +465,6 @@ class dba { self::$affected_rows = $retval->affected_rows; } break; - case 'mysql': - // For the old "mysql" functions we cannot use prepared statements - $retval = mysql_query(self::replace_parameters($sql, $args), self::$db); - if (mysql_errno(self::$db)) { - self::$error = mysql_error(self::$db); - self::$errorno = mysql_errno(self::$db); - } else { - self::$affected_rows = mysql_affected_rows($retval); - - // Due to missing mysql_* support this here wasn't tested at all - // See here: http://php.net/manual/en/function.mysql-num-rows.php - if (self::$affected_rows <= 0) { - self::$affected_rows = mysql_num_rows($retval); - } - } - break; } // We are having an own error logging in the function "e" @@ -668,8 +632,6 @@ class dba { return $stmt->columnCount(); case 'mysqli': return $stmt->field_count; - case 'mysql': - return mysql_affected_rows($stmt); } return 0; } @@ -688,8 +650,6 @@ class dba { return $stmt->rowCount(); case 'mysqli': return $stmt->num_rows; - case 'mysql': - return mysql_num_rows($stmt); } return 0; } @@ -740,8 +700,6 @@ class dba { $columns[$fields[$param]->name] = $col; } return $columns; - case 'mysql': - return mysql_fetch_array($stmt, MYSQL_ASSOC); } } @@ -755,6 +713,12 @@ class dba { * @return boolean was the insert successfull? */ public static function insert($table, $param, $on_duplicate_update = false) { + + if (empty($table) || empty($param)) { + logger('Table and fields have to be set'); + return false; + } + $sql = "INSERT INTO `".self::escape($table)."` (`".implode("`, `", array_keys($param))."`) VALUES (". substr(str_repeat("?, ", count($param)), 0, -2).")"; @@ -781,9 +745,6 @@ class dba { case 'mysqli': $id = self::$db->insert_id; break; - case 'mysql': - $id = mysql_insert_id(self::$db); - break; } return $id; } @@ -897,6 +858,12 @@ class dba { * @return boolean|array was the delete successfull? When $in_process is set: deletion data */ public static function delete($table, $param, $in_process = false, &$callstack = array()) { + + if (empty($table) || empty($param)) { + logger('Table and condition have to be set'); + return false; + } + $commands = array(); // Create a key for the loop prevention @@ -1059,18 +1026,20 @@ class dba { * @return boolean was the update successfull? */ public static function update($table, $fields, $condition, $old_fields = array()) { + + if (empty($table) || empty($fields) || empty($condition)) { + logger('Table, fields and condition have to be set'); + return false; + } + $table = self::escape($table); - if (count($condition) > 0) { - $array_element = each($condition); - $array_key = $array_element['key']; - if (is_int($array_key)) { - $condition_string = " WHERE ".array_shift($condition); - } else { - $condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?"; - } + $array_element = each($condition); + $array_key = $array_element['key']; + if (is_int($array_key)) { + $condition_string = " WHERE ".array_shift($condition); } else { - $condition_string = ""; + $condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?"; } if (is_bool($old_fields)) { @@ -1250,10 +1219,8 @@ class dba { case 'pdo': return $stmt->closeCursor(); case 'mysqli': - return $stmt->free_result(); + $stmt->free_result(); return $stmt->close(); - case 'mysql': - return mysql_free_result($stmt); } } } diff --git a/include/dbclean.php b/include/dbclean.php deleted file mode 100644 index 1e1dd9082..000000000 --- a/include/dbclean.php +++ /dev/null @@ -1,303 +0,0 @@ - 0))) { - Worker::add(PRIORITY_LOW, 'dbclean', $i); - } - } - } else { - remove_orphans($stage); - } -} - -/** - * @brief Remove orphaned database entries - * @param integer $stage What should be deleted? - * - * Values for $stage: - * ------------------ - * 1: Old global item entries from item table without user copy. - * 2: Items without parents. - * 3: Orphaned data from thread table. - * 4: Orphaned data from notify table. - * 5: Orphaned data from notify-threads table. - * 6: Orphaned data from sign table. - * 7: Orphaned data from term table. - * 8: Expired threads. - * 9: Old global item entries from expired threads - */ -function remove_orphans($stage = 0) { - global $db; - - $count = 0; - - // We split the deletion in many small tasks - $limit = 1000; - - // Get the expire days for step 8 and 9 - $days = Config::get('system', 'dbclean-expire-days', 0); - - if ($stage == 1) { - $last_id = Config::get('system', 'dbclean-last-id-1', 0); - - logger("Deleting old global item entries from item table without user copy. Last ID: ".$last_id); - $r = dba::p("SELECT `id` FROM `item` WHERE `uid` = 0 AND - NOT EXISTS (SELECT `guid` FROM `item` AS `i` WHERE `item`.`guid` = `i`.`guid` AND `i`.`uid` != 0) AND - `received` < UTC_TIMESTAMP() - INTERVAL 90 DAY AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found global item orphans: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["id"]; - dba::delete('item', array('id' => $orphan["id"])); - } - } else { - logger("No global item orphans found"); - } - dba::close($r); - logger("Done deleting ".$count." old global item entries from item table without user copy. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-1', $last_id); - } elseif ($stage == 2) { - $last_id = Config::get('system', 'dbclean-last-id-2', 0); - - logger("Deleting items without parents. Last ID: ".$last_id); - $r = dba::p("SELECT `id` FROM `item` - WHERE NOT EXISTS (SELECT `id` FROM `item` AS `i` WHERE `item`.`parent` = `i`.`id`) - AND `id` >= ? ORDER BY `id` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found item orphans without parents: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["id"]; - dba::delete('item', array('id' => $orphan["id"])); - } - } else { - logger("No item orphans without parents found"); - } - dba::close($r); - logger("Done deleting ".$count." items without parents. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-2', $last_id); - - if ($count < $limit) { - Config::set('system', 'finished-dbclean-2', true); - } - } elseif ($stage == 3) { - $last_id = Config::get('system', 'dbclean-last-id-3', 0); - - logger("Deleting orphaned data from thread table. Last ID: ".$last_id); - $r = dba::p("SELECT `iid` FROM `thread` - WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `thread`.`iid`) AND `iid` >= ? - ORDER BY `iid` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found thread orphans: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["iid"]; - dba::delete('thread', array('iid' => $orphan["iid"])); - } - } else { - logger("No thread orphans found"); - } - dba::close($r); - logger("Done deleting ".$count." orphaned data from thread table. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-3', $last_id); - - if ($count < $limit) { - Config::set('system', 'finished-dbclean-3', true); - } - } elseif ($stage == 4) { - $last_id = Config::get('system', 'dbclean-last-id-4', 0); - - logger("Deleting orphaned data from notify table. Last ID: ".$last_id); - $r = dba::p("SELECT `iid`, `id` FROM `notify` - WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `notify`.`iid`) AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found notify orphans: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["id"]; - dba::delete('notify', array('iid' => $orphan["iid"])); - } - } else { - logger("No notify orphans found"); - } - dba::close($r); - logger("Done deleting ".$count." orphaned data from notify table. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-4', $last_id); - - if ($count < $limit) { - Config::set('system', 'finished-dbclean-4', true); - } - } elseif ($stage == 5) { - $last_id = Config::get('system', 'dbclean-last-id-5', 0); - - logger("Deleting orphaned data from notify-threads table. Last ID: ".$last_id); - $r = dba::p("SELECT `id` FROM `notify-threads` - WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `notify-threads`.`master-parent-item`) AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found notify-threads orphans: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["id"]; - dba::delete('notify-threads', array('id' => $orphan["id"])); - } - } else { - logger("No notify-threads orphans found"); - } - dba::close($r); - logger("Done deleting ".$count." orphaned data from notify-threads table. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-5', $last_id); - - if ($count < $limit) { - Config::set('system', 'finished-dbclean-5', true); - } - } elseif ($stage == 6) { - $last_id = Config::get('system', 'dbclean-last-id-6', 0); - - logger("Deleting orphaned data from sign table. Last ID: ".$last_id); - $r = dba::p("SELECT `iid`, `id` FROM `sign` - WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `sign`.`iid`) AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found sign orphans: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["id"]; - dba::delete('sign', array('iid' => $orphan["iid"])); - } - } else { - logger("No sign orphans found"); - } - dba::close($r); - logger("Done deleting ".$count." orphaned data from sign table. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-6', $last_id); - - if ($count < $limit) { - Config::set('system', 'finished-dbclean-6', true); - } - } elseif ($stage == 7) { - $last_id = Config::get('system', 'dbclean-last-id-7', 0); - - logger("Deleting orphaned data from term table. Last ID: ".$last_id); - $r = dba::p("SELECT `oid`, `tid` FROM `term` - WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `term`.`oid`) AND `tid` >= ? - ORDER BY `tid` LIMIT ".intval($limit), $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found term orphans: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["tid"]; - dba::delete('term', array('oid' => $orphan["oid"])); - } - } else { - logger("No term orphans found"); - } - dba::close($r); - logger("Done deleting ".$count." orphaned data from term table. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-7', $last_id); - - if ($count < $limit) { - Config::set('system', 'finished-dbclean-7', true); - } - } elseif ($stage == 8) { - if ($days <= 0) { - return; - } - - $last_id = Config::get('system', 'dbclean-last-id-8', 0); - - logger("Deleting expired threads. Last ID: ".$last_id); - $r = dba::p("SELECT `thread`.`iid` FROM `thread` - INNER JOIN `contact` ON `thread`.`contact-id` = `contact`.`id` AND NOT `notify_new_posts` - WHERE `thread`.`received` < UTC_TIMESTAMP() - INTERVAL ? DAY - AND NOT `thread`.`mention` AND NOT `thread`.`starred` - AND NOT `thread`.`wall` AND NOT `thread`.`origin` - AND `thread`.`uid` != 0 AND `thread`.`iid` >= ? - AND NOT `thread`.`iid` IN (SELECT `parent` FROM `item` - WHERE (`item`.`starred` OR (`item`.`resource-id` != '') - OR (`item`.`file` != '') OR (`item`.`event-id` != '') - OR (`item`.`attach` != '') OR `item`.`wall` OR `item`.`origin`) - AND `item`.`parent` = `thread`.`iid`) - ORDER BY `thread`.`iid` LIMIT 1000", $days, $last_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found expired threads: ".$count); - while ($thread = dba::fetch($r)) { - $last_id = $thread["iid"]; - dba::delete('thread', array('iid' => $thread["iid"])); - } - } else { - logger("No expired threads found"); - } - dba::close($r); - logger("Done deleting ".$count." expired threads. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-8', $last_id); - } elseif ($stage == 9) { - if ($days <= 0) { - return; - } - - $last_id = Config::get('system', 'dbclean-last-id-9', 0); - $till_id = Config::get('system', 'dbclean-last-id-8', 0); - - logger("Deleting old global item entries from expired threads from ID ".$last_id." to ID ".$till_id); - $r = dba::p("SELECT `id` FROM `item` WHERE `uid` = 0 AND - NOT EXISTS (SELECT `guid` FROM `item` AS `i` WHERE `item`.`guid` = `i`.`guid` AND `i`.`uid` != 0) AND - `received` < UTC_TIMESTAMP() - INTERVAL 90 DAY AND `id` >= ? AND `id` <= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id, $till_id); - $count = dba::num_rows($r); - if ($count > 0) { - logger("found global item entries from expired threads: ".$count); - while ($orphan = dba::fetch($r)) { - $last_id = $orphan["id"]; - dba::delete('item', array('id' => $orphan["id"])); - } - } else { - logger("No global item entries from expired threads"); - } - dba::close($r); - logger("Done deleting ".$count." old global item entries from expired threads. Last ID: ".$last_id); - - Config::set('system', 'dbclean-last-id-9', $last_id); - } - - // Call it again if not all entries were purged - if (($stage != 0) && ($count > 0)) { - Worker::add(PRIORITY_MEDIUM, 'dbclean'); - } -} diff --git a/include/dbstructure.php b/include/dbstructure.php index 1df82b1be..dde3dc6f1 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -1757,73 +1757,3 @@ function db_definition() { return($database); } - - -/* - * run from command line - */ -function dbstructure_run(&$argv, &$argc) { - global $a; - - if (empty($a)) { - $a = new App(dirname(__DIR__)); - } - - @include ".htconfig.php"; - require_once "include/dba.php"; - dba::connect($db_host, $db_user, $db_pass, $db_data); - unset($db_host, $db_user, $db_pass, $db_data); - - if ($argc == 2) { - switch ($argv[1]) { - case "dryrun": - update_structure(true, false); - return; - case "update": - update_structure(true, true); - - $build = Config::get('system','build'); - if (!x($build)) { - Config::set('system', 'build', DB_UPDATE_VERSION); - $build = DB_UPDATE_VERSION; - } - - $stored = intval($build); - $current = intval(DB_UPDATE_VERSION); - - // run any left update_nnnn functions in update.php - for ($x = $stored; $x < $current; $x ++) { - $r = run_update_function($x); - if (!$r) { - break; - } - } - - Config::set('system','build',DB_UPDATE_VERSION); - return; - case "dumpsql": - print_structure(db_definition()); - return; - case "toinnodb": - convert_to_innodb(); - return; - } - } - - - // print help - echo $argv[0]." \n"; - echo "\n"; - echo "Commands:\n"; - echo "dryrun show database update schema queries without running them\n"; - echo "update update database schema\n"; - echo "dumpsql dump database schema\n"; - echo "toinnodb convert all tables from MyISAM to InnoDB\n"; - return; - -} - -if (array_search(__FILE__,get_included_files())===0) { - dbstructure_run($_SERVER["argv"],$_SERVER["argc"]); - killme(); -} diff --git a/include/dbupdate.php b/include/dbupdate.php deleted file mode 100644 index 799ca262c..000000000 --- a/include/dbupdate.php +++ /dev/null @@ -1,13 +0,0 @@ - $argv[1]); - - call_hooks('globaldir_update', $arr); - - logger('Updating directory: ' . $arr['url'], LOGGER_DEBUG); - if (strlen($arr['url'])) { - fetch_url($dir . '?url=' . bin2hex($arr['url'])); - } - - return; -} - -function directory_update_all() { - $r = q("SELECT `url` FROM `contact` - INNER JOIN `profile` ON `profile`.`uid` = `contact`.`uid` - INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`self` AND `profile`.`net-publish` AND `profile`.`is-default` AND - NOT `user`.`account_expired` AND `user`.`verified`"); - - if (DBM::is_result($r)) { - foreach ($r AS $user) { - Worker::add(PRIORITY_LOW, 'directory', $user['url']); - } - } -} diff --git a/include/discover_poco.php b/include/discover_poco.php deleted file mode 100644 index bb8daad6f..000000000 --- a/include/discover_poco.php +++ /dev/null @@ -1,293 +0,0 @@ -: Searches for "search pattern" in the directory. "search pattern" is url encoded. - - checkcontact: Updates gcontact entries - - suggestions: Discover other servers for their contacts. - - server : Searches for the poco server list. "poco url" is base64 encoded. - - update_server: Frequently check the first 250 servers for vitality. - - update_server_directory: Discover the given server id for their contacts - - poco_load: Load POCO data from a given POCO address - - check_profile: Update remote profile data - */ - - if (($argc > 2) && ($argv[1] == "dirsearch")) { - $search = urldecode($argv[2]); - $mode = 1; - } elseif (($argc == 2) && ($argv[1] == "checkcontact")) { - $mode = 2; - } elseif (($argc == 2) && ($argv[1] == "suggestions")) { - $mode = 3; - } elseif (($argc == 3) && ($argv[1] == "server")) { - $mode = 4; - } elseif (($argc == 2) && ($argv[1] == "update_server")) { - $mode = 5; - } elseif (($argc == 3) && ($argv[1] == "update_server_directory")) { - $mode = 6; - } elseif (($argc > 5) && ($argv[1] == "poco_load")) { - $mode = 7; - } elseif (($argc == 3) && ($argv[1] == "check_profile")) { - $mode = 8; - } elseif ($argc == 1) { - $search = ""; - $mode = 0; - } else { - die("Unknown or missing parameter ".$argv[1]."\n"); - } - - logger('start '.$search); - - if ($mode == 8) { - if ($argv[2] != "") { - poco_last_updated($argv[2], true); - } - } elseif ($mode == 7) { - if ($argc == 6) { - $url = $argv[5]; - } else { - $url = ''; - } - poco_load_worker(intval($argv[2]), intval($argv[3]), intval($argv[4]), $url); - } elseif ($mode == 6) { - poco_discover_single_server(intval($argv[2])); - } elseif ($mode == 5) { - update_server(); - } elseif ($mode == 4) { - $server_url = $argv[2]; - if ($server_url == "") { - return; - } - $server_url = filter_var($server_url, FILTER_SANITIZE_URL); - if (substr(normalise_link($server_url), 0, 7) != "http://") { - return; - } - $result = "Checking server ".$server_url." - "; - $ret = poco_check_server($server_url); - if ($ret) { - $result .= "success"; - } else { - $result .= "failed"; - } - logger($result, LOGGER_DEBUG); - } elseif ($mode == 3) { - update_suggestions(); - } elseif (($mode == 2) && Config::get('system','poco_completion')) { - discover_users(); - } elseif (($mode == 1) && ($search != "") && Config::get('system','poco_local_search')) { - discover_directory($search); - gs_search_user($search); - } elseif (($mode == 0) && ($search == "") && (Config::get('system','poco_discovery') > 0)) { - // Query Friendica and Hubzilla servers for their users - poco_discover(); - - // Query GNU Social servers for their users ("statistics" addon has to be enabled on the GS server) - if (!Config::get('system','ostatus_disabled')) - gs_discover(); - } - - logger('end '.$search); - - return; -} - -/** - * @brief Updates the first 250 servers - * - */ -function update_server() { - $r = q("SELECT `url`, `created`, `last_failure`, `last_contact` FROM `gserver` ORDER BY rand()"); - - if (!DBM::is_result($r)) { - return; - } - - $updated = 0; - - foreach ($r AS $server) { - if (!poco_do_update($server["created"], "", $server["last_failure"], $server["last_contact"])) { - continue; - } - logger('Update server status for server '.$server["url"], LOGGER_DEBUG); - - Worker::add(PRIORITY_LOW, "discover_poco", "server", $server["url"]); - - if (++$updated > 250) { - return; - } - } -} - -function discover_users() { - logger("Discover users", LOGGER_DEBUG); - - $starttime = time(); - - $users = q("SELECT `url`, `created`, `updated`, `last_failure`, `last_contact`, `server_url`, `network` FROM `gcontact` - WHERE `last_contact` < UTC_TIMESTAMP - INTERVAL 1 MONTH AND - `last_failure` < UTC_TIMESTAMP - INTERVAL 1 MONTH AND - `network` IN ('%s', '%s', '%s', '%s', '') ORDER BY rand()", - dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), - dbesc(NETWORK_OSTATUS), dbesc(NETWORK_FEED)); - - if (!$users) { - return; - } - $checked = 0; - - foreach ($users AS $user) { - - $urlparts = parse_url($user["url"]); - if (!isset($urlparts["scheme"])) { - q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'", - dbesc(NETWORK_PHANTOM), dbesc(normalise_link($user["url"]))); - continue; - } - - if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com", - "identi.ca", "alpha.app.net"))) { - $networks = array("www.facebook.com" => NETWORK_FACEBOOK, - "facebook.com" => NETWORK_FACEBOOK, - "twitter.com" => NETWORK_TWITTER, - "identi.ca" => NETWORK_PUMPIO, - "alpha.app.net" => NETWORK_APPNET); - - q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'", - dbesc($networks[$urlparts["host"]]), dbesc(normalise_link($user["url"]))); - continue; - } - - $server_url = poco_detect_server($user["url"]); - $force_update = false; - - if ($user["server_url"] != "") { - - $force_update = (normalise_link($user["server_url"]) != normalise_link($server_url)); - - $server_url = $user["server_url"]; - } - - if ((($server_url == "") && ($user["network"] == NETWORK_FEED)) || $force_update || poco_check_server($server_url, $user["network"])) { - logger('Check profile '.$user["url"]); - Worker::add(PRIORITY_LOW, "discover_poco", "check_profile", $user["url"]); - - if (++$checked > 100) { - return; - } - } else { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($user["url"]))); - } - - // Quit the loop after 3 minutes - if (time() > ($starttime + 180)) { - return; - } - } -} - -function discover_directory($search) { - - $data = Cache::get("dirsearch:".$search); - if (!is_null($data)) { - // Only search for the same item every 24 hours - if (time() < $data + (60 * 60 * 24)) { - logger("Already searched for ".$search." in the last 24 hours", LOGGER_DEBUG); - return; - } - } - - $x = fetch_url(get_server()."/lsearch?p=1&n=500&search=".urlencode($search)); - $j = json_decode($x); - - if (count($j->results)) { - foreach ($j->results as $jj) { - // Check if the contact already exists - $exists = q("SELECT `id`, `last_contact`, `last_failure`, `updated` FROM `gcontact` WHERE `nurl` = '%s'", normalise_link($jj->url)); - if (DBM::is_result($exists)) { - logger("Profile ".$jj->url." already exists (".$search.")", LOGGER_DEBUG); - - if (($exists[0]["last_contact"] < $exists[0]["last_failure"]) && - ($exists[0]["updated"] < $exists[0]["last_failure"])) { - continue; - } - // Update the contact - poco_last_updated($jj->url); - continue; - } - - $server_url = poco_detect_server($jj->url); - if ($server_url != '') { - if (!poco_check_server($server_url)) { - logger("Friendica server ".$server_url." doesn't answer.", LOGGER_DEBUG); - continue; - } - logger("Friendica server ".$server_url." seems to be okay.", LOGGER_DEBUG); - } - - $data = Probe::uri($jj->url); - if ($data["network"] == NETWORK_DFRN) { - logger("Profile ".$jj->url." is reachable (".$search.")", LOGGER_DEBUG); - logger("Add profile ".$jj->url." to local directory (".$search.")", LOGGER_DEBUG); - - if ($jj->tags != "") { - $data["keywords"] = $jj->tags; - } - - $data["server_url"] = $data["baseurl"]; - - update_gcontact($data); - } else { - logger("Profile ".$jj->url." is not responding or no Friendica contact - but network ".$data["network"], LOGGER_DEBUG); - } - } - } - Cache::set("dirsearch:".$search, time(), CACHE_DAY); -} - -/** - * @brief Search for GNU Social user with gstools.org - * - * @param str $search User name - */ -function gs_search_user($search) { - - // Currently disabled, since the service isn't available anymore. - // It is not removed since I hope that there will be a successor. - return false; - - $a = get_app(); - - $url = "http://gstools.org/api/users_search/".urlencode($search); - - $result = z_fetch_url($url); - if (!$result["success"]) { - return false; - } - - $contacts = json_decode($result["body"]); - - if ($contacts->status == 'ERROR') { - return false; - } - - /// @TODO AS is considered as a notation for constants (as they usually being written all upper-case) - /// @TODO find all those and convert to all lower-case which is a keyword then - foreach ($contacts->data AS $user) { - $contact = Probe::uri($user->site_address."/".$user->name); - if ($contact["network"] != NETWORK_PHANTOM) { - $contact["about"] = $user->description; - update_gcontact($contact); - } - } -} diff --git a/include/enotify.php b/include/enotify.php index 7de2027ca..dc030fa8b 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -1,14 +1,16 @@ $params['uid'], 'fromName' => $sender_name, 'fromEmail' => $sender_email, @@ -646,11 +649,11 @@ function notification($params) { 'messageSubject' => $datarray['subject'], 'htmlVersion' => $email_html_body, 'textVersion' => $email_text_body, - 'additionalMailHeader' => $datarray['headers'], - )); + 'additionalMailHeader' => $datarray['headers']) + ); } - return False; + return false; } /** diff --git a/include/event.php b/include/event.php index 9a74551bc..a0509aa0f 100644 --- a/include/event.php +++ b/include/event.php @@ -12,6 +12,7 @@ use Friendica\Database\DBM; require_once 'include/bbcode.php'; require_once 'include/map.php'; require_once 'include/datetime.php'; +require_once "include/conversation.php"; function format_event_html($ev, $simple = false) { if (! ((is_array($ev)) && count($ev))) { @@ -216,7 +217,7 @@ function event_delete($event_id) { return; } - q("DELETE FROM `event` WHERE `id` = %d", intval($event_id)); + dba::delete('event', array('id' => $event_id)); logger("Deleted event ".$event_id, LOGGER_DEBUG); } diff --git a/include/expire.php b/include/expire.php deleted file mode 100644 index 7a3549ada..000000000 --- a/include/expire.php +++ /dev/null @@ -1,76 +0,0 @@ - $row['id'])); - } - dba::close($r); - - logger('Delete expired items - done', LOGGER_DEBUG); - - // make this optional as it could have a performance impact on large sites - if (intval(Config::get('system', 'optimize_items'))) { - q("OPTIMIZE TABLE `item`"); - } - return; - } elseif (($argc == 2) && (intval($argv[1]) > 0)) { - $user = dba::select('user', array('uid', 'username', 'expire'), array('uid' => $argv[1]), array('limit' => 1)); - if (DBM::is_result($user)) { - logger('Expire items for user '.$user['uid'].' ('.$user['username'].') - interval: '.$user['expire'], LOGGER_DEBUG); - item_expire($user['uid'], $user['expire']); - logger('Expire items for user '.$user['uid'].' ('.$user['username'].') - done ', LOGGER_DEBUG); - } - return; - } elseif (($argc == 3) && ($argv[1] == 'hook') && is_array($a->hooks) && array_key_exists("expire", $a->hooks)) { - foreach ($a->hooks["expire"] as $hook) { - if ($hook[1] == $argv[2]) { - logger("Calling expire hook '" . $hook[1] . "'", LOGGER_DEBUG); - call_single_hook($a, $name, $hook, $data); - } - } - return; - } - - logger('expire: start'); - - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'expire', 'delete'); - - $r = dba::p("SELECT `uid`, `username` FROM `user` WHERE `expire` != 0"); - while ($row = dba::fetch($r)) { - logger('Calling expiry for user '.$row['uid'].' ('.$row['username'].')', LOGGER_DEBUG); - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'expire', (int)$row['uid']); - } - dba::close($r); - - logger('expire: calling hooks'); - - if (is_array($a->hooks) && array_key_exists('expire', $a->hooks)) { - foreach ($a->hooks['expire'] as $hook) { - logger("Calling expire hook for '" . $hook[1] . "'", LOGGER_DEBUG); - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'expire', 'hook', $hook[1]); - } - } - - logger('expire: end'); - - return; -} diff --git a/include/features.php b/include/features.php index 5ff93eacd..e03dc4a5b 100644 --- a/include/features.php +++ b/include/features.php @@ -14,16 +14,16 @@ use Friendica\Core\PConfig; * @return boolean */ function feature_enabled($uid, $feature) { - $x = Config::get('feature_lock', $feature); + $x = Config::get('feature_lock', $feature, false); - if (is_null($x)) { - $x = PConfig::get($uid, 'feature', $feature); - if (is_null($x)) { - $x = Config::get('feature', $feature); - if (is_null($x)) { - $x = get_feature_default($feature); - } - } + if ($x === false) { + $x = PConfig::get($uid, 'feature', $feature, false); + } + if ($x === false) { + $x = Config::get('feature', $feature, false); + } + if ($x === false) { + $x = get_feature_default($feature); } $arr = array('uid' => $uid, 'feature' => $feature, 'enabled' => $x); @@ -67,53 +67,54 @@ function get_features($filtered = true) { 'general' => array( t('General Features'), //array('expire', t('Content Expiration'), t('Remove old posts/comments after a period of time')), - array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles'), false, Config::get('feature_lock','multi_profiles')), - array('photo_location', t('Photo Location'), t('Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map.'), false, Config::get('feature_lock','photo_location')), - array('export_calendar', t('Export Public Calendar'), t('Ability for visitors to download the public calendar'), false, Config::get('feature_lock','export_calendar')), + array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles'), false, Config::get('feature_lock','multi_profiles', false)), + array('photo_location', t('Photo Location'), t('Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map.'), false, Config::get('feature_lock','photo_location', false)), + array('export_calendar', t('Export Public Calendar'), t('Ability for visitors to download the public calendar'), false, Config::get('feature_lock','export_calendar', false)), ), // Post composition 'composition' => array( t('Post Composition Features'), - array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them'), false, Config::get('feature_lock','preview')), - array('aclautomention', t('Auto-mention Forums'), t('Add/remove mention when a forum page is selected/deselected in ACL window.'), false, Config::get('feature_lock','aclautomention')), + array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them'), false, Config::get('feature_lock','preview', false)), + array('aclautomention', t('Auto-mention Forums'), t('Add/remove mention when a forum page is selected/deselected in ACL window.'), false, Config::get('feature_lock','aclautomention', false)), ), // Network sidebar widgets 'widgets' => array( t('Network Sidebar Widgets'), - array('archives', t('Search by Date'), t('Ability to select posts by date ranges'), false, Config::get('feature_lock','archives')), - array('forumlist_widget', t('List Forums'), t('Enable widget to display the forums your are connected with'), true, Config::get('feature_lock','forumlist_widget')), - array('groups', t('Group Filter'), t('Enable widget to display Network posts only from selected group'), false, Config::get('feature_lock','groups')), - array('networks', t('Network Filter'), t('Enable widget to display Network posts only from selected network'), false, Config::get('feature_lock','networks')), - array('savedsearch', t('Saved Searches'), t('Save search terms for re-use'), false, Config::get('feature_lock','savedsearch')), + array('archives', t('Search by Date'), t('Ability to select posts by date ranges'), false, Config::get('feature_lock','archives', false)), + array('forumlist_widget', t('List Forums'), t('Enable widget to display the forums your are connected with'), true, Config::get('feature_lock','forumlist_widget', false)), + array('groups', t('Group Filter'), t('Enable widget to display Network posts only from selected group'), false, Config::get('feature_lock','groups', false)), + array('networks', t('Network Filter'), t('Enable widget to display Network posts only from selected network'), false, Config::get('feature_lock','networks', false)), + array('savedsearch', t('Saved Searches'), t('Save search terms for re-use'), false, Config::get('feature_lock','savedsearch', false)), ), // Network tabs 'net_tabs' => array( t('Network Tabs'), - array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on'), false, Config::get('feature_lock','personal_tab')), - array('new_tab', t('Network New Tab'), t('Enable tab to display only new Network posts (from the last 12 hours)'), false, Config::get('feature_lock','new_tab')), - array('link_tab', t('Network Shared Links Tab'), t('Enable tab to display only Network posts with links in them'), false, Config::get('feature_lock','link_tab')), + array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on'), false, Config::get('feature_lock','personal_tab', false)), + array('new_tab', t('Network New Tab'), t('Enable tab to display only new Network posts (from the last 12 hours)'), false, Config::get('feature_lock','new_tab', false)), + array('link_tab', t('Network Shared Links Tab'), t('Enable tab to display only Network posts with links in them'), false, Config::get('feature_lock','link_tab', false)), ), // Item tools 'tools' => array( t('Post/Comment Tools'), - array('multi_delete', t('Multiple Deletion'), t('Select and delete multiple posts/comments at once'), false, Config::get('feature_lock','multi_delete')), - array('edit_posts', t('Edit Sent Posts'), t('Edit and correct posts and comments after sending'), false, Config::get('feature_lock','edit_posts')), - array('commtag', t('Tagging'), t('Ability to tag existing posts'), false, Config::get('feature_lock','commtag')), - array('categories', t('Post Categories'), t('Add categories to your posts'), false, Config::get('feature_lock','categories')), - array('filing', t('Saved Folders'), t('Ability to file posts under folders'), false, Config::get('feature_lock','filing')), - array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments'), false, Config::get('feature_lock','dislike')), - array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator'), false, Config::get('feature_lock','star_posts')), - array('ignore_posts', t('Mute Post Notifications'), t('Ability to mute notifications for a thread'), false, Config::get('feature_lock','ignore_posts')), + array('multi_delete', t('Multiple Deletion'), t('Select and delete multiple posts/comments at once'), false, Config::get('feature_lock','multi_delete', false)), + array('edit_posts', t('Edit Sent Posts'), t('Edit and correct posts and comments after sending'), false, Config::get('feature_lock','edit_posts', false)), + array('commtag', t('Tagging'), t('Ability to tag existing posts'), false, Config::get('feature_lock','commtag', false)), + array('categories', t('Post Categories'), t('Add categories to your posts'), false, Config::get('feature_lock','categories', false)), + array('filing', t('Saved Folders'), t('Ability to file posts under folders'), false, Config::get('feature_lock','filing', false)), + array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments'), false, Config::get('feature_lock','dislike', false)), + array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator'), false, Config::get('feature_lock','star_posts', false)), + array('ignore_posts', t('Mute Post Notifications'), t('Ability to mute notifications for a thread'), false, Config::get('feature_lock','ignore_posts', false)), ), // Advanced Profile Settings 'advanced_profile' => array( t('Advanced Profile Settings'), - array('forumlist_profile', t('List Forums'), t('Show visitors public community forums at the Advanced Profile Page'), false, Config::get('feature_lock','forumlist_profile')), + array('forumlist_profile', t('List Forums'), t('Show visitors public community forums at the Advanced Profile Page'), false, Config::get('feature_lock','forumlist_profile', false)), + array('tagadelic', t('Tag Cloud'), t('Provide a personal tag cloud on your profile page'), false, Config::get('feature_lock', 'tagadelic', false)), ), ); @@ -127,8 +128,7 @@ function get_features($filtered = true) { if (is_array($arr[$k][$y])) { if ($arr[$k][$y][4] === false) { $has_items = true; - } - else { + } else { unset($arr[$k][$y]); } } diff --git a/include/feed.php b/include/feed.php index 22deff535..0be6a5781 100644 --- a/include/feed.php +++ b/include/feed.php @@ -344,7 +344,7 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) { $item["title"] = ''; } - if ($contact["fetch_further_information"]) { + if (!empty($contact["fetch_further_information"]) && ($contact["fetch_further_information"] < 3)) { $preview = ""; // Handle enclosures and treat them as preview picture @@ -384,6 +384,9 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) { if (!strstr($item["body"], '[url') && ($item['plink'] != '')) { $item["body"] .= "[hr][url]".$item['plink']."[/url]"; } + if ($contact["fetch_further_information"] == 3) { + $item["tag"] = add_page_keywords($item["plink"], false, $preview, true, $contact["ffi_keyword_blacklist"]); + } } if (!$simulate) { diff --git a/include/follow.php b/include/follow.php index e34ae92fd..7e8b25d79 100644 --- a/include/follow.php +++ b/include/follow.php @@ -1,5 +1,7 @@ user,$contact); + $ret = Diaspora::sendShare($a->user, $contact); logger('share returns: '.$ret); } } diff --git a/include/friendica_smarty.php b/include/friendica_smarty.php index f497fbee0..5dd324bf7 100644 --- a/include/friendica_smarty.php +++ b/include/friendica_smarty.php @@ -1,6 +1,7 @@ parsed($template); } - public function get_template_file($file, $root=''){ + public function getTemplateFile($file, $root=''){ $a = get_app(); $template_file = get_template_file($a, SMARTY3_TEMPLATE_FOLDER.'/'.$file, $root); $template = new FriendicaSmarty(); diff --git a/include/gprobe.php b/include/gprobe.php deleted file mode 100644 index 700305185..000000000 --- a/include/gprobe.php +++ /dev/null @@ -1,57 +0,0 @@ - $uid, 'pid' => $group_id)); // remove group $r = q("UPDATE `group` SET `deleted` = 1 WHERE `uid` = %d AND `name` = '%s'", @@ -109,20 +106,19 @@ function group_byname($uid,$name) { return false; } -function group_rmv_member($uid,$name,$member) { - $gid = group_byname($uid,$name); - if (! $gid) +function group_rmv_member($uid, $name, $member) { + $gid = group_byname($uid, $name); + + if (!$gid) { return false; - if (! ( $uid && $gid && $member)) + } + + if (!($uid && $gid && $member)) { return false; - $r = q("DELETE FROM `group_member` WHERE `uid` = %d AND `gid` = %d AND `contact-id` = %d", - intval($uid), - intval($gid), - intval($member) - ); + } + + $r = dba::delete('group_member', array('uid' => $uid, 'gid' => $gid, 'contact-id' => $member)); return $r; - - } diff --git a/include/identity.php b/include/identity.php index 727073ea6..3066b7113 100644 --- a/include/identity.php +++ b/include/identity.php @@ -4,14 +4,15 @@ */ use Friendica\App; +use Friendica\Content\ForumManager; use Friendica\Core\Cache; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Object\Contact; -require_once 'include/ForumManager.php'; require_once 'include/bbcode.php'; require_once 'mod/proxy.php'; @@ -168,7 +169,7 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` AS `contact_photo`, `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`, `profile`.`uid` AS `profile_uid`, `profile`.*, - `contact`.`avatar-date` AS picdate, `contact`.`addr`, `user`.* + `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.* FROM `profile` INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` AND `contact`.`self` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid` @@ -182,7 +183,7 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` as `contact_photo`, `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`, `profile`.`uid` AS `profile_uid`, `profile`.*, - `contact`.`avatar-date` AS picdate, `contact`.`addr`, `user`.* + `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.* FROM `profile` INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` AND `contact`.`self` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid` @@ -345,7 +346,7 @@ function profile_sidebar($profile, $block = 0) } // Fetch the account type - $account_type = account_type($profile); + $account_type = Contact::getAccountType($profile); if ((x($profile, 'address') == 1) || (x($profile, 'location') == 1) @@ -442,10 +443,6 @@ function profile_sidebar($profile, $block = 0) $p["photo"] = proxy_url($p["photo"], false, PROXY_SIZE_SMALL); } - if ($a->theme['template_engine'] === 'internal') { - $location = template_escape($location); - } - $tpl = get_markup_template('profile_vcard.tpl'); $o .= replace_macros( $tpl, @@ -794,7 +791,7 @@ function advanced_profile(App $a) //show subcribed forum if it is enabled in the usersettings if (feature_enabled($uid, 'forumlist_profile')) { - $profile['forumlist'] = array( t('Forums:'), ForumManager::profile_advanced($uid)); + $profile['forumlist'] = array( t('Forums:'), ForumManager::profileAdvanced($uid)); } if ($a->profile['uid'] == local_user()) { @@ -939,7 +936,7 @@ function zrl_init(App $a) return; } - Worker::add(PRIORITY_LOW, 'gprobe', $tmp_str); + Worker::add(PRIORITY_LOW, 'GProbe', $tmp_str); $arr = array('zrl' => $tmp_str, 'url' => $a->cmd); call_hooks('zrl_init', $arr); } diff --git a/include/items.php b/include/items.php index 6d4d30e7c..cffa12728 100644 --- a/include/items.php +++ b/include/items.php @@ -5,14 +5,17 @@ */ use Friendica\App; -use Friendica\Core\System; use Friendica\ParseUrl; -use Friendica\Util\Lock; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; +use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; use Friendica\Protocol\DFRN; +use Friendica\Protocol\OStatus; +use Friendica\Util\Lock; require_once 'include/bbcode.php'; require_once 'include/oembed.php'; @@ -24,11 +27,8 @@ require_once 'include/files.php'; require_once 'include/text.php'; require_once 'include/email.php'; require_once 'include/threads.php'; -require_once 'include/socgraph.php'; require_once 'include/plaintext.php'; -require_once 'include/ostatus.php'; require_once 'include/feed.php'; -require_once 'include/Contact.php'; require_once 'mod/share.php'; require_once 'include/enotify.php'; require_once 'include/group.php'; @@ -207,7 +207,8 @@ function add_page_info_data($data) { $preview = str_replace(array("[", "]"), array("[", "]"), htmlentities($data["images"][0]["src"], ENT_QUOTES, 'UTF-8', false)); // if the preview picture is larger than 500 pixels then show it in a larger mode // But only, if the picture isn't higher than large (To prevent huge posts) - if (($data["images"][0]["width"] >= 500) && ($data["images"][0]["width"] >= $data["images"][0]["height"])) { + if (!Config::get('system', 'always_show_preview') && ($data["images"][0]["width"] >= 500) + && ($data["images"][0]["width"] >= $data["images"][0]["height"])) { $text .= " image='".$preview."'"; } else { $text .= " preview='".$preview."'"; @@ -426,7 +427,7 @@ function uri_to_guid($uri, $host = "") { * @return array Item array with removed conversation data */ function store_conversation($arr) { - if (in_array($arr['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { + if (in_array($arr['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)) && !empty($arr['uri'])) { $conversation = array('item-uri' => $arr['uri'], 'received' => DBM::date()); if (isset($arr['parent-uri']) && ($arr['parent-uri'] != $arr['uri'])) { @@ -542,9 +543,9 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f /// @todo Check if this is really still needed if ($arr['network'] == NETWORK_OSTATUS) { if (isset($arr['plink'])) { - $arr['plink'] = ostatus::convert_href($arr['plink']); + $arr['plink'] = OStatus::convertHref($arr['plink']); } elseif (isset($arr['uri'])) { - $arr['plink'] = ostatus::convert_href($arr['uri']); + $arr['plink'] = OStatus::convertHref($arr['uri']); } } @@ -718,12 +719,12 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f * This is done only for comments (See below explanation at "gcontact-id") */ if ($arr['parent-uri'] != $arr['uri']) { - $arr["contact-id"] = get_contact($arr['author-link'], $uid); + $arr["contact-id"] = Contact::getIdForURL($arr['author-link'], $uid); } // If not present then maybe the owner was found if ($arr["contact-id"] == 0) { - $arr["contact-id"] = get_contact($arr['owner-link'], $uid); + $arr["contact-id"] = Contact::getIdForURL($arr['owner-link'], $uid); } // Still missing? Then use the "self" contact of the current user @@ -745,28 +746,28 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f * On comments the author is the better choice. */ if ($arr['parent-uri'] === $arr['uri']) { - $arr["gcontact-id"] = get_gcontact_id(array("url" => $arr['owner-link'], "network" => $arr['network'], + $arr["gcontact-id"] = GlobalContact::getId(array("url" => $arr['owner-link'], "network" => $arr['network'], "photo" => $arr['owner-avatar'], "name" => $arr['owner-name'])); } else { - $arr["gcontact-id"] = get_gcontact_id(array("url" => $arr['author-link'], "network" => $arr['network'], + $arr["gcontact-id"] = GlobalContact::getId(array("url" => $arr['author-link'], "network" => $arr['network'], "photo" => $arr['author-avatar'], "name" => $arr['author-name'])); } } if ($arr["author-id"] == 0) { - $arr["author-id"] = get_contact($arr["author-link"], 0); + $arr["author-id"] = Contact::getIdForURL($arr["author-link"], 0); } - if (blockedContact($arr["author-id"])) { + if (Contact::isBlocked($arr["author-id"])) { logger('Contact '.$arr["author-id"].' is blocked, item '.$arr["uri"].' will not be stored'); return 0; } if ($arr["owner-id"] == 0) { - $arr["owner-id"] = get_contact($arr["owner-link"], 0); + $arr["owner-id"] = Contact::getIdForURL($arr["owner-link"], 0); } - if (blockedContact($arr["owner-id"])) { + if (Contact::isBlocked($arr["owner-id"])) { logger('Contact '.$arr["owner-id"].' is blocked, item '.$arr["uri"].' will not be stored'); return 0; } @@ -1138,7 +1139,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f check_item_notification($current_post, $uid); if ($notify) { - Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "notifier", $notify_type, $current_post); + Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "Notifier", $notify_type, $current_post); } return $current_post; @@ -1421,7 +1422,7 @@ function tag_deliver($uid, $item_id) { ); update_thread($item_id); - Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'notifier', 'tgroup', $item_id); + Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'Notifier', 'tgroup', $item_id); } @@ -1532,7 +1533,7 @@ function consume_feed($xml, $importer, &$contact, &$hub, $datedir = 0, $pass = 0 //$tempfile = tempnam(get_temppath(), "ostatus2"); //file_put_contents($tempfile, $xml); logger("Consume OStatus messages ", LOGGER_DEBUG); - ostatus::import($xml, $importer, $contact, $hub); + OStatus::import($xml, $importer, $contact, $hub); } return; } @@ -1750,7 +1751,7 @@ function lose_follower($importer, $contact, array $datarray = array(), $item = " if (($contact['rel'] == CONTACT_IS_FRIEND) || ($contact['rel'] == CONTACT_IS_SHARING)) { dba::update('contact', array('rel' => CONTACT_IS_SHARING), array('id' => $contact['id'])); } else { - contact_remove($contact['id']); + Contact::remove($contact['id']); } } @@ -1759,7 +1760,7 @@ function lose_sharer($importer, $contact, array $datarray = array(), $item = "") if (($contact['rel'] == CONTACT_IS_FRIEND) || ($contact['rel'] == CONTACT_IS_FOLLOWER)) { dba::update('contact', array('rel' => CONTACT_IS_FOLLOWER), array('id' => $contact['id'])); } else { - contact_remove($contact['id']); + Contact::remove($contact['id']); } } @@ -2055,7 +2056,7 @@ function item_expire($uid, $days, $network = "", $force = false) { drop_item($item['id'], false); } - Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "notifier", "expire", $uid); + Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Notifier", "expire", $uid); } /// @TODO type-hint is array @@ -2077,7 +2078,7 @@ function drop_items($items) { // multiple threads may have been deleted, send an expire notification if ($uid) { - Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "notifier", "expire", $uid); + Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Notifier", "expire", $uid); } } @@ -2122,7 +2123,7 @@ function drop_item($id, $interactive = true) { } - if ((local_user() == $item['uid']) || ($contact_id) || (! $interactive)) { + if ((local_user() == $item['uid']) || $contact_id || !$interactive) { // Check if we should do HTML-based delete confirmation if ($_REQUEST['confirm']) { @@ -2189,30 +2190,18 @@ function drop_item($id, $interactive = true) { * generate a resource-id and therefore aren't intimately linked to the item. */ if (strlen($item['resource-id'])) { - q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ", - dbesc($item['resource-id']), - intval($item['uid']) - ); - // ignore the result + dba::delete('photo', array('resource-id' => $item['resource-id'], 'uid' => $item['uid'])); } // If item is a link to an event, nuke the event record. if (intval($item['event-id'])) { - q("DELETE FROM `event` WHERE `id` = %d AND `uid` = %d", - intval($item['event-id']), - intval($item['uid']) - ); - // ignore the result + dba::delete('event', array('id' => $item['event-id'], 'uid' => $item['uid'])); } // If item has attachments, drop them foreach (explode(", ", $item['attach']) as $attach) { preg_match("|attach/(\d+)|", $attach, $matches); - q("DELETE FROM `attach` WHERE `id` = %d AND `uid` = %d", - intval($matches[1]), - local_user() - ); - // ignore the result + dba::delete('attach', array('id' => $matches[1], 'uid' => $item['uid'])); } // The new code splits the queries since the mysql optimizer really has bad problems with subqueries @@ -2269,7 +2258,7 @@ function drop_item($id, $interactive = true) { $drop_id = intval($item['id']); $priority = ($interactive ? PRIORITY_HIGH : PRIORITY_LOW); - Worker::add(array('priority' => $priority, 'dont_fork' => true), "notifier", "drop", $drop_id); + Worker::add(array('priority' => $priority, 'dont_fork' => true), "Notifier", "drop", $drop_id); if (! $interactive) { return $owner; diff --git a/include/like.php b/include/like.php index eee89168a..1dcadde70 100644 --- a/include/like.php +++ b/include/like.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Object\Contact; use Friendica\Protocol\Diaspora; /** @@ -115,7 +116,7 @@ function do_like($item_id, $verb) { $item_contact_id = $owner_self_contact['id']; $item_contact = $owner_self_contact; } else { - $item_contact_id = get_contact($author_contact['url'], $item['uid']); + $item_contact_id = Contact::getIdForURL($author_contact['url'], $item['uid']); $contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($item_contact_id) @@ -162,12 +163,10 @@ function do_like($item_id, $verb) { // Clean up the Diaspora signatures for this like // Go ahead and do it even if Diaspora support is disabled. We still want to clean up // if it had been enabled in the past - q("DELETE FROM `sign` WHERE `iid` = %d", - intval($like_item['id']) - ); + dba::delete('sign', array('iid' => $like_item['id'])); $like_item_id = $like_item['id']; - Worker::add(PRIORITY_HIGH, "notifier", "like", $like_item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "like", $like_item_id); if (!$event_verb_flag || $like_item['verb'] == $activity) { return true; @@ -248,13 +247,13 @@ EOT; } // Save the author information for the like in case we need to relay to Diaspora - Diaspora::store_like_signature($item_contact, $new_item_id); + Diaspora::storeLikeSignature($item_contact, $new_item_id); $new_item['id'] = $new_item_id; call_hooks('post_local_end', $new_item); - Worker::add(PRIORITY_HIGH, "notifier", "like", $new_item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "like", $new_item_id); return true; } diff --git a/include/message.php b/include/message.php index dcc1fbc12..e49647b6e 100644 --- a/include/message.php +++ b/include/message.php @@ -145,7 +145,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){ } if ($post_id) { - Worker::add(PRIORITY_HIGH, "notifier", "mail", $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", "mail", $post_id); return intval($post_id); } else { return -3; diff --git a/include/network.php b/include/network.php index e9cfe8603..c11cdb2c6 100644 --- a/include/network.php +++ b/include/network.php @@ -414,7 +414,7 @@ function xml_status($st, $message = '') $xmldata = array("result" => $result); - echo XML::from_array($xmldata, $xml); + echo XML::fromArray($xmldata, $xml); killme(); } diff --git a/include/notifier.php b/include/notifier.php deleted file mode 100644 index 3e9ea66f2..000000000 --- a/include/notifier.php +++ /dev/null @@ -1,617 +0,0 @@ - UTC_TIMESTAMP() - INTERVAL 10 MINUTE", - intval($item_id) - ); - $uid = $item_id; - $item_id = 0; - if (! count($items)) { - return; - } - } elseif ($cmd === 'suggest') { - $normal_mode = false; - $fsuggest = true; - - $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1", - intval($item_id) - ); - if (! count($suggest)) { - return; - } - $uid = $suggest[0]['uid']; - $recipients[] = $suggest[0]['cid']; - $item = $suggest[0]; - } elseif ($cmd === 'removeme') { - $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, - `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, - `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`, `user`.`guid` - FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($item_id)); - if (!$r) - return; - - $user = $r[0]; - - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id)); - if (!$r) - return; - - $self = $r[0]; - - $r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id)); - if (!$r) { - return; - } - require_once 'include/Contact.php'; - foreach ($r as $contact) { - terminate_friendship($user, $self, $contact); - } - return; - } elseif ($cmd === 'relocate') { - $normal_mode = false; - $relocate = true; - $uid = $item_id; - - $recipients_relocate = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `self` AND `network` IN ('%s', '%s')", - intval($uid), NETWORK_DFRN, NETWORK_DIASPORA); - } else { - // find ancestors - $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1", - intval($item_id) - ); - - if ((! DBM::is_result($r)) || (! intval($r[0]['parent']))) { - return; - } - - $target_item = $r[0]; - $parent_id = intval($r[0]['parent']); - $uid = $r[0]['uid']; - $updated = $r[0]['edited']; - - $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer` - FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC", - intval($parent_id) - ); - - if (! count($items)) { - return; - } - - // avoid race condition with deleting entries - - if ($items[0]['deleted']) { - foreach ($items as $item) { - $item['deleted'] = 1; - } - } - - if ((count($items) == 1) && ($items[0]['id'] === $target_item['id']) && ($items[0]['uri'] === $items[0]['parent-uri'])) { - logger('notifier: top level post'); - $top_level = true; - } - - } - - $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, - `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, - `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type` - FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", - intval($uid) - ); - - if (! DBM::is_result($r)) { - return; - } - - $owner = $r[0]; - - $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false); - - // Should the post be transmitted to Diaspora? - $diaspora_delivery = true; - - // If this is a public conversation, notify the feed hub - $public_message = true; - - // Do a PuSH - $push_notify = false; - - // Deliver directly to a forum, don't PuSH - $direct_forum_delivery = false; - - // fill this in with a single salmon slap if applicable - $slap = ''; - - if (! ($mail || $fsuggest || $relocate)) { - - $slap = ostatus::salmon($target_item,$owner); - - require_once 'include/group.php'; - - $parent = $items[0]; - - $thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d", - dbesc($target_item["thr-parent"]), intval($target_item["uid"])); - - logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG); - - // This is IMPORTANT!!!! - - // We will only send a "notify owner to relay" or followup message if the referenced post - // originated on our system by virtue of having our hostname somewhere - // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere. - - // if $parent['wall'] == 1 we will already have the parent message in our array - // and we will relay the whole lot. - - // expire sends an entire group of expire messages and cannot be forwarded. - // However the conversation owner will be a part of the conversation and will - // be notified during this run. - // Other DFRN conversation members will be alerted during polled updates. - - - - // Diaspora members currently are not notified of expirations, and other networks have - // either limited or no ability to process deletions. We should at least fix Diaspora - // by stringing togther an array of retractions and sending them onward. - - - $localhost = str_replace('www.','',$a->get_hostname()); - if (strpos($localhost,':')) { - $localhost = substr($localhost,0,strpos($localhost,':')); - } - /** - * - * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes - * have been known to cause runaway conditions which affected several servers, along with - * permissions issues. - * - */ - - $relay_to_owner = false; - - if (!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) { - $relay_to_owner = true; - } - - - if (($cmd === 'uplink') && (intval($parent['forum_mode']) == 1) && !$top_level) { - $relay_to_owner = true; - } - - // until the 'origin' flag has been in use for several months - // we will just use it as a fallback test - // later we will be able to use it as the primary test of whether or not to relay. - - if (! $target_item['origin']) { - $relay_to_owner = false; - } - if ($parent['origin']) { - $relay_to_owner = false; - } - - // Special treatment for forum posts - if (($target_item['author-link'] != $target_item['owner-link']) && - ($owner['id'] != $target_item['contact-id']) && - ($target_item['uri'] === $target_item['parent-uri'])) { - - $fields = array('forum', 'prv'); - $condition = array('id' => $target_item['contact-id']); - $contact = dba::select('contact', $fields, $condition, array('limit' => 1)); - if (!DBM::is_result($contact)) { - // Should never happen - return false; - } - - // Is the post from a forum? - if ($contact['forum'] || $contact['prv']) { - $relay_to_owner = true; - $direct_forum_delivery = true; - } - } - if ($relay_to_owner) { - logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG); - // local followup to remote post - $followup = true; - $public_message = false; // not public - $conversant_str = dbesc($parent['contact-id']); - $recipients = array($parent['contact-id']); - $recipients_followup = array($parent['contact-id']); - - //if (!$target_item['private'] && $target_item['wall'] && - if (!$target_item['private'] && - (strlen($target_item['allow_cid'].$target_item['allow_gid']. - $target_item['deny_cid'].$target_item['deny_gid']) == 0)) - $push_notify = true; - - if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) { - - $push_notify = true; - - if ($parent["network"] == NETWORK_OSTATUS) { - // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments - // Currently it is work at progress - $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s' AND NOT `blocked` AND NOT `pending` AND NOT `archive`", - intval($uid), - dbesc(NETWORK_DFRN) - ); - if (DBM::is_result($r)) { - foreach ($r as $rr) { - $recipients_followup[] = $rr['id']; - } - } - } - } - - if ($direct_forum_delivery) { - $push_notify = false; - } - - logger("Notify ".$target_item["guid"]." via PuSH: ".($push_notify?"Yes":"No"), LOGGER_DEBUG); - } else { - $followup = false; - - logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG); - - // don't send deletions onward for other people's stuff - - if ($target_item['deleted'] && (! intval($target_item['wall']))) { - logger('notifier: ignoring delete notification for non-wall item'); - return; - } - - if ((strlen($parent['allow_cid'])) - || (strlen($parent['allow_gid'])) - || (strlen($parent['deny_cid'])) - || (strlen($parent['deny_gid']))) { - $public_message = false; // private recipients, not public - } - - $allow_people = expand_acl($parent['allow_cid']); - $allow_groups = expand_groups(expand_acl($parent['allow_gid']),true); - $deny_people = expand_acl($parent['deny_cid']); - $deny_groups = expand_groups(expand_acl($parent['deny_gid'])); - - // if our parent is a public forum (forum_mode == 1), uplink to the origional author causing - // a delivery fork. private groups (forum_mode == 2) do not uplink - - if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) { - Worker::add($a->queue['priority'], 'notifier', 'uplink', $item_id); - } - - $conversants = array(); - - foreach ($items as $item) { - $recipients[] = $item['contact-id']; - $conversants[] = $item['contact-id']; - // pull out additional tagged people to notify (if public message) - if ($public_message && strlen($item['inform'])) { - $people = explode(',',$item['inform']); - foreach ($people as $person) { - if (substr($person,0,4) === 'cid:') { - $recipients[] = intval(substr($person,4)); - $conversants[] = intval(substr($person,4)); - } else { - $url_recipients[] = substr($person,4); - } - } - } - } - - if (count($url_recipients)) - logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true)); - - $conversants = array_unique($conversants); - - - $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups)); - $deny = array_unique(array_merge($deny_people,$deny_groups)); - $recipients = array_diff($recipients,$deny); - - $conversant_str = dbesc(implode(', ',$conversants)); - } - - // If the thread parent is OStatus then do some magic to distribute the messages. - // We have not only to look at the parent, since it could be a Friendica thread. - if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) { - - $diaspora_delivery = false; - - logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG); - - // Send a salmon to the parent author - $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", - dbesc(normalise_link($thr_parent[0]['author-link'])), - intval($uid)); - if (DBM::is_result($r)) { - $probed_contact = $r[0]; - } else { - $probed_contact = Probe::uri($thr_parent[0]['author-link']); - } - - if ($probed_contact["notify"] != "") { - logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]); - $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; - } - - // Send a salmon to the parent owner - $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", - dbesc(normalise_link($thr_parent[0]['owner-link'])), - intval($uid)); - if (DBM::is_result($r)) { - $probed_contact = $r[0]; - } else { - $probed_contact = Probe::uri($thr_parent[0]['owner-link']); - } - - if ($probed_contact["notify"] != "") { - logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]); - $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; - } - - // Send a salmon notification to every person we mentioned in the post - $arr = explode(',',$target_item['tag']); - foreach ($arr as $x) { - //logger('Checking tag '.$x, LOGGER_DEBUG); - $matches = null; - if (preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) { - $probed_contact = Probe::uri($matches[1]); - if ($probed_contact["notify"] != "") { - logger('Notify mentioned user '.$probed_contact["url"].': '.$probed_contact["notify"]); - $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; - } - } - } - - // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora - $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')"; - } else { - $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."', '".NETWORK_DIASPORA."', '".NETWORK_MAIL."', '".NETWORK_MAIL2."')"; - } - } else { - $public_message = false; - } - - // If this is a public message and pubmail is set on the parent, include all your email contacts - - $mail_disabled = ((function_exists('imap_open') && (!Config::get('system','imap_disabled'))) ? 0 : 1); - - if (! $mail_disabled) { - if ((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid'])) - && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid'])) - && (intval($target_item['pubmail']))) { - $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s'", - intval($uid), - dbesc(NETWORK_MAIL) - ); - if (DBM::is_result($r)) { - foreach ($r as $rr) { - $recipients[] = $rr['id']; - } - } - } - } - - if ($followup) { - $recip_str = implode(', ', $recipients_followup); - } else { - $recip_str = implode(', ', $recipients); - } - if ($relocate) { - $r = $recipients_relocate; - } else { - $r = q("SELECT `id`, `url`, `network`, `self` FROM `contact` - WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra, - dbesc($recip_str) - ); - } - - // delivery loop - - if (DBM::is_result($r)) { - foreach ($r as $contact) { - if ($contact['self']) { - continue; - } - logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG); - - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'delivery', $cmd, $item_id, (int)$contact['id']); - } - } - - // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts - // They are especially used for notifications to OStatus users that don't follow us. - - if ($slap && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) { - if (!Config::get('system','dfrn_only')) { - foreach ($url_recipients as $url) { - if ($url) { - logger('notifier: urldelivery: ' . $url); - $deliver_status = slapper($owner,$url,$slap); - /// @TODO Redeliver/queue these items on failure, though there is no contact record - } - } - } - } - - - if ($public_message) { - - $r0 = array(); - $r1 = array(); - - if ($diaspora_delivery) { - if (!$followup) { - $r0 = Diaspora::relay_list(); - } - - $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network` - FROM `contact` WHERE `network` = '%s' AND `batch` != '' - AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`", - dbesc(NETWORK_DIASPORA), - intval($owner['uid']), - intval(CONTACT_IS_SHARING) - ); - } - - $r2 = q("SELECT `id`, `name`,`network` FROM `contact` - WHERE `network` in ('%s', '%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `rel` != %d", - dbesc(NETWORK_DFRN), - dbesc(NETWORK_MAIL2), - intval($owner['uid']), - intval(CONTACT_IS_SHARING) - ); - - $r = array_merge($r2,$r1,$r0); - - if (DBM::is_result($r)) { - logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG); - - foreach ($r as $rr) { - - // except for Diaspora batch jobs - // Don't deliver to folks who have already been delivered to - - if (($rr['network'] !== NETWORK_DIASPORA) && (in_array($rr['id'],$conversants))) { - logger('notifier: already delivered id=' . $rr['id']); - continue; - } - - if ((! $mail) && (! $fsuggest) && (! $followup)) { - logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]); - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'delivery', $cmd, $item_id, (int)$rr['id']); - } - } - } - - $push_notify = true; - - } - - // Notify PuSH subscribers (Used for OStatus distribution of regular posts) - if ($push_notify) { - // Set push flag for PuSH subscribers to this topic, - // they will be notified in queue.php - q("UPDATE `push_subscriber` SET `push` = 1 ". - "WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname'])); - - logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG); - - // Handling the pubsubhubbub requests - Worker::add(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true), - 'pubsubpublish'); - } - - logger('notifier: calling hooks', LOGGER_DEBUG); - - if ($normal_mode) { - call_hooks('notifier_normal',$target_item); - } - - call_hooks('notifier_end',$target_item); - - return; -} diff --git a/include/oauth.php b/include/oauth.php index bb1227868..8834b9355 100644 --- a/include/oauth.php +++ b/include/oauth.php @@ -113,7 +113,7 @@ class FKOAuthDataStore extends OAuthDataStore { } - q("DELETE FROM tokens WHERE id='%s'", $token->key); + dba::delete('tokens', array('id' => $token->key)); if (!is_null($ret) && $uverifier!==false){ @@ -182,93 +182,3 @@ class FKOAuth1 extends OAuthServer { } } -/* -class FKOAuth2 extends OAuth2 { - - private function db_secret($client_secret){ - return hash('whirlpool',$client_secret); - } - - public function addClient($client_id, $client_secret, $redirect_uri) { - $client_secret = $this->db_secret($client_secret); - $r = q("INSERT INTO clients (client_id, pw, redirect_uri) VALUES ('%s', '%s', '%s')", - dbesc($client_id), - dbesc($client_secret), - dbesc($redirect_uri) - ); - - return $r; - } - - protected function checkClientCredentials($client_id, $client_secret = NULL) { - $client_secret = $this->db_secret($client_secret); - - $r = q("SELECT pw FROM clients WHERE client_id = '%s'", - dbesc($client_id)); - - if ($client_secret === NULL) - return $result !== FALSE; - - return $result["client_secret"] == $client_secret; - } - - protected function getRedirectUri($client_id) { - $r = q("SELECT redirect_uri FROM clients WHERE client_id = '%s'", - dbesc($client_id)); - if ($r === FALSE) - return FALSE; - - return isset($r[0]["redirect_uri"]) && $r[0]["redirect_uri"] ? $r[0]["redirect_uri"] : NULL; - } - - protected function getAccessToken($oauth_token) { - $r = q("SELECT client_id, expires, scope FROM tokens WHERE id = '%s'", - dbesc($oauth_token)); - - if (DBM::is_result($r)) - return $r[0]; - return null; - } - - - - protected function setAccessToken($oauth_token, $client_id, $expires, $scope = NULL) { - $r = q("INSERT INTO tokens (id, client_id, expires, scope) VALUES ('%s', '%s', %d, '%s')", - dbesc($oauth_token), - dbesc($client_id), - intval($expires), - dbesc($scope)); - - return $r; - } - - protected function getSupportedGrantTypes() { - return array( - OAUTH2_GRANT_TYPE_AUTH_CODE, - ); - } - - - protected function getAuthCode($code) { - $r = q("SELECT id, client_id, redirect_uri, expires, scope FROM auth_codes WHERE id = '%s'", - dbesc($code)); - - if (DBM::is_result($r)) - return $r[0]; - return null; - } - - protected function setAuthCode($code, $client_id, $redirect_uri, $expires, $scope = NULL) { - $r = q("INSERT INTO auth_codes - (id, client_id, redirect_uri, expires, scope) VALUES - ('%s', '%s', '%s', %d, '%s')", - dbesc($code), - dbesc($client_id), - dbesc($redirect_uri), - intval($expires), - dbesc($scope)); - return $r; - } - -} -*/ diff --git a/include/oembed.php b/include/oembed.php index 74ce90dd1..b7c1616fe 100755 --- a/include/oembed.php +++ b/include/oembed.php @@ -28,17 +28,17 @@ function oembed_replacecb($matches){ * @return bool|object Returns object with embed content or false if no embedable * content exists */ -function oembed_fetch_url($embedurl, $no_rich_type = false){ +function oembed_fetch_url($embedurl, $no_rich_type = false) { $embedurl = trim($embedurl, "'"); $embedurl = trim($embedurl, '"'); $a = get_app(); - $r = q("SELECT * FROM `oembed` WHERE `url` = '%s'", - dbesc(normalise_link($embedurl))); + $condition = array('url' => normalise_link($embedurl)); + $r = dba::select('oembed', array('content'), $condition, array('limit' => 1)); if (DBM::is_result($r)) { - $txt = $r[0]["content"]; + $txt = $r["content"]; } else { $txt = Cache::get($a->videowidth . $embedurl); } diff --git a/include/onepoll.php b/include/onepoll.php deleted file mode 100644 index c9fbb1610..000000000 --- a/include/onepoll.php +++ /dev/null @@ -1,625 +0,0 @@ - 1) && (intval($argv[1]))) { - $contact_id = intval($argv[1]); - } - - if (($argc > 2) && ($argv[2] == "force")) { - $force = true; - } - - if (!$contact_id) { - logger('onepoll: no contact'); - return; - } - - $d = datetime_convert(); - - // Only poll from those with suitable relationships, - // and which have a polling address and ignore Diaspora since - // we are unable to match those posts with a Diaspora GUID and prevent duplicates. - - $contacts = q("SELECT `contact`.* FROM `contact` - WHERE (`rel` = %d OR `rel` = %d) AND `poll` != '' - AND NOT `network` IN ('%s', '%s') - AND `contact`.`id` = %d - AND `self` = 0 AND `contact`.`blocked` = 0 AND `contact`.`readonly` = 0 - AND `contact`.`archive` = 0 LIMIT 1", - intval(CONTACT_IS_SHARING), - intval(CONTACT_IS_FRIEND), - dbesc(NETWORK_FACEBOOK), - dbesc(NETWORK_PUMPIO), - intval($contact_id) - ); - - if (!count($contacts)) { - logger('Contact not found or cannot be used.'); - return; - } - - $contact = $contacts[0]; - - $importer_uid = $contact['uid']; - - // load current friends if possible. - if (($contact['poco'] != "") && ($contact['success_update'] > $contact['failure_update'])) { - $r = q("SELECT count(*) AS total FROM glink - WHERE `cid` = %d AND updated > UTC_TIMESTAMP() - INTERVAL 1 DAY", - intval($contact['id']) - ); - if (DBM::is_result($r)) { - if (!$r[0]['total']) { - poco_load($contact['id'], $importer_uid, 0, $contact['poco']); - } - } - } - - /// @TODO Check why we don't poll the Diaspora feed at the moment (some guid problem in the items?) - /// @TODO Check whether this is possible with Redmatrix - if ($contact["network"] == NETWORK_DIASPORA) { - if (poco_do_update($contact["created"], $contact["last-item"], $contact["failure_update"], $contact["success_update"])) { - $last_updated = poco_last_updated($contact["url"]); - $updated = datetime_convert(); - if ($last_updated) { - $fields = array('last-item' => $last_updated, 'last-update' => $updated, 'success_update' => $updated); - dba::update('contact', $fields, array('id' => $contact['id'])); - } else { - dba::update('contact', array('last-update' => $updated, 'failure_update' => $updated), array('id' => $contact['id'])); - } - } - return; - } - - $xml = false; - - $t = $contact['last-update']; - - if ($contact['subhub']) { - $poll_interval = Config::get('system', 'pushpoll_frequency'); - $contact['priority'] = (($poll_interval !== false) ? intval($poll_interval) : 3); - $hub_update = false; - - if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 day")) { - $hub_update = true; - } - } else { - $hub_update = false; - } - - $last_update = (($contact['last-update'] <= NULL_DATE) - ? datetime_convert('UTC', 'UTC', 'now - 7 days', ATOM_TIME) - : datetime_convert('UTC', 'UTC', $contact['last-update'], ATOM_TIME) - ); - - // Update the contact entry - if (($contact['network'] === NETWORK_OSTATUS) || ($contact['network'] === NETWORK_DIASPORA) || ($contact['network'] === NETWORK_DFRN)) { - if (!poco_reachable($contact['url'])) { - logger("Skipping probably dead contact ".$contact['url']); - return; - } - - if (!update_contact($contact["id"])) { - mark_for_death($contact); - logger('Contact is marked dead'); - return; - } else { - unmark_for_death($contact); - } - } - - if ($importer_uid == 0) { - logger('Ignore public contacts'); - return; - } - - $r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` INNER JOIN `user` on `contact`.`uid` = `user`.`uid` WHERE `user`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", - intval($importer_uid) - ); - - if (!DBM::is_result($r)) { - logger('No self contact for user '.$importer_uid); - return; - } - - $importer = $r[0]; - - logger("onepoll: poll: ({$contact['id']}) IMPORTER: {$importer['name']}, CONTACT: {$contact['name']}"); - - if ($contact['network'] === NETWORK_DFRN) { - $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); - if (intval($contact['duplex']) && $contact['dfrn-id']) { - $idtosend = '0:' . $orig_id; - } - if (intval($contact['duplex']) && $contact['issued-id']) { - $idtosend = '1:' . $orig_id; - } - - // they have permission to write to us. We already filtered this in the contact query. - $perm = 'rw'; - - // But this may be our first communication, so set the writable flag if it isn't set already. - - if (!intval($contact['writable'])) { - $fields = array('writable' => true); - dba::update('contact', $fields, array('id' => $contact['id'])); - } - - $url = $contact['poll'] . '?dfrn_id=' . $idtosend - . '&dfrn_version=' . DFRN_PROTOCOL_VERSION - . '&type=data&last_update=' . $last_update - . '&perm=' . $perm ; - - $ret = z_fetch_url($url); - - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { - return; - } - - $handshake_xml = $ret['body']; - - $html_code = $a->get_curl_code(); - - logger('onepoll: handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA); - - - if (!strlen($handshake_xml) || ($html_code >= 400) || !$html_code) { - logger("poller: $url appears to be dead - marking for death "); - - // dead connection - might be a transient event, or this might - // mean the software was uninstalled or the domain expired. - // Will keep trying for one month. - - mark_for_death($contact); - - // set the last-update so we don't keep polling - $fields = array('last-update' => datetime_convert(), 'failure_update' => datetime_convert()); - dba::update('contact', $fields, array('id' => $contact['id'])); - - return; - } - - if (! strstr($handshake_xml, '<')) { - logger('poller: response from ' . $url . ' did not contain XML.'); - - mark_for_death($contact); - - $fields = array('last-update' => datetime_convert(), 'failure_update' => datetime_convert()); - dba::update('contact', $fields, array('id' => $contact['id'])); - - return; - } - - - $res = parse_xml_string($handshake_xml); - - if (intval($res->status) == 1) { - logger("poller: $url replied status 1 - marking for death "); - - // we may not be friends anymore. Will keep trying for one month. - // set the last-update so we don't keep polling - $fields = array('last-update' => datetime_convert(), 'failure_update' => datetime_convert()); - dba::update('contact', $fields, array('id' => $contact['id'])); - - mark_for_death($contact); - } elseif ($contact['term-date'] > NULL_DATE) { - logger("poller: $url back from the dead - removing mark for death"); - unmark_for_death($contact); - } - - if ((intval($res->status) != 0) || !strlen($res->challenge) || !strlen($res->dfrn_id)) { - return; - } - - if (((float)$res->dfrn_version > 2.21) && ($contact['poco'] == '')) { - $fields = array('poco' => str_replace('/profile/', '/poco/', $contact['url'])); - dba::update('contact', $fields, array('id' => $contact['id'])); - } - - $postvars = array(); - - $sent_dfrn_id = hex2bin((string) $res->dfrn_id); - $challenge = hex2bin((string) $res->challenge); - - $final_dfrn_id = ''; - - if ($contact['duplex'] && strlen($contact['prvkey'])) { - openssl_private_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['prvkey']); - openssl_private_decrypt($challenge, $postvars['challenge'], $contact['prvkey']); - } else { - openssl_public_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['pubkey']); - openssl_public_decrypt($challenge, $postvars['challenge'], $contact['pubkey']); - } - - $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); - - if (strpos($final_dfrn_id, ':') == 1) { - $final_dfrn_id = substr($final_dfrn_id, 2); - } - - if ($final_dfrn_id != $orig_id) { - logger('poller: ID did not decode: ' . $contact['id'] . ' orig: ' . $orig_id . ' final: ' . $final_dfrn_id); - // did not decode properly - cannot trust this site - return; - } - - $postvars['dfrn_id'] = $idtosend; - $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; - $postvars['perm'] = 'rw'; - - $xml = post_url($contact['poll'], $postvars); - - } elseif (($contact['network'] === NETWORK_OSTATUS) - || ($contact['network'] === NETWORK_DIASPORA) - || ($contact['network'] === NETWORK_FEED)) { - - // Upgrading DB fields from an older Friendica version - // Will only do this once per notify-enabled OStatus contact - // or if relationship changes - - $stat_writeable = ((($contact['notify']) && ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['rel'] == CONTACT_IS_FRIEND)) ? 1 : 0); - - // Contacts from OStatus are always writable - if ($contact['network'] === NETWORK_OSTATUS) { - $stat_writeable = 1; - } - - if ($stat_writeable != $contact['writable']) { - $fields = array('writable' => $stat_writeable); - dba::update('contact', $fields, array('id' => $contact['id'])); - } - - // Are we allowed to import from this person? - - if ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['blocked'] || $contact['readonly']) { - return; - } - - $cookiejar = tempnam(get_temppath(), 'cookiejar-onepoll-'); - $ret = z_fetch_url($contact['poll'], false, $redirects, array('cookiejar' => $cookiejar)); - - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { - return; - } - - $xml = $ret['body']; - - unlink($cookiejar); - } elseif ($contact['network'] === NETWORK_MAIL || $contact['network'] === NETWORK_MAIL2) { - - logger("Mail: Fetching for ".$contact['addr'], LOGGER_DEBUG); - - $mail_disabled = ((function_exists('imap_open') && (! Config::get('system', 'imap_disabled'))) ? 0 : 1); - if ($mail_disabled) { - return; - } - - logger("Mail: Enabled", LOGGER_DEBUG); - - $mbox = null; - $x = dba::select('user', array('prvkey'), array('uid' => $importer_uid), array('limit' => 1)); - - $condition = array("`server` != '' AND `uid` = ?", $importer_uid); - $mailconf = dba::select('mailacct', array(), $condition, array('limit' => 1)); - if (DBM::is_result($x) && DBM::is_result($mailconf)) { - $mailbox = construct_mailbox_name($mailconf); - $password = ''; - openssl_private_decrypt(hex2bin($mailconf['pass']), $password, $x['prvkey']); - $mbox = email_connect($mailbox, $mailconf['user'], $password); - unset($password); - logger("Mail: Connect to " . $mailconf['user']); - if ($mbox) { - $fields = array('last_check' => datetime_convert()); - dba::update('mailacct', $fields, array('id' => $mailconf['id'])); - logger("Mail: Connected to " . $mailconf['user']); - } else { - logger("Mail: Connection error ".$mailconf['user']." ".print_r(imap_errors(), true)); - } - } - - if ($mbox) { - $msgs = email_poll($mbox, $contact['addr']); - - if (count($msgs)) { - logger("Mail: Parsing ".count($msgs)." mails from ".$contact['addr']." for ".$mailconf['user'], LOGGER_DEBUG); - - $metas = email_msg_meta($mbox,implode(',', $msgs)); - if (count($metas) != count($msgs)) { - logger("onepoll: for " . $mailconf['user'] . " there are ". count($msgs) . " messages but received " . count($metas) . " metas", LOGGER_DEBUG); - } else { - $msgs = array_combine($msgs, $metas); - - foreach ($msgs as $msg_uid => $meta) { - logger("Mail: Parsing mail ".$msg_uid, LOGGER_DATA); - - $datarray = array(); - $datarray['verb'] = ACTIVITY_POST; - $datarray['object-type'] = ACTIVITY_OBJ_NOTE; - // $meta = email_msg_meta($mbox, $msg_uid); - // $headers = email_msg_headers($mbox, $msg_uid); - - $datarray['uri'] = msgid2iri(trim($meta->message_id, '<>')); - - // Have we seen it before? - $fields = array('deleted', 'id'); - $condition = array('uid' => $importer_uid, 'uri' => $datarray['uri']); - $r = dba::select('item', $fields, $condition, array('limit' => 1)); - - if (DBM::is_result($r)) { - logger("Mail: Seen before ".$msg_uid." for ".$mailconf['user']." UID: ".$importer_uid." URI: ".$datarray['uri'],LOGGER_DEBUG); - - // Only delete when mails aren't automatically moved or deleted - if (($mailconf['action'] != 1) && ($mailconf['action'] != 3)) - if ($meta->deleted && ! $r['deleted']) { - $fields = array('deleted' => true, 'changed' => datetime_convert()); - dba::update('item', $fields, array('id' => $r['id'])); - } - - switch ($mailconf['action']) { - case 0: - logger("Mail: Seen before ".$msg_uid." for ".$mailconf['user'].". Doing nothing.", LOGGER_DEBUG); - break; - case 1: - logger("Mail: Deleting ".$msg_uid." for ".$mailconf['user']); - imap_delete($mbox, $msg_uid, FT_UID); - break; - case 2: - logger("Mail: Mark as seen ".$msg_uid." for ".$mailconf['user']); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - break; - case 3: - logger("Mail: Moving ".$msg_uid." to ".$mailconf['movetofolder']." for ".$mailconf['user']); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - if ($mailconf['movetofolder'] != "") { - imap_mail_move($mbox, $msg_uid, $mailconf['movetofolder'], FT_UID); - } - break; - } - continue; - } - - - // look for a 'references' or an 'in-reply-to' header and try to match with a parent item we have locally. - $raw_refs = ((property_exists($meta, 'references')) ? str_replace("\t", '', $meta->references) : ''); - if (! trim($raw_refs)) { - $raw_refs = ((property_exists($meta, 'in_reply_to')) ? str_replace("\t", '', $meta->in_reply_to) : ''); - } - $raw_refs = trim($raw_refs); // Don't allow a blank reference in $refs_arr - - if ($raw_refs) { - $refs_arr = explode(' ', $raw_refs); - if (count($refs_arr)) { - for ($x = 0; $x < count($refs_arr); $x ++) { - $refs_arr[$x] = "'" . msgid2iri(str_replace(array('<', '>', ' '),array('', '', ''),dbesc($refs_arr[$x]))) . "'"; - } - } - $qstr = implode(',', $refs_arr); - $r = q("SELECT `parent-uri` FROM `item` USE INDEX (`uid_uri`) WHERE `uri` IN ($qstr) AND `uid` = %d LIMIT 1", - intval($importer_uid) - ); - if (DBM::is_result($r)) { - $datarray['parent-uri'] = $r[0]['parent-uri']; // Set the parent as the top-level item - } - } - - // Decoding the header - $subject = imap_mime_header_decode($meta->subject); - $datarray['title'] = ""; - foreach ($subject as $subpart) { - if ($subpart->charset != "default") { - $datarray['title'] .= iconv($subpart->charset, 'UTF-8//IGNORE', $subpart->text); - } else { - $datarray['title'] .= $subpart->text; - } - } - $datarray['title'] = notags(trim($datarray['title'])); - - //$datarray['title'] = notags(trim($meta->subject)); - $datarray['created'] = datetime_convert('UTC', 'UTC', $meta->date); - - // Is it a reply? - $reply = ((substr(strtolower($datarray['title']), 0, 3) == "re:") || - (substr(strtolower($datarray['title']), 0, 3) == "re-") || - ($raw_refs != "")); - - // Remove Reply-signs in the subject - $datarray['title'] = RemoveReply($datarray['title']); - - // If it seems to be a reply but a header couldn't be found take the last message with matching subject - if (empty($datarray['parent-uri']) && $reply) { - $r = q("SELECT `parent-uri` FROM `item` WHERE `title` = \"%s\" AND `uid` = %d AND `network` = '%s' ORDER BY `created` DESC LIMIT 1", - dbesc(protect_sprintf($datarray['title'])), - intval($importer_uid), - dbesc(NETWORK_MAIL)); - if (DBM::is_result($r)) { - $datarray['parent-uri'] = $r[0]['parent-uri']; - } - } - - if (empty($datarray['parent-uri'])) { - $datarray['parent-uri'] = $datarray['uri']; - } - - $r = email_get_msg($mbox, $msg_uid, $reply); - if (!$r) { - logger("Mail: can't fetch msg ".$msg_uid." for ".$mailconf['user']); - continue; - } - $datarray['body'] = escape_tags($r['body']); - $datarray['body'] = limit_body_size($datarray['body']); - - logger("Mail: Importing ".$msg_uid." for ".$mailconf['user']); - - /// @TODO Adding a gravatar for the original author would be cool - - $from = imap_mime_header_decode($meta->from); - $fromdecoded = ""; - foreach ($from as $frompart) { - if ($frompart->charset != "default") { - $fromdecoded .= iconv($frompart->charset, 'UTF-8//IGNORE', $frompart->text); - } else { - $fromdecoded .= $frompart->text; - } - } - - $fromarr = imap_rfc822_parse_adrlist($fromdecoded, $a->get_hostname()); - - $frommail = $fromarr[0]->mailbox."@".$fromarr[0]->host; - - if (isset($fromarr[0]->personal)) { - $fromname = $fromarr[0]->personal; - } else { - $fromname = $frommail; - } - - $datarray['author-name'] = $fromname; - $datarray['author-link'] = "mailto:".$frommail; - $datarray['author-avatar'] = $contact['photo']; - - $datarray['owner-name'] = $contact['name']; - $datarray['owner-link'] = "mailto:".$contact['addr']; - $datarray['owner-avatar'] = $contact['photo']; - - $datarray['uid'] = $importer_uid; - $datarray['contact-id'] = $contact['id']; - if ($datarray['parent-uri'] === $datarray['uri']) { - $datarray['private'] = 1; - } - if (($contact['network'] === NETWORK_MAIL) && (!PConfig::get($importer_uid, 'system', 'allow_public_email_replies'))) { - $datarray['private'] = 1; - $datarray['allow_cid'] = '<' . $contact['id'] . '>'; - } - - $stored_item = item_store($datarray); - - $condition = array('parent-uri' => $datarray['parent-uri'], 'uid' => $importer_uid); - dba::update('item', array('last-child' => false), $condition); - - dba::update('item', array('last-child' => true), array('id' => $stored_item)); - - switch ($mailconf['action']) { - case 0: - logger("Mail: Seen before ".$msg_uid." for ".$mailconf['user'].". Doing nothing.", LOGGER_DEBUG); - break; - case 1: - logger("Mail: Deleting ".$msg_uid." for ".$mailconf['user']); - imap_delete($mbox, $msg_uid, FT_UID); - break; - case 2: - logger("Mail: Mark as seen ".$msg_uid." for ".$mailconf['user']); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - break; - case 3: - logger("Mail: Moving ".$msg_uid." to ".$mailconf['movetofolder']." for ".$mailconf['user']); - imap_setflag_full($mbox, $msg_uid, "\\Seen", ST_UID); - if ($mailconf['movetofolder'] != "") { - imap_mail_move($mbox, $msg_uid, $mailconf['movetofolder'], FT_UID); - } - break; - } - } - } - } else { - logger("Mail: no mails for ".$mailconf['user']); - } - - logger("Mail: closing connection for ".$mailconf['user']); - imap_close($mbox); - } - } - - if ($xml) { - logger('poller: received xml : ' . $xml, LOGGER_DATA); - if (!strstr($xml, '<')) { - logger('poller: post_handshake: response from ' . $url . ' did not contain XML.'); - - $fields = array('last-update' => datetime_convert(), 'failure_update' => datetime_convert()); - dba::update('contact', $fields, array('id' => $contact['id'])); - - return; - } - - - logger("Consume feed of contact ".$contact['id']); - - consume_feed($xml, $importer, $contact, $hub, 1, 1); - - // do it twice. Ensures that children of parents which may be later in the stream aren't tossed - - consume_feed($xml, $importer, $contact, $hub, 1, 2); - - $hubmode = 'subscribe'; - if ($contact['network'] === NETWORK_DFRN || $contact['blocked'] || $contact['readonly']) { - $hubmode = 'unsubscribe'; - } - - if (($contact['network'] === NETWORK_OSTATUS || $contact['network'] == NETWORK_FEED) && (! $contact['hub-verify'])) { - $hub_update = true; - } - - if ($force) { - $hub_update = true; - } - - logger("Contact ".$contact['id']." returned hub: ".$hub." Network: ".$contact['network']." Relation: ".$contact['rel']." Update: ".$hub_update); - - if (strlen($hub) && $hub_update && (($contact['rel'] != CONTACT_IS_FOLLOWER) || $contact['network'] == NETWORK_FEED)) { - logger('poller: hub ' . $hubmode . ' : ' . $hub . ' contact name : ' . $contact['name'] . ' local user : ' . $importer['name']); - $hubs = explode(',', $hub); - if (count($hubs)) { - foreach ($hubs as $h) { - $h = trim($h); - if (!strlen($h)) { - continue; - } - subscribe_to_hub($h, $importer, $contact, $hubmode); - } - } - } - - $updated = datetime_convert(); - - dba::update('contact', array('last-update' => $updated, 'success_update' => $updated), array('id' => $contact['id'])); - dba::update('gcontact', array('last_contact' => $updated), array('nurl' => $contact['nurl'])); - } elseif (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_FEED))) { - $updated = datetime_convert(); - - dba::update('contact', array('last-update' => $updated, 'failure_update' => $updated), array('id' => $contact['id'])); - dba::update('gcontact', array('last_failure' => $updated), array('nurl' => $contact['nurl'])); - } else { - dba::update('contact', array('last-update' => $updated), array('id' => $contact['id'])); - } - - return; -} diff --git a/include/plugin.php b/include/plugin.php index 2814b2464..276c36bd2 100644 --- a/include/plugin.php +++ b/include/plugin.php @@ -16,19 +16,16 @@ use Friendica\Database\DBM; * @param string $plugin name of the addon * @return boolean */ -if (! function_exists('uninstall_plugin')){ -function uninstall_plugin($plugin){ +function uninstall_plugin($plugin) { logger("Addons: uninstalling " . $plugin); - q("DELETE FROM `addon` WHERE `name` = '%s' ", - dbesc($plugin) - ); + dba::delete('addon', array('name' => $plugin)); @include_once('addon/' . $plugin . '/' . $plugin . '.php'); if (function_exists($plugin . '_uninstall')) { $func = $plugin . '_uninstall'; $func(); } -}} +} /** * @brief installs an addon. @@ -36,12 +33,12 @@ function uninstall_plugin($plugin){ * @param string $plugin name of the addon * @return bool */ -if (! function_exists('install_plugin')){ function install_plugin($plugin) { // silently fail if plugin was removed - if (! file_exists('addon/' . $plugin . '/' . $plugin . '.php')) + if (!file_exists('addon/' . $plugin . '/' . $plugin . '.php')) { return false; + } logger("Addons: installing " . $plugin); $t = @filemtime('addon/' . $plugin . '/' . $plugin . '.php'); @include_once('addon/' . $plugin . '/' . $plugin . '.php'); @@ -62,26 +59,24 @@ function install_plugin($plugin) { dba::update('addon', array('hidden' => true), array('name' => $plugin)); } return true; - } - else { + } else { logger("Addons: FAILED installing " . $plugin); return false; } - -}} +} // reload all updated plugins -if (! function_exists('reload_plugins')) { function reload_plugins() { - $plugins = Config::get('system','addon'); + $plugins = Config::get('system', 'addon'); if (strlen($plugins)) { $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); - if (DBM::is_result($r)) + if (DBM::is_result($r)) { $installed = $r; - else + } else { $installed = array(); + } $parr = explode(',',$plugins); @@ -115,7 +110,7 @@ function reload_plugins() { } } -}} +} /** * @brief check if addon is enabled @@ -137,21 +132,17 @@ function plugin_enabled($plugin) { * @param int $priority A priority (defaults to 0) * @return mixed|bool */ -if (! function_exists('register_hook')) { -function register_hook($hook,$file,$function,$priority=0) { - - $r = q("SELECT * FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s' LIMIT 1", - dbesc($hook), - dbesc($file), - dbesc($function) - ); - if (DBM::is_result($r)) +function register_hook($hook, $file, $function, $priority=0) { + $condition = array('hook' => $hook, 'file' => $file, 'function' => $function); + $exists = dba::exists('hook', $condition); + if ($exists) { return true; + } $r = dba::insert('hook', array('hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority)); return $r; -}} +} /** * @brief unregisters a hook. @@ -161,16 +152,11 @@ function register_hook($hook,$file,$function,$priority=0) { * @param string $function the name of the function that the hook called * @return array */ -if (! function_exists('unregister_hook')) { -function unregister_hook($hook,$file,$function) { - - $r = q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s'", - dbesc($hook), - dbesc($file), - dbesc($function) - ); +function unregister_hook($hook, $file, $function) { + $condition = array('hook' => $hook, 'file' => $file, 'function' => $function); + $r = dba::delete('hook', $condition); return $r; -}} +} function load_hooks() { @@ -224,17 +210,13 @@ function call_single_hook($a, $name, $hook, &$data = null) { $func($a, $data); } else { // remove orphan hooks - q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s'", - dbesc($name), - dbesc($hook[0]), - dbesc($hook[1]) - ); + $condition = array('hook' => $name, 'file' => $hook[0], 'function' => $hook[1]); + dba::delete('hook', $condition); } } //check if an app_menu hook exist for plugin $name. //Return true if the plugin is an app -if (! function_exists('plugin_is_app')) { function plugin_is_app($name) { $a = get_app(); @@ -246,7 +228,7 @@ function plugin_is_app($name) { } return false; -}} +} /** * @brief Parse plugin comment in search of plugin infos. @@ -264,8 +246,7 @@ function plugin_is_app($name) { * @return array with the plugin information */ -if (! function_exists('get_plugin_info')){ -function get_plugin_info($plugin){ +function get_plugin_info($plugin) { $a = get_app(); @@ -285,14 +266,14 @@ function get_plugin_info($plugin){ $r = preg_match("|/\*.*\*/|msU", $f, $m); - if ($r){ + if ($r) { $ll = explode("\n", $m[0]); foreach ( $ll as $l ) { $l = trim($l,"\t\n\r */"); - if ($l!=""){ + if ($l != "") { list($k,$v) = array_map("trim", explode(":",$l,2)); $k= strtolower($k); - if ($k=="author"){ + if ($k == "author") { $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { $info['author'][] = array('name'=>$m[1], 'link'=>$m[2]); @@ -300,7 +281,7 @@ function get_plugin_info($plugin){ $info['author'][] = array('name'=>$v); } } else { - if (array_key_exists($k,$info)){ + if (array_key_exists($k,$info)) { $info[$k]=$v; } } @@ -310,7 +291,7 @@ function get_plugin_info($plugin){ } return $info; -}} +} /** @@ -329,8 +310,7 @@ function get_plugin_info($plugin){ * @return array */ -if (! function_exists('get_theme_info')){ -function get_theme_info($theme){ +function get_theme_info($theme) { $info=Array( 'name' => $theme, 'description' => "", @@ -356,14 +336,14 @@ function get_theme_info($theme){ $r = preg_match("|/\*.*\*/|msU", $f, $m); - if ($r){ + if ($r) { $ll = explode("\n", $m[0]); foreach ( $ll as $l ) { $l = trim($l,"\t\n\r */"); - if ($l!=""){ + if ($l != "") { list($k,$v) = array_map("trim", explode(":",$l,2)); $k= strtolower($k); - if ($k=="author"){ + if ($k == "author") { $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { @@ -371,8 +351,7 @@ function get_theme_info($theme){ } else { $info['author'][] = array('name'=>$v); } - } - elseif ($k=="maintainer"){ + } elseif ($k == "maintainer") { $r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); if ($r) { $info['maintainer'][] = array('name'=>$m[1], 'link'=>$m[2]); @@ -380,7 +359,7 @@ function get_theme_info($theme){ $info['maintainer'][] = array('name'=>$v); } } else { - if (array_key_exists($k,$info)){ + if (array_key_exists($k,$info)) { $info[$k]=$v; } } @@ -390,7 +369,7 @@ function get_theme_info($theme){ } return $info; -}} +} /** * @brief Returns the theme's screenshot. @@ -411,8 +390,7 @@ function get_theme_screenshot($theme) { } // install and uninstall theme -if (! function_exists('uninstall_theme')){ -function uninstall_theme($theme){ +function uninstall_theme($theme) { logger("Addons: uninstalling theme " . $theme); include_once("view/theme/$theme/theme.php"); @@ -420,9 +398,8 @@ function uninstall_theme($theme){ $func = "{$theme}_uninstall"; $func(); } -}} +} -if (! function_exists('install_theme')){ function install_theme($theme) { // silently fail if theme was removed @@ -443,7 +420,7 @@ function install_theme($theme) { return false; } -}} +} /** * @brief Get the full path to relevant theme files by filename diff --git a/include/poller.php b/include/poller.php deleted file mode 100644 index 3f6290a98..000000000 --- a/include/poller.php +++ /dev/null @@ -1,58 +0,0 @@ -set_baseurl(Config::get('system', 'url')); - - load_hooks(); - - $run_cron = (($argc <= 1) || ($argv[1] != "no_cron")); - Worker::processQueue($run_cron); - return; -} - -if (array_search(__file__, get_included_files()) === 0) { - poller_run($_SERVER["argv"], $_SERVER["argc"]); - - Worker::unclaimProcess(); - - get_app()->end_process(); - - killme(); -} diff --git a/include/post_update.php b/include/post_update.php index 1d27f3399..f67c064da 100644 --- a/include/post_update.php +++ b/include/post_update.php @@ -5,6 +5,8 @@ use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Model\GlobalContact; +use Friendica\Object\Contact; /** * @brief Calls the post update functions @@ -72,7 +74,7 @@ function post_update_1192() { // Set the "gcontact-id" in the item table and add a new gcontact entry if needed foreach ($item_arr AS $item) { - $gcontact_id = get_gcontact_id(array("url" => $item['author-link'], "network" => $item['network'], + $gcontact_id = GlobalContact::getId(array("url" => $item['author-link'], "network" => $item['network'], "photo" => $item['author-avatar'], "name" => $item['author-name'])); q("UPDATE `item` SET `gcontact-id` = %d WHERE `uid` = %d AND `author-link` = '%s' AND `gcontact-id` = 0", intval($gcontact_id), intval($item["uid"]), dbesc($item["author-link"])); @@ -208,8 +210,8 @@ function post_update_1198() { // Set the "gcontact-id" in the item table and add a new gcontact entry if needed foreach ($item_arr AS $item) { - $author_id = get_contact($item["author-link"], 0); - $owner_id = get_contact($item["owner-link"], 0); + $author_id = Contact::getIdForURL($item["author-link"], 0); + $owner_id = Contact::getIdForURL($item["owner-link"], 0); if ($author_id == 0) $author_id = -1; diff --git a/include/profile_update.php b/include/profile_update.php deleted file mode 100644 index 0c5de0156..000000000 --- a/include/profile_update.php +++ /dev/null @@ -1,12 +0,0 @@ - 1) { - $pubsubpublish_id = intval($argv[1]); - } else { - // We'll push to each subscriber that has push > 0, - // i.e. there has been an update (set in notifier.php). - $r = q("SELECT `id`, `callback_url` FROM `push_subscriber` WHERE `push` > 0 ORDER BY `last_update` DESC"); - - foreach ($r as $rr) { - logger("Publish feed to ".$rr["callback_url"], LOGGER_DEBUG); - Worker::add(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true), - 'pubsubpublish', (int)$rr["id"]); - } - } - - handle_pubsubhubbub($pubsubpublish_id); - - return; -} - -function handle_pubsubhubbub($id) { - global $a; - - $r = q("SELECT * FROM `push_subscriber` WHERE `id` = %d", intval($id)); - if (!DBM::is_result($r)) { - return; - } - - $rr = $r[0]; - - /// @todo Check server status with poco_check_server() - // Before this can be done we need a way to safely detect the server url. - - logger("Generate feed of user ".$rr['nickname']." to ".$rr['callback_url']." - last updated ".$rr['last_update'], LOGGER_DEBUG); - - $last_update = $rr['last_update']; - $params = ostatus::feed($a, $rr['nickname'], $last_update); - - if (!$params) { - return; - } - - $hmac_sig = hash_hmac("sha1", $params, $rr['secret']); - - $headers = array("Content-type: application/atom+xml", - sprintf("Link: <%s>;rel=hub,<%s>;rel=self", - System::baseUrl().'/pubsubhubbub/'.$rr['nickname'], - $rr['topic']), - "X-Hub-Signature: sha1=".$hmac_sig); - - logger('POST '.print_r($headers, true)."\n".$params, LOGGER_DEBUG); - - post_url($rr['callback_url'], $params, $headers); - $ret = $a->get_curl_code(); - - if ($ret >= 200 && $ret <= 299) { - logger('successfully pushed to '.$rr['callback_url']); - - // set last_update to the "created" date of the last item, and reset push=0 - q("UPDATE `push_subscriber` SET `push` = 0, last_update = '%s' WHERE id = %d", - dbesc($last_update), - intval($rr['id'])); - - } else { - logger('error when pushing to '.$rr['callback_url'].' HTTP: '.$ret); - - // we use the push variable also as a counter, if we failed we - // increment this until some upper limit where we give up - $new_push = intval($rr['push']) + 1; - - if ($new_push > 30) // OK, let's give up - $new_push = 0; - - q("UPDATE `push_subscriber` SET `push` = %d WHERE id = %d", - $new_push, - intval($rr['id'])); - } -} diff --git a/include/queue.php b/include/queue.php deleted file mode 100644 index a56c41d97..000000000 --- a/include/queue.php +++ /dev/null @@ -1,191 +0,0 @@ - 1) { - $queue_id = intval($argv[1]); - } else { - $queue_id = 0; - } - - $cachekey_deadguy = 'queue_run:deadguy:'; - $cachekey_server = 'queue_run:server:'; - - if (!$queue_id) { - logger('queue: start'); - - // Handling the pubsubhubbub requests - Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'pubsubpublish'); - - $r = q( - "SELECT `queue`.*, `contact`.`name`, `contact`.`uid` FROM `queue` - INNER JOIN `contact` ON `queue`.`cid` = `contact`.`id` - WHERE `queue`.`created` < UTC_TIMESTAMP() - INTERVAL 3 DAY" - ); - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - logger('Removing expired queue item for ' . $rr['name'] . ', uid=' . $rr['uid']); - logger('Expired queue data: ' . $rr['content'], LOGGER_DATA); - } - q("DELETE FROM `queue` WHERE `created` < UTC_TIMESTAMP() - INTERVAL 3 DAY"); - } - - /* - * For the first 12 hours we'll try to deliver every 15 minutes - * After that, we'll only attempt delivery once per hour. - */ - $r = q("SELECT `id` FROM `queue` WHERE ((`created` > UTC_TIMESTAMP() - INTERVAL 12 HOUR AND `last` < UTC_TIMESTAMP() - INTERVAL 15 MINUTE) OR (`last` < UTC_TIMESTAMP() - INTERVAL 1 HOUR)) ORDER BY `cid`, `created`"); - - call_hooks('queue_predeliver', $a, $r); - - if (DBM::is_result($r)) { - foreach ($r as $q_item) { - logger('Call queue for id '.$q_item['id']); - Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "queue", (int)$q_item['id']); - } - } - return; - } - - - // delivering - - require_once 'include/salmon.php'; - - $r = q( - "SELECT * FROM `queue` WHERE `id` = %d LIMIT 1", - intval($queue_id) - ); - - if (!DBM::is_result($r)) { - return; - } - - $q_item = $r[0]; - - $c = q( - "SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", - intval($q_item['cid']) - ); - - if (!DBM::is_result($c)) { - remove_queue_item($q_item['id']); - return; - } - - $dead = Cache::get($cachekey_deadguy.$c[0]['notify']); - - if (!is_null($dead) && $dead) { - logger('queue: skipping known dead url: '.$c[0]['notify']); - update_queue_time($q_item['id']); - return; - } - - $server = poco_detect_server($c[0]['url']); - - if ($server != "") { - $vital = Cache::get($cachekey_server.$server); - - if (is_null($vital)) { - logger("Check server ".$server." (".$c[0]["network"].")"); - - $vital = poco_check_server($server, $c[0]["network"], true); - Cache::set($cachekey_server.$server, $vital, CACHE_QUARTER_HOUR); - } - - if (!is_null($vital) && !$vital) { - logger('queue: skipping dead server: '.$server); - update_queue_time($q_item['id']); - return; - } - } - - $u = q( - "SELECT `user`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey` - FROM `user` WHERE `uid` = %d LIMIT 1", - intval($c[0]['uid']) - ); - if (!DBM::is_result($u)) { - remove_queue_item($q_item['id']); - return; - } - - $data = $q_item['content']; - $public = $q_item['batch']; - $contact = $c[0]; - $owner = $u[0]; - - $deliver_status = 0; - - switch ($contact['network']) { - case NETWORK_DFRN: - logger('queue: dfrndelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>'); - $deliver_status = DFRN::deliver($owner, $contact, $data); - - if ($deliver_status == (-1)) { - update_queue_time($q_item['id']); - Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR); - } else { - remove_queue_item($q_item['id']); - } - break; - case NETWORK_OSTATUS: - if ($contact['notify']) { - logger('queue: slapdelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>'); - $deliver_status = slapper($owner, $contact['notify'], $data); - - if ($deliver_status == (-1)) { - update_queue_time($q_item['id']); - Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR); - } else { - remove_queue_item($q_item['id']); - } - } - break; - case NETWORK_DIASPORA: - if ($contact['notify']) { - logger('queue: diaspora_delivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>'); - $deliver_status = Diaspora::transmit($owner, $contact, $data, $public, true); - - if ($deliver_status == (-1)) { - update_queue_time($q_item['id']); - Cache::set($cachekey_deadguy.$contact['notify'], true, CACHE_QUARTER_HOUR); - } else { - remove_queue_item($q_item['id']); - } - } - break; - - default: - $params = array('owner' => $owner, 'contact' => $contact, 'queue' => $q_item, 'result' => false); - call_hooks('queue_deliver', $a, $params); - - if ($params['result']) { - remove_queue_item($q_item['id']); - } else { - update_queue_time($q_item['id']); - } - break; - } - logger('Deliver status '.(int)$deliver_status.' for item '.$q_item['id'].' to '.$contact['name'].' <'.$contact['url'].'>'); - - return; -} diff --git a/include/queue_fn.php b/include/queue_fn.php index e6fd14e07..c4ab229ae 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -13,9 +13,7 @@ function update_queue_time($id) { function remove_queue_item($id) { logger('queue: remove queue item ' . $id); - q("DELETE FROM `queue` WHERE `id` = %d", - intval($id) - ); + dba::delete('queue', array('id' => $id)); } /** diff --git a/include/remove_contact.php b/include/remove_contact.php deleted file mode 100644 index 9d4b1e4c3..000000000 --- a/include/remove_contact.php +++ /dev/null @@ -1,24 +0,0 @@ - $id)); - if ($r) { - return; - } - - // Now we delete all the depending table entries - dba::delete('contact', array('id' => $id)); -} diff --git a/include/salmon.php b/include/salmon.php index 9a1ef72e5..264b92e80 100644 --- a/include/salmon.php +++ b/include/salmon.php @@ -112,7 +112,7 @@ function slapper($owner, $url, $slap) $namespaces = array("me" => "http://salmon-protocol.org/ns/magic-env"); - $salmon = XML::from_array($xmldata, $xml, false, $namespaces); + $salmon = XML::fromArray($xmldata, $xml, false, $namespaces); // slap them post_url($url, $salmon, array( @@ -138,7 +138,7 @@ function slapper($owner, $url, $slap) $namespaces = array("me" => "http://salmon-protocol.org/ns/magic-env"); - $salmon = XML::from_array($xmldata, $xml, false, $namespaces); + $salmon = XML::fromArray($xmldata, $xml, false, $namespaces); // slap them post_url($url, $salmon, array( @@ -161,7 +161,7 @@ function slapper($owner, $url, $slap) $namespaces = array("me" => "http://salmon-protocol.org/ns/magic-env"); - $salmon = XML::from_array($xmldata, $xml, false, $namespaces); + $salmon = XML::fromArray($xmldata, $xml, false, $namespaces); // slap them post_url($url, $salmon, array( diff --git a/include/security.php b/include/security.php index 18793ce06..6f6ef94b6 100644 --- a/include/security.php +++ b/include/security.php @@ -15,7 +15,7 @@ use Friendica\Database\DBM; */ function cookie_hash($user) { return(hash("sha256", Config::get("system", "site_prvkey"). - $user["uprvkey"]. + $user["prvkey"]. $user["password"])); } diff --git a/include/shadowupdate.php b/include/shadowupdate.php deleted file mode 100644 index c41b23122..000000000 --- a/include/shadowupdate.php +++ /dev/null @@ -1,29 +0,0 @@ -get_curl_code(), LOGGER_DEBUG); - - if (($a->get_curl_code() > 299) || (! $s)) { - return; - } - - $j = json_decode($s); - - logger('poco_load: json: ' . print_r($j,true),LOGGER_DATA); - - if (! isset($j->entry)) { - return; - } - - $total = 0; - foreach ($j->entry as $entry) { - - $total ++; - $profile_url = ''; - $profile_photo = ''; - $connect_url = ''; - $name = ''; - $network = ''; - $updated = NULL_DATE; - $location = ''; - $about = ''; - $keywords = ''; - $gender = ''; - $contact_type = -1; - $generation = 0; - - $name = $entry->displayName; - - if (isset($entry->urls)) { - foreach ($entry->urls as $url) { - if ($url->type == 'profile') { - $profile_url = $url->value; - continue; - } - if ($url->type == 'webfinger') { - $connect_url = str_replace('acct:' , '', $url->value); - continue; - } - } - } - if (isset($entry->photos)) { - foreach ($entry->photos as $photo) { - if ($photo->type == 'profile') { - $profile_photo = $photo->value; - continue; - } - } - } - - if (isset($entry->updated)) { - $updated = date("Y-m-d H:i:s", strtotime($entry->updated)); - } - - if (isset($entry->network)) { - $network = $entry->network; - } - - if (isset($entry->currentLocation)) { - $location = $entry->currentLocation; - } - - if (isset($entry->aboutMe)) { - $about = html2bbcode($entry->aboutMe); - } - - if (isset($entry->gender)) { - $gender = $entry->gender; - } - - if (isset($entry->generation) && ($entry->generation > 0)) { - $generation = ++$entry->generation; - } - - if (isset($entry->tags)) { - foreach ($entry->tags as $tag) { - $keywords = implode(", ", $tag); - } - } - - if (isset($entry->contactType) && ($entry->contactType >= 0)) { - $contact_type = $entry->contactType; - } - - $gcontact = array("url" => $profile_url, - "name" => $name, - "network" => $network, - "photo" => $profile_photo, - "about" => $about, - "location" => $location, - "gender" => $gender, - "keywords" => $keywords, - "connect" => $connect_url, - "updated" => $updated, - "contact-type" => $contact_type, - "generation" => $generation); - - try { - $gcontact = sanitize_gcontact($gcontact); - $gcid = update_gcontact($gcontact); - - link_gcontact($gcid, $uid, $cid, $zcid); - } catch (Exception $e) { - logger($e->getMessage(), LOGGER_DEBUG); - } - } - logger("poco_load: loaded $total entries",LOGGER_DEBUG); - - q("DELETE FROM `glink` WHERE `cid` = %d AND `uid` = %d AND `zcid` = %d AND `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", - intval($cid), - intval($uid), - intval($zcid) - ); - -} -/** - * @brief Sanitize the given gcontact data - * - * @param array $gcontact array with gcontact data - * @throw Exception - * - * Generation: - * 0: No definition - * 1: Profiles on this server - * 2: Contacts of profiles on this server - * 3: Contacts of contacts of profiles on this server - * 4: ... - * - */ -function sanitize_gcontact($gcontact) { - - if ($gcontact['url'] == "") { - throw new Exception('URL is empty'); - } - - $urlparts = parse_url($gcontact['url']); - if (!isset($urlparts["scheme"])) { - throw new Exception("This (".$gcontact['url'].") doesn't seem to be an url."); - } - - if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com", - "identi.ca", "alpha.app.net"))) { - throw new Exception('Contact from a non federated network ignored. ('.$gcontact['url'].')'); - } - - // Don't store the statusnet connector as network - // We can't simply set this to NETWORK_OSTATUS since the connector could have fetched posts from friendica as well - if ($gcontact['network'] == NETWORK_STATUSNET) { - $gcontact['network'] = ""; - } - - // Assure that there are no parameter fragments in the profile url - if (in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { - $gcontact['url'] = clean_contact_url($gcontact['url']); - } - - $alternate = poco_alternate_ostatus_url($gcontact['url']); - - // The global contacts should contain the original picture, not the cached one - if (($gcontact['generation'] != 1) && stristr(normalise_link($gcontact['photo']), normalise_link(System::baseUrl()."/photo/"))) { - $gcontact['photo'] = ""; - } - - if (!isset($gcontact['network'])) { - $r = q("SELECT `network` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' AND `network` != '' AND `network` != '%s' LIMIT 1", - dbesc(normalise_link($gcontact['url'])), dbesc(NETWORK_STATUSNET) - ); - if (DBM::is_result($r)) { - $gcontact['network'] = $r[0]["network"]; - } - - if (($gcontact['network'] == "") || ($gcontact['network'] == NETWORK_OSTATUS)) { - $r = q("SELECT `network`, `url` FROM `contact` WHERE `uid` = 0 AND `alias` IN ('%s', '%s') AND `network` != '' AND `network` != '%s' LIMIT 1", - dbesc($gcontact['url']), dbesc(normalise_link($gcontact['url'])), dbesc(NETWORK_STATUSNET) - ); - if (DBM::is_result($r)) { - $gcontact['network'] = $r[0]["network"]; - } - } - } - - $gcontact['server_url'] = ''; - $gcontact['network'] = ''; - - $x = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", - dbesc(normalise_link($gcontact['url'])) - ); - - if (DBM::is_result($x)) { - if (!isset($gcontact['network']) && ($x[0]["network"] != NETWORK_STATUSNET)) { - $gcontact['network'] = $x[0]["network"]; - } - if ($gcontact['updated'] <= NULL_DATE) { - $gcontact['updated'] = $x[0]["updated"]; - } - if (!isset($gcontact['server_url']) && (normalise_link($x[0]["server_url"]) != normalise_link($x[0]["url"]))) { - $gcontact['server_url'] = $x[0]["server_url"]; - } - if (!isset($gcontact['addr'])) { - $gcontact['addr'] = $x[0]["addr"]; - } - } - - if ((!isset($gcontact['network']) || !isset($gcontact['name']) || !isset($gcontact['addr']) || !isset($gcontact['photo']) || !isset($gcontact['server_url']) || $alternate) - && poco_reachable($gcontact['url'], $gcontact['server_url'], $gcontact['network'], false)) { - $data = Probe::uri($gcontact['url']); - - if ($data["network"] == NETWORK_PHANTOM) { - throw new Exception('Probing for URL '.$gcontact['url'].' failed'); - } - - $orig_profile = $gcontact['url']; - - $gcontact["server_url"] = $data["baseurl"]; - - $gcontact = array_merge($gcontact, $data); - - if ($alternate && ($gcontact['network'] == NETWORK_OSTATUS)) { - // Delete the old entry - if it exists - $r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); - if (DBM::is_result($r)) { - q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); - q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"])); - } - } - } - - if (!isset($gcontact['name']) || !isset($gcontact['photo'])) { - throw new Exception('No name and photo for URL '.$gcontact['url']); - } - - if (!in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) { - throw new Exception('No federated network ('.$gcontact['network'].') detected for URL '.$gcontact['url']); - } - - if (!isset($gcontact['server_url'])) { - // We check the server url to be sure that it is a real one - $server_url = poco_detect_server($gcontact['url']); - - // We are now sure that it is a correct URL. So we use it in the future - if ($server_url != "") { - $gcontact['server_url'] = $server_url; - } - } - - // The server URL doesn't seem to be valid, so we don't store it. - if (!poco_check_server($gcontact['server_url'], $gcontact['network'])) { - $gcontact['server_url'] = ""; - } - - return $gcontact; -} - -/** - * @brief Link the gcontact entry with user, contact and global contact - * - * @param integer $gcid Global contact ID - * @param integer $cid Contact ID - * @param integer $uid User ID - * @param integer $zcid Global Contact ID - * * - */ -function link_gcontact($gcid, $uid = 0, $cid = 0, $zcid = 0) { - - if ($gcid <= 0) { - return; - } - - $r = q("SELECT * FROM `glink` WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d LIMIT 1", - intval($cid), - intval($uid), - intval($gcid), - intval($zcid) - ); - - if (!DBM::is_result($r)) { - q("INSERT INTO `glink` (`cid`, `uid`, `gcid`, `zcid`, `updated`) VALUES (%d, %d, %d, %d, '%s') ", - intval($cid), - intval($uid), - intval($gcid), - intval($zcid), - dbesc(datetime_convert()) - ); - } else { - q("UPDATE `glink` SET `updated` = '%s' WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d", - dbesc(datetime_convert()), - intval($cid), - intval($uid), - intval($gcid), - intval($zcid) - ); - } -} - -function poco_reachable($profile, $server = "", $network = "", $force = false) { - - if ($server == "") { - $server = poco_detect_server($profile); - } - - if ($server == "") { - return true; - } - - return poco_check_server($server, $network, $force); -} - -function poco_detect_server($profile) { - - // Try to detect the server path based upon some known standard paths - $server_url = ""; - - if ($server_url == "") { - $friendica = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $profile); - if ($friendica != $profile) { - $server_url = $friendica; - $network = NETWORK_DFRN; - } - } - - if ($server_url == "") { - $diaspora = preg_replace("=(https?://)(.*)/u/(.*)=ism", "$1$2", $profile); - if ($diaspora != $profile) { - $server_url = $diaspora; - $network = NETWORK_DIASPORA; - } - } - - if ($server_url == "") { - $red = preg_replace("=(https?://)(.*)/channel/(.*)=ism", "$1$2", $profile); - if ($red != $profile) { - $server_url = $red; - $network = NETWORK_DIASPORA; - } - } - - // Mastodon - if ($server_url == "") { - $mastodon = preg_replace("=(https?://)(.*)/users/(.*)=ism", "$1$2", $profile); - if ($mastodon != $profile) { - $server_url = $mastodon; - $network = NETWORK_OSTATUS; - } - } - - // Numeric OStatus variant - if ($server_url == "") { - $ostatus = preg_replace("=(https?://)(.*)/user/(.*)=ism", "$1$2", $profile); - if ($ostatus != $profile) { - $server_url = $ostatus; - $network = NETWORK_OSTATUS; - } - } - - // Wild guess - if ($server_url == "") { - $base = preg_replace("=(https?://)(.*?)/(.*)=ism", "$1$2", $profile); - if ($base != $profile) { - $server_url = $base; - $network = NETWORK_PHANTOM; - } - } - - if ($server_url == "") { - return ""; - } - - $r = q("SELECT `id` FROM `gserver` WHERE `nurl` = '%s' AND `last_contact` > `last_failure`", - dbesc(normalise_link($server_url))); - if (DBM::is_result($r)) { - return $server_url; - } - - // Fetch the host-meta to check if this really is a server - $serverret = z_fetch_url($server_url."/.well-known/host-meta"); - if (!$serverret["success"]) { - return ""; - } - - return $server_url; -} - -function poco_alternate_ostatus_url($url) { - return(preg_match("=https?://.+/user/\d+=ism", $url, $matches)); -} - -function poco_last_updated($profile, $force = false) { - - $gcontacts = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'", - dbesc(normalise_link($profile))); - - if (!DBM::is_result($gcontacts)) { - return false; - } - - $contact = array("url" => $profile); - - if ($gcontacts[0]["created"] <= NULL_DATE) { - $contact['created'] = datetime_convert(); - } - - if ($force) { - $server_url = normalise_link(poco_detect_server($profile)); - } - - if (($server_url == '') && ($gcontacts[0]["server_url"] != "")) { - $server_url = $gcontacts[0]["server_url"]; - } - - if (!$force && (($server_url == '') || ($gcontacts[0]["server_url"] == $gcontacts[0]["nurl"]))) { - $server_url = normalise_link(poco_detect_server($profile)); - } - - if (!in_array($gcontacts[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_FEED, NETWORK_OSTATUS, ""))) { - logger("Profile ".$profile.": Network type ".$gcontacts[0]["network"]." can't be checked", LOGGER_DEBUG); - return false; - } - - if ($server_url != "") { - if (!poco_check_server($server_url, $gcontacts[0]["network"], $force)) { - if ($force) { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); - } - - logger("Profile ".$profile.": Server ".$server_url." wasn't reachable.", LOGGER_DEBUG); - return false; - } - $contact['server_url'] = $server_url; - } - - if (in_array($gcontacts[0]["network"], array("", NETWORK_FEED))) { - $server = q("SELECT `network` FROM `gserver` WHERE `nurl` = '%s' AND `network` != ''", - dbesc(normalise_link($server_url))); - - if ($server) { - $contact['network'] = $server[0]["network"]; - } else { - return false; - } - } - - // noscrape is really fast so we don't cache the call. - if (($server_url != "") && ($gcontacts[0]["nick"] != "")) { - - // Use noscrape if possible - $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($server_url))); - - if ($server) { - $noscraperet = z_fetch_url($server[0]["noscrape"]."/".$gcontacts[0]["nick"]); - - if ($noscraperet["success"] && ($noscraperet["body"] != "")) { - - $noscrape = json_decode($noscraperet["body"], true); - - if (is_array($noscrape)) { - $contact["network"] = $server[0]["network"]; - - if (isset($noscrape["fn"])) { - $contact["name"] = $noscrape["fn"]; - } - if (isset($noscrape["comm"])) { - $contact["community"] = $noscrape["comm"]; - } - if (isset($noscrape["tags"])) { - $keywords = implode(" ", $noscrape["tags"]); - if ($keywords != "") { - $contact["keywords"] = $keywords; - } - } - - $location = formatted_location($noscrape); - if ($location) { - $contact["location"] = $location; - } - if (isset($noscrape["dfrn-notify"])) { - $contact["notify"] = $noscrape["dfrn-notify"]; - } - // Remove all fields that are not present in the gcontact table - unset($noscrape["fn"]); - unset($noscrape["key"]); - unset($noscrape["homepage"]); - unset($noscrape["comm"]); - unset($noscrape["tags"]); - unset($noscrape["locality"]); - unset($noscrape["region"]); - unset($noscrape["country-name"]); - unset($noscrape["contacts"]); - unset($noscrape["dfrn-request"]); - unset($noscrape["dfrn-confirm"]); - unset($noscrape["dfrn-notify"]); - unset($noscrape["dfrn-poll"]); - - // Set the date of the last contact - /// @todo By now the function "update_gcontact" doesn't work with this field - //$contact["last_contact"] = datetime_convert(); - - $contact = array_merge($contact, $noscrape); - - update_gcontact($contact); - - if (trim($noscrape["updated"]) != "") { - q("UPDATE `gcontact` SET `last_contact` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); - - logger("Profile ".$profile." was last updated at ".$noscrape["updated"]." (noscrape)", LOGGER_DEBUG); - - return $noscrape["updated"]; - } - } - } - } - } - - // If we only can poll the feed, then we only do this once a while - if (!$force && !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) { - logger("Profile ".$profile." was last updated at ".$gcontacts[0]["updated"]." (cached)", LOGGER_DEBUG); - - update_gcontact($contact); - return $gcontacts[0]["updated"]; - } - - $data = Probe::uri($profile); - - // Is the profile link the alternate OStatus link notation? (http://domain.tld/user/4711) - // Then check the other link and delete this one - if (($data["network"] == NETWORK_OSTATUS) && poco_alternate_ostatus_url($profile) && - (normalise_link($profile) == normalise_link($data["alias"])) && - (normalise_link($profile) != normalise_link($data["url"]))) { - - // Delete the old entry - q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($profile))); - q("DELETE FROM `glink` WHERE `gcid` = %d", intval($gcontacts[0]["id"])); - - $gcontact = array_merge($gcontacts[0], $data); - - $gcontact["server_url"] = $data["baseurl"]; - - try { - $gcontact = sanitize_gcontact($gcontact); - update_gcontact($gcontact); - - poco_last_updated($data["url"], $force); - } catch (Exception $e) { - logger($e->getMessage(), LOGGER_DEBUG); - } - - logger("Profile ".$profile." was deleted", LOGGER_DEBUG); - return false; - } - - if (($data["poll"] == "") || (in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM)))) { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); - - logger("Profile ".$profile." wasn't reachable (profile)", LOGGER_DEBUG); - return false; - } - - $contact = array_merge($contact, $data); - - $contact["server_url"] = $data["baseurl"]; - - update_gcontact($contact); - - $feedret = z_fetch_url($data["poll"]); - - if (!$feedret["success"]) { - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($profile))); - - logger("Profile ".$profile." wasn't reachable (no feed)", LOGGER_DEBUG); - return false; - } - - $doc = new DOMDocument(); - @$doc->loadXML($feedret["body"]); - - $xpath = new DomXPath($doc); - $xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom"); - - $entries = $xpath->query('/atom:feed/atom:entry'); - - $last_updated = ""; - - foreach ($entries as $entry) { - $published = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue; - $updated = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue; - - if ($last_updated < $published) - $last_updated = $published; - - if ($last_updated < $updated) - $last_updated = $updated; - } - - // Maybe there aren't any entries. Then check if it is a valid feed - if ($last_updated == "") { - if ($xpath->query('/atom:feed')->length > 0) { - $last_updated = NULL_DATE; - } - } - q("UPDATE `gcontact` SET `updated` = '%s', `last_contact` = '%s' WHERE `nurl` = '%s'", - dbesc(DBM::date($last_updated)), dbesc(DBM::date()), dbesc(normalise_link($profile))); - - if (($gcontacts[0]["generation"] == 0)) { - q("UPDATE `gcontact` SET `generation` = 9 WHERE `nurl` = '%s'", - dbesc(normalise_link($profile))); - } - - logger("Profile ".$profile." was last updated at ".$last_updated, LOGGER_DEBUG); - - return($last_updated); -} - -function poco_do_update($created, $updated, $last_failure, $last_contact) { - $now = strtotime(datetime_convert()); - - if ($updated > $last_contact) { - $contact_time = strtotime($updated); - } else { - $contact_time = strtotime($last_contact); - } - - $failure_time = strtotime($last_failure); - $created_time = strtotime($created); - - // If there is no "created" time then use the current time - if ($created_time <= 0) { - $created_time = $now; - } - - // If the last contact was less than 24 hours then don't update - if (($now - $contact_time) < (60 * 60 * 24)) { - return false; - } - - // If the last failure was less than 24 hours then don't update - if (($now - $failure_time) < (60 * 60 * 24)) { - return false; - } - - // If the last contact was less than a week ago and the last failure is older than a week then don't update - //if ((($now - $contact_time) < (60 * 60 * 24 * 7)) && ($contact_time > $failure_time)) - // return false; - - // If the last contact time was more than a week ago and the contact was created more than a week ago, then only try once a week - if ((($now - $contact_time) > (60 * 60 * 24 * 7)) && (($now - $created_time) > (60 * 60 * 24 * 7)) && (($now - $failure_time) < (60 * 60 * 24 * 7))) { - return false; - } - - // If the last contact time was more than a month ago and the contact was created more than a month ago, then only try once a month - if ((($now - $contact_time) > (60 * 60 * 24 * 30)) && (($now - $created_time) > (60 * 60 * 24 * 30)) && (($now - $failure_time) < (60 * 60 * 24 * 30))) { - return false; - } - - return true; -} - -function poco_to_boolean($val) { - if (($val == "true") || ($val == 1)) { - return true; - } elseif (($val == "false") || ($val == 0)) { - return false; - } - - return $val; -} - -/** - * @brief Detect server type (Hubzilla or Friendica) via the poco data - * - * @param object $data POCO data - * @return array Server data - */ -function poco_detect_poco_data($data) { - $server = false; - - if (!isset($data->entry)) { - return false; - } - - if (count($data->entry) == 0) { - return false; - } - - if (!isset($data->entry[0]->urls)) { - return false; - } - - if (count($data->entry[0]->urls) == 0) { - return false; - } - - foreach ($data->entry[0]->urls as $url) { - if ($url->type == 'zot') { - $server = array(); - $server["platform"] = 'Hubzilla'; - $server["network"] = NETWORK_DIASPORA; - return $server; - } - } - return false; -} - -/** - * @brief Detect server type by using the nodeinfo data - * - * @param string $server_url address of the server - * @return array Server data - */ -function poco_fetch_nodeinfo($server_url) { - $serverret = z_fetch_url($server_url."/.well-known/nodeinfo"); - if (!$serverret["success"]) { - return false; - } - - $nodeinfo = json_decode($serverret['body']); - - if (!is_object($nodeinfo)) { - return false; - } - - if (!is_array($nodeinfo->links)) { - return false; - } - - $nodeinfo_url = ''; - - foreach ($nodeinfo->links as $link) { - if ($link->rel == 'http://nodeinfo.diaspora.software/ns/schema/1.0') { - $nodeinfo_url = $link->href; - } - } - - if ($nodeinfo_url == '') { - return false; - } - - $serverret = z_fetch_url($nodeinfo_url); - if (!$serverret["success"]) { - return false; - } - - $nodeinfo = json_decode($serverret['body']); - - if (!is_object($nodeinfo)) { - return false; - } - - $server = array(); - - $server['register_policy'] = REGISTER_CLOSED; - - if (is_bool($nodeinfo->openRegistrations) && $nodeinfo->openRegistrations) { - $server['register_policy'] = REGISTER_OPEN; - } - - if (is_object($nodeinfo->software)) { - if (isset($nodeinfo->software->name)) { - $server['platform'] = $nodeinfo->software->name; - } - - if (isset($nodeinfo->software->version)) { - $server['version'] = $nodeinfo->software->version; - // Version numbers on Nodeinfo are presented with additional info, e.g.: - // 0.6.3.0-p1702cc1c, 0.6.99.0-p1b9ab160 or 3.4.3-2-1191. - $server['version'] = preg_replace("=(.+)-(.{4,})=ism", "$1", $server['version']); - } - } - - if (is_object($nodeinfo->metadata)) { - if (isset($nodeinfo->metadata->nodeName)) { - $server['site_name'] = $nodeinfo->metadata->nodeName; - } - } - - $diaspora = false; - $friendica = false; - $gnusocial = false; - - if (is_array($nodeinfo->protocols->inbound)) { - foreach ($nodeinfo->protocols->inbound as $inbound) { - if ($inbound == 'diaspora') { - $diaspora = true; - } - if ($inbound == 'friendica') { - $friendica = true; - } - if ($inbound == 'gnusocial') { - $gnusocial = true; - } - } - } - - if ($gnusocial) { - $server['network'] = NETWORK_OSTATUS; - } - if ($diaspora) { - $server['network'] = NETWORK_DIASPORA; - } - if ($friendica) { - $server['network'] = NETWORK_DFRN; - } - - if (!$server) { - return false; - } - - return $server; -} - -/** - * @brief Detect server type (Hubzilla or Friendica) via the front page body - * - * @param string $body Front page of the server - * @return array Server data - */ -function poco_detect_server_type($body) { - $server = false; - - $doc = new DOMDocument(); - @$doc->loadHTML($body); - $xpath = new DomXPath($doc); - - $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; - } - } - if ($attr['name'] == 'generator') { - $version_part = explode(" ", $attr['content']); - if (count($version_part) == 2) { - if (in_array($version_part[0], array("Friendika", "Friendica"))) { - $server = array(); - $server["platform"] = $version_part[0]; - $server["version"] = $version_part[1]; - $server["network"] = NETWORK_DFRN; - } - } - } - } - - if (!$server) { - $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; - } - } - if ($attr['property'] == 'generator' && in_array($attr['content'], array("hubzilla", "BlaBlaNet"))) { - $server = array(); - $server["platform"] = $attr['content']; - $server["version"] = ""; - $server["network"] = NETWORK_DIASPORA; - } - } - } - - if (!$server) { - return false; - } - - $server["site_name"] = $xpath->evaluate($element."//head/title/text()", $context)->item(0)->nodeValue; - return $server; -} - -function poco_check_server($server_url, $network = "", $force = false) { - - // Unify the server address - $server_url = trim($server_url, "/"); - $server_url = str_replace("/index.php", "", $server_url); - - if ($server_url == "") { - return false; - } - - $servers = q("SELECT * FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); - if (DBM::is_result($servers)) { - - if ($servers[0]["created"] <= NULL_DATE) { - q("UPDATE `gserver` SET `created` = '%s' WHERE `nurl` = '%s'", - dbesc(datetime_convert()), dbesc(normalise_link($server_url))); - } - $poco = $servers[0]["poco"]; - $noscrape = $servers[0]["noscrape"]; - - if ($network == "") { - $network = $servers[0]["network"]; - } - - $last_contact = $servers[0]["last_contact"]; - $last_failure = $servers[0]["last_failure"]; - $version = $servers[0]["version"]; - $platform = $servers[0]["platform"]; - $site_name = $servers[0]["site_name"]; - $info = $servers[0]["info"]; - $register_policy = $servers[0]["register_policy"]; - - if (!$force && !poco_do_update($servers[0]["created"], "", $last_failure, $last_contact)) { - logger("Use cached data for server ".$server_url, LOGGER_DEBUG); - return ($last_contact >= $last_failure); - } - } else { - $poco = ""; - $noscrape = ""; - $version = ""; - $platform = ""; - $site_name = ""; - $info = ""; - $register_policy = -1; - - $last_contact = NULL_DATE; - $last_failure = NULL_DATE; - } - logger("Server ".$server_url." is outdated or unknown. Start discovery. Force: ".$force." Created: ".$servers[0]["created"]." Failure: ".$last_failure." Contact: ".$last_contact, LOGGER_DEBUG); - - $failure = false; - $possible_failure = false; - $orig_last_failure = $last_failure; - $orig_last_contact = $last_contact; - - // Check if the page is accessible via SSL. - $orig_server_url = $server_url; - $server_url = str_replace("http://", "https://", $server_url); - - // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital - $serverret = z_fetch_url($server_url."/.well-known/host-meta", false, $redirects, array('timeout' => 20)); - - // Quit if there is a timeout. - // But we want to make sure to only quit if we are mostly sure that this server url fits. - if (DBM::is_result($servers) && ($orig_server_url == $server_url) && - ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) { - logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); - dba::update('gserver', array('last_failure' => datetime_convert()), array('nurl' => normalise_link($server_url))); - return false; - } - - // Maybe the page is unencrypted only? - $xmlobj = @simplexml_load_string($serverret["body"],'SimpleXMLElement',0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); - if (!$serverret["success"] || ($serverret["body"] == "") || (@sizeof($xmlobj) == 0) || !is_object($xmlobj)) { - $server_url = str_replace("https://", "http://", $server_url); - - // We set the timeout to 20 seconds since this operation should be done in no time if the server was vital - $serverret = z_fetch_url($server_url."/.well-known/host-meta", false, $redirects, array('timeout' => 20)); - - // Quit if there is a timeout - if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) { - logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); - dba::update('gserver', array('last_failure' => datetime_convert()), array('nurl' => normalise_link($server_url))); - return false; - } - - $xmlobj = @simplexml_load_string($serverret["body"],'SimpleXMLElement',0, "http://docs.oasis-open.org/ns/xri/xrd-1.0"); - } - - if (!$serverret["success"] || ($serverret["body"] == "") || (sizeof($xmlobj) == 0) || !is_object($xmlobj)) { - // Workaround for bad configured servers (known nginx problem) - if (!in_array($serverret["debug"]["http_code"], array("403", "404"))) { - $failure = true; - } - $possible_failure = true; - } - - // If the server has no possible failure we reset the cached data - if (!$possible_failure) { - $version = ""; - $platform = ""; - $site_name = ""; - $info = ""; - $register_policy = -1; - } - - // Look for poco - if (!$failure) { - $serverret = z_fetch_url($server_url."/poco"); - if ($serverret["success"]) { - $data = json_decode($serverret["body"]); - if (isset($data->totalResults)) { - $poco = $server_url."/poco"; - $server = poco_detect_poco_data($data); - if ($server) { - $platform = $server['platform']; - $network = $server['network']; - $version = ''; - $site_name = ''; - } - } - } - } - - if (!$failure) { - // Test for Diaspora, Hubzilla, Mastodon or older Friendica servers - $serverret = z_fetch_url($server_url); - - if (!$serverret["success"] || ($serverret["body"] == "")) { - $failure = true; - } else { - $server = poco_detect_server_type($serverret["body"]); - if ($server) { - $platform = $server['platform']; - $network = $server['network']; - $version = $server['version']; - $site_name = $server['site_name']; - } - - $lines = explode("\n",$serverret["header"]); - if (count($lines)) { - foreach($lines as $line) { - $line = trim($line); - if (stristr($line,'X-Diaspora-Version:')) { - $platform = "Diaspora"; - $version = trim(str_replace("X-Diaspora-Version:", "", $line)); - $version = trim(str_replace("x-diaspora-version:", "", $version)); - $network = NETWORK_DIASPORA; - $versionparts = explode("-", $version); - $version = $versionparts[0]; - } - - if (stristr($line,'Server: Mastodon')) { - $platform = "Mastodon"; - $network = NETWORK_OSTATUS; - } - } - } - } - } - - if (!$failure && ($poco == "")) { - // Test for Statusnet - // Will also return data for Friendica and GNU Social - but it will be overwritten later - // The "not implemented" is a special treatment for really, really old Friendica versions - $serverret = z_fetch_url($server_url."/api/statusnet/version.json"); - if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && - ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { - $platform = "StatusNet"; - // Remove junk that some GNU Social servers return - $version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]); - $version = trim($version, '"'); - $network = NETWORK_OSTATUS; - } - - // Test for GNU Social - $serverret = z_fetch_url($server_url."/api/gnusocial/version.json"); - if ($serverret["success"] && ($serverret["body"] != '{"error":"not implemented"}') && - ($serverret["body"] != '') && (strlen($serverret["body"]) < 30)) { - $platform = "GNU Social"; - // Remove junk that some GNU Social servers return - $version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]); - $version = trim($version, '"'); - $network = NETWORK_OSTATUS; - } - - // Test for Mastodon - $orig_version = $version; - $serverret = z_fetch_url($server_url."/api/v1/instance"); - if ($serverret["success"] && ($serverret["body"] != '')) { - $data = json_decode($serverret["body"]); - if (isset($data->version)) { - $platform = "Mastodon"; - $version = $data->version; - $site_name = $data->title; - $info = $data->description; - $network = NETWORK_OSTATUS; - } - } - if (strstr($orig_version.$version, 'Pleroma')) { - $platform = 'Pleroma'; - $version = trim(str_replace('Pleroma', '', $version)); - } - } - - if (!$failure) { - // Test for Hubzilla and Red - $serverret = z_fetch_url($server_url."/siteinfo.json"); - if ($serverret["success"]) { - $data = json_decode($serverret["body"]); - if (isset($data->url)) { - $platform = $data->platform; - $version = $data->version; - $network = NETWORK_DIASPORA; - } - if (!empty($data->site_name)) { - $site_name = $data->site_name; - } - switch ($data->register_policy) { - case "REGISTER_OPEN": - $register_policy = REGISTER_OPEN; - break; - case "REGISTER_APPROVE": - $register_policy = REGISTER_APPROVE; - break; - case "REGISTER_CLOSED": - default: - $register_policy = REGISTER_CLOSED; - break; - } - } else { - // Test for Hubzilla, Redmatrix or Friendica - $serverret = z_fetch_url($server_url."/api/statusnet/config.json"); - if ($serverret["success"]) { - $data = json_decode($serverret["body"]); - if (isset($data->site->server)) { - if (isset($data->site->platform)) { - $platform = $data->site->platform->PLATFORM_NAME; - $version = $data->site->platform->STD_VERSION; - $network = NETWORK_DIASPORA; - } - if (isset($data->site->BlaBlaNet)) { - $platform = $data->site->BlaBlaNet->PLATFORM_NAME; - $version = $data->site->BlaBlaNet->STD_VERSION; - $network = NETWORK_DIASPORA; - } - if (isset($data->site->hubzilla)) { - $platform = $data->site->hubzilla->PLATFORM_NAME; - $version = $data->site->hubzilla->RED_VERSION; - $network = NETWORK_DIASPORA; - } - if (isset($data->site->redmatrix)) { - if (isset($data->site->redmatrix->PLATFORM_NAME)) { - $platform = $data->site->redmatrix->PLATFORM_NAME; - } elseif (isset($data->site->redmatrix->RED_PLATFORM)) { - $platform = $data->site->redmatrix->RED_PLATFORM; - } - - $version = $data->site->redmatrix->RED_VERSION; - $network = NETWORK_DIASPORA; - } - if (isset($data->site->friendica)) { - $platform = $data->site->friendica->FRIENDICA_PLATFORM; - $version = $data->site->friendica->FRIENDICA_VERSION; - $network = NETWORK_DFRN; - } - - $site_name = $data->site->name; - - $data->site->closed = poco_to_boolean($data->site->closed); - $data->site->private = poco_to_boolean($data->site->private); - $data->site->inviteonly = poco_to_boolean($data->site->inviteonly); - - if (!$data->site->closed && !$data->site->private and $data->site->inviteonly) { - $register_policy = REGISTER_APPROVE; - } elseif (!$data->site->closed && !$data->site->private) { - $register_policy = REGISTER_OPEN; - } else { - $register_policy = REGISTER_CLOSED; - } - } - } - } - } - - // Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix - if (!$failure) { - $serverret = z_fetch_url($server_url."/statistics.json"); - if ($serverret["success"]) { - $data = json_decode($serverret["body"]); - if (isset($data->version)) { - $version = $data->version; - // Version numbers on statistics.json are presented with additional info, e.g.: - // 0.6.3.0-p1702cc1c, 0.6.99.0-p1b9ab160 or 3.4.3-2-1191. - $version = preg_replace("=(.+)-(.{4,})=ism", "$1", $version); - } - - if (!empty($data->name)) { - $site_name = $data->name; - } - - if (!empty($data->network)) { - $platform = $data->network; - } - - if ($platform == "Diaspora") { - $network = NETWORK_DIASPORA; - } - - if ($data->registrations_open) { - $register_policy = REGISTER_OPEN; - } else { - $register_policy = REGISTER_CLOSED; - } - } - } - - // Query nodeinfo. Working for (at least) Diaspora and Friendica. - if (!$failure) { - $server = poco_fetch_nodeinfo($server_url); - if ($server) { - $register_policy = $server['register_policy']; - - if (isset($server['platform'])) { - $platform = $server['platform']; - } - - if (isset($server['network'])) { - $network = $server['network']; - } - - if (isset($server['version'])) { - $version = $server['version']; - } - - if (isset($server['site_name'])) { - $site_name = $server['site_name']; - } - } - } - - // Check for noscrape - // Friendica servers could be detected as OStatus servers - if (!$failure && in_array($network, array(NETWORK_DFRN, NETWORK_OSTATUS))) { - $serverret = z_fetch_url($server_url."/friendica/json"); - - if (!$serverret["success"]) { - $serverret = z_fetch_url($server_url."/friendika/json"); - } - - if ($serverret["success"]) { - $data = json_decode($serverret["body"]); - - if (isset($data->version)) { - $network = NETWORK_DFRN; - - $noscrape = $data->no_scrape_url; - $version = $data->version; - $site_name = $data->site_name; - $info = $data->info; - $register_policy_str = $data->register_policy; - $platform = $data->platform; - - switch ($register_policy_str) { - case "REGISTER_CLOSED": - $register_policy = REGISTER_CLOSED; - break; - case "REGISTER_APPROVE": - $register_policy = REGISTER_APPROVE; - break; - case "REGISTER_OPEN": - $register_policy = REGISTER_OPEN; - break; - } - } - } - } - - if ($possible_failure && !$failure) { - $failure = true; - } - - if ($failure) { - $last_contact = $orig_last_contact; - $last_failure = datetime_convert(); - } else { - $last_contact = datetime_convert(); - $last_failure = $orig_last_failure; - } - - if (($last_contact <= $last_failure) && !$failure) { - logger("Server ".$server_url." seems to be alive, but last contact wasn't set - could be a bug", LOGGER_DEBUG); - } elseif (($last_contact >= $last_failure) && $failure) { - logger("Server ".$server_url." seems to be dead, but last failure wasn't set - could be a bug", LOGGER_DEBUG); - } - - // Check again if the server exists - $servers = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); - - $version = strip_tags($version); - $site_name = strip_tags($site_name); - $info = strip_tags($info); - $platform = strip_tags($platform); - - if ($servers) { - q("UPDATE `gserver` SET `url` = '%s', `version` = '%s', `site_name` = '%s', `info` = '%s', `register_policy` = %d, `poco` = '%s', `noscrape` = '%s', - `network` = '%s', `platform` = '%s', `last_contact` = '%s', `last_failure` = '%s' WHERE `nurl` = '%s'", - dbesc($server_url), - dbesc($version), - dbesc($site_name), - dbesc($info), - intval($register_policy), - dbesc($poco), - dbesc($noscrape), - dbesc($network), - dbesc($platform), - dbesc($last_contact), - dbesc($last_failure), - dbesc(normalise_link($server_url)) - ); - } elseif (!$failure) { - q("INSERT INTO `gserver` (`url`, `nurl`, `version`, `site_name`, `info`, `register_policy`, `poco`, `noscrape`, `network`, `platform`, `created`, `last_contact`, `last_failure`) - VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s')", - dbesc($server_url), - dbesc(normalise_link($server_url)), - dbesc($version), - dbesc($site_name), - dbesc($info), - intval($register_policy), - dbesc($poco), - dbesc($noscrape), - dbesc($network), - dbesc($platform), - dbesc(datetime_convert()), - dbesc($last_contact), - dbesc($last_failure), - dbesc(datetime_convert()) - ); - } - logger("End discovery for server " . $server_url, LOGGER_DEBUG); - - return !$failure; -} - -function count_common_friends($uid, $cid) { - - $r = q("SELECT count(*) as `total` - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) - AND `gcontact`.`nurl` IN (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) ", - intval($cid), - intval($uid), - intval($uid), - intval($cid) - ); - - // logger("count_common_friends: $uid $cid {$r[0]['total']}"); - if (DBM::is_result($r)) { - return $r[0]['total']; - } - return 0; - -} - - -function common_friends($uid, $cid, $start = 0, $limit = 9999, $shuffle = false) { - - if ($shuffle) { - $sql_extra = " order by rand() "; - } else { - $sql_extra = " order by `gcontact`.`name` asc "; - } - - $r = q("SELECT `gcontact`.*, `contact`.`id` AS `cid` - FROM `glink` - INNER JOIN `gcontact` ON `glink`.`gcid` = `gcontact`.`id` - INNER JOIN `contact` ON `gcontact`.`nurl` = `contact`.`nurl` - WHERE `glink`.`cid` = %d and `glink`.`uid` = %d - AND `contact`.`uid` = %d AND `contact`.`self` = 0 AND `contact`.`blocked` = 0 - AND `contact`.`hidden` = 0 AND `contact`.`id` != %d - AND ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) - $sql_extra LIMIT %d, %d", - intval($cid), - intval($uid), - intval($uid), - intval($cid), - intval($start), - intval($limit) - ); - - /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() - return $r; - -} - - -function count_common_friends_zcid($uid, $zcid) { - - $r = q("SELECT count(*) as `total` - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - where `glink`.`zcid` = %d - and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) ", - intval($zcid), - intval($uid) - ); - - if (DBM::is_result($r)) { - return $r[0]['total']; - } - return 0; - -} - -function common_friends_zcid($uid, $zcid, $start = 0, $limit = 9999, $shuffle = false) { - - if ($shuffle) { - $sql_extra = " order by rand() "; - } else { - $sql_extra = " order by `gcontact`.`name` asc "; - } - - $r = q("SELECT `gcontact`.* - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - where `glink`.`zcid` = %d - and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 ) - $sql_extra limit %d, %d", - intval($zcid), - intval($uid), - intval($start), - intval($limit) - ); - - /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() - return $r; - -} - - -function count_all_friends($uid, $cid) { - - $r = q("SELECT count(*) as `total` - FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - where `glink`.`cid` = %d and `glink`.`uid` = %d AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))", - intval($cid), - intval($uid) - ); - - if (DBM::is_result($r)) { - return $r[0]['total']; - } - return 0; - -} - - -function all_friends($uid, $cid, $start = 0, $limit = 80) { - - $r = q("SELECT `gcontact`.*, `contact`.`id` AS `cid` - FROM `glink` - INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id` - LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl` AND `contact`.`uid` = %d - WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND - ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) - ORDER BY `gcontact`.`name` ASC LIMIT %d, %d ", - intval($uid), - intval($cid), - intval($uid), - intval($start), - intval($limit) - ); - - /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() - return $r; -} - - - -function suggestion_query($uid, $start = 0, $limit = 80) { - - if (!$uid) { - return array(); - } - - /* - * Uncommented because the result of the queries are to big to store it in the cache. - * We need to decide if we want to change the db column type or if we want to delete it. - */ - //$list = Cache::get("suggestion_query:".$uid.":".$start.":".$limit); - //if (!is_null($list)) { - // return $list; - //} - - $network = array(NETWORK_DFRN); - - if (Config::get('system','diaspora_enabled')) { - $network[] = NETWORK_DIASPORA; - } - - if (!Config::get('system','ostatus_disabled')) { - $network[] = NETWORK_OSTATUS; - } - - $sql_network = implode("', '", $network); - $sql_network = "'".$sql_network."'"; - - /// @todo This query is really slow - // By now we cache the data for five minutes - $r = q("SELECT count(glink.gcid) as `total`, gcontact.* from gcontact - INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id` - where uid = %d and not gcontact.nurl in ( select nurl from contact where uid = %d ) - AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d) - AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d) - AND `gcontact`.`updated` >= '%s' - AND `gcontact`.`last_contact` >= `gcontact`.`last_failure` - AND `gcontact`.`network` IN (%s) - GROUP BY `glink`.`gcid` ORDER BY `gcontact`.`updated` DESC,`total` DESC LIMIT %d, %d", - intval($uid), - intval($uid), - intval($uid), - intval($uid), - dbesc(NULL_DATE), - $sql_network, - intval($start), - intval($limit) - ); - - if (DBM::is_result($r) && count($r) >= ($limit -1)) { - /* - * Uncommented because the result of the queries are to big to store it in the cache. - * We need to decide if we want to change the db column type or if we want to delete it. - */ - //Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $r, CACHE_FIVE_MINUTES); - - return $r; - } - - $r2 = q("SELECT gcontact.* FROM gcontact - INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id` - WHERE `glink`.`uid` = 0 AND `glink`.`cid` = 0 AND `glink`.`zcid` = 0 AND NOT `gcontact`.`nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = %d) - AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d) - AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d) - AND `gcontact`.`updated` >= '%s' - AND `gcontact`.`last_contact` >= `gcontact`.`last_failure` - AND `gcontact`.`network` IN (%s) - ORDER BY rand() LIMIT %d, %d", - intval($uid), - intval($uid), - intval($uid), - dbesc(NULL_DATE), - $sql_network, - intval($start), - intval($limit) - ); - - $list = array(); - foreach ($r2 as $suggestion) { - $list[$suggestion["nurl"]] = $suggestion; - } - - foreach ($r as $suggestion) { - $list[$suggestion["nurl"]] = $suggestion; - } - - while (sizeof($list) > ($limit)) { - array_pop($list); - } - - /* - * Uncommented because the result of the queries are to big to store it in the cache. - * We need to decide if we want to change the db column type or if we want to delete it. - */ - //Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $list, CACHE_FIVE_MINUTES); - return $list; -} - -function update_suggestions() { - - $a = get_app(); - - $done = array(); - - /// @TODO Check if it is really neccessary to poll the own server - poco_load(0, 0, 0, System::baseUrl() . '/poco'); - - $done[] = System::baseUrl() . '/poco'; - - if (strlen(Config::get('system','directory'))) { - $x = fetch_url(get_server()."/pubsites"); - if ($x) { - $j = json_decode($x); - if ($j->entries) { - foreach ($j->entries as $entry) { - - poco_check_server($entry->url); - - $url = $entry->url . '/poco'; - if (! in_array($url,$done)) { - poco_load(0,0,0,$entry->url . '/poco'); - } - } - } - } - } - - // Query your contacts from Friendica and Redmatrix/Hubzilla for their contacts - $r = q("SELECT DISTINCT(`poco`) AS `poco` FROM `contact` WHERE `network` IN ('%s', '%s')", - dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA) - ); - - if (DBM::is_result($r)) { - foreach ($r as $rr) { - $base = substr($rr['poco'],0,strrpos($rr['poco'],'/')); - if (! in_array($base,$done)) { - poco_load(0,0,0,$base); - } - } - } -} - -/** - * @brief Fetch server list from remote servers and adds them when they are new. - * - * @param string $poco URL to the POCO endpoint - */ -function poco_fetch_serverlist($poco) { - $serverret = z_fetch_url($poco."/@server"); - if (!$serverret["success"]) { - return; - } - $serverlist = json_decode($serverret['body']); - - if (!is_array($serverlist)) { - return; - } - - foreach ($serverlist as $server) { - $server_url = str_replace("/index.php", "", $server->url); - - $r = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); - if (!DBM::is_result($r)) { - logger("Call server check for server ".$server_url, LOGGER_DEBUG); - Worker::add(PRIORITY_LOW, "discover_poco", "server", $server_url); - } - } -} - -function poco_discover_federation() { - $last = Config::get('poco','last_federation_discovery'); - - if ($last) { - $next = $last + (24 * 60 * 60); - if ($next > time()) { - return; - } - } - - // Discover Friendica, Hubzilla and Diaspora servers - $serverdata = fetch_url("http://the-federation.info/pods.json"); - - if ($serverdata) { - $servers = json_decode($serverdata); - - foreach ($servers->pods as $server) { - Worker::add(PRIORITY_LOW, "discover_poco", "server", "https://".$server->host); - } - } - - // Disvover Mastodon servers - if (!Config::get('system','ostatus_disabled')) { - $serverdata = fetch_url("https://instances.mastodon.xyz/instances.json"); - - if ($serverdata) { - $servers = json_decode($serverdata); - - foreach ($servers as $server) { - $url = (is_null($server->https_score) ? 'http' : 'https').'://'.$server->name; - Worker::add(PRIORITY_LOW, "discover_poco", "server", $url); - } - } - } - - // Currently disabled, since the service isn't available anymore. - // It is not removed since I hope that there will be a successor. - // Discover GNU Social Servers. - //if (!Config::get('system','ostatus_disabled')) { - // $serverdata = "http://gstools.org/api/get_open_instances/"; - - // $result = z_fetch_url($serverdata); - // if ($result["success"]) { - // $servers = json_decode($result["body"]); - - // foreach($servers->data as $server) - // poco_check_server($server->instance_address); - // } - //} - - Config::set('poco','last_federation_discovery', time()); -} - -function poco_discover_single_server($id) { - $r = q("SELECT `poco`, `nurl`, `url`, `network` FROM `gserver` WHERE `id` = %d", intval($id)); - if (!DBM::is_result($r)) { - return false; - } - - $server = $r[0]; - - // Discover new servers out there (Works from Friendica version 3.5.2) - poco_fetch_serverlist($server["poco"]); - - // Fetch all users from the other server - $url = $server["poco"]."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; - - logger("Fetch all users from the server ".$server["url"], LOGGER_DEBUG); - - $retdata = z_fetch_url($url); - if ($retdata["success"]) { - $data = json_decode($retdata["body"]); - - poco_discover_server($data, 2); - - if (Config::get('system','poco_discovery') > 1) { - - $timeframe = Config::get('system','poco_discovery_since'); - if ($timeframe == 0) { - $timeframe = 30; - } - - $updatedSince = date("Y-m-d H:i:s", time() - $timeframe * 86400); - - // Fetch all global contacts from the other server (Not working with Redmatrix and Friendica versions before 3.3) - $url = $server["poco"]."/@global?updatedSince=".$updatedSince."&fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; - - $success = false; - - $retdata = z_fetch_url($url); - if ($retdata["success"]) { - logger("Fetch all global contacts from the server ".$server["nurl"], LOGGER_DEBUG); - $success = poco_discover_server(json_decode($retdata["body"])); - } - - if (!$success && (Config::get('system','poco_discovery') > 2)) { - logger("Fetch contacts from users of the server ".$server["nurl"], LOGGER_DEBUG); - poco_discover_server_users($data, $server); - } - } - - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); - - return true; - } else { - // If the server hadn't replied correctly, then force a sanity check - poco_check_server($server["url"], $server["network"], true); - - // If we couldn't reach the server, we will try it some time later - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); - - return false; - } -} - -function poco_discover($complete = false) { - - // Update the server list - poco_discover_federation(); - - $no_of_queries = 5; - - $requery_days = intval(Config::get("system", "poco_requery_days")); - - if ($requery_days == 0) { - $requery_days = 7; - } - $last_update = date("c", time() - (60 * 60 * 24 * $requery_days)); - - $r = q("SELECT `id`, `url`, `network` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `poco` != '' AND `last_poco_query` < '%s' ORDER BY RAND()", dbesc($last_update)); - if (DBM::is_result($r)) { - foreach ($r as $server) { - - if (!poco_check_server($server["url"], $server["network"])) { - // The server is not reachable? Okay, then we will try it later - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); - continue; - } - - logger('Update directory from server '.$server['url'].' with ID '.$server['id'], LOGGER_DEBUG); - Worker::add(PRIORITY_LOW, "discover_poco", "update_server_directory", (int)$server['id']); - - if (!$complete && (--$no_of_queries == 0)) { - break; - } - } - } -} - -function poco_discover_server_users($data, $server) { - - if (!isset($data->entry)) { - return; - } - - foreach ($data->entry as $entry) { - $username = ""; - if (isset($entry->urls)) { - foreach ($entry->urls as $url) { - if ($url->type == 'profile') { - $profile_url = $url->value; - $urlparts = parse_url($profile_url); - $username = end(explode("/", $urlparts["path"])); - } - } - } - if ($username != "") { - logger("Fetch contacts for the user ".$username." from the server ".$server["nurl"], LOGGER_DEBUG); - - // Fetch all contacts from a given user from the other server - $url = $server["poco"]."/".$username."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,contactType,generation"; - - $retdata = z_fetch_url($url); - if ($retdata["success"]) { - poco_discover_server(json_decode($retdata["body"]), 3); - } - } - } -} - -function poco_discover_server($data, $default_generation = 0) { - - if (!isset($data->entry) || !count($data->entry)) { - return false; - } - - $success = false; - - foreach ($data->entry as $entry) { - $profile_url = ''; - $profile_photo = ''; - $connect_url = ''; - $name = ''; - $network = ''; - $updated = NULL_DATE; - $location = ''; - $about = ''; - $keywords = ''; - $gender = ''; - $contact_type = -1; - $generation = $default_generation; - - $name = $entry->displayName; - - if (isset($entry->urls)) { - foreach ($entry->urls as $url) { - if ($url->type == 'profile') { - $profile_url = $url->value; - continue; - } - if ($url->type == 'webfinger') { - $connect_url = str_replace('acct:' , '', $url->value); - continue; - } - } - } - - if (isset($entry->photos)) { - foreach ($entry->photos as $photo) { - if ($photo->type == 'profile') { - $profile_photo = $photo->value; - continue; - } - } - } - - if (isset($entry->updated)) { - $updated = date("Y-m-d H:i:s", strtotime($entry->updated)); - } - - if (isset($entry->network)) { - $network = $entry->network; - } - - if (isset($entry->currentLocation)) { - $location = $entry->currentLocation; - } - - if (isset($entry->aboutMe)) { - $about = html2bbcode($entry->aboutMe); - } - - if (isset($entry->gender)) { - $gender = $entry->gender; - } - - if(isset($entry->generation) && ($entry->generation > 0)) { - $generation = ++$entry->generation; - } - - if(isset($entry->contactType) && ($entry->contactType >= 0)) { - $contact_type = $entry->contactType; - } - - if (isset($entry->tags)) { - foreach ($entry->tags as $tag) { - $keywords = implode(", ", $tag); - } - } - - if ($generation > 0) { - $success = true; - - logger("Store profile ".$profile_url, LOGGER_DEBUG); - - $gcontact = array("url" => $profile_url, - "name" => $name, - "network" => $network, - "photo" => $profile_photo, - "about" => $about, - "location" => $location, - "gender" => $gender, - "keywords" => $keywords, - "connect" => $connect_url, - "updated" => $updated, - "contact-type" => $contact_type, - "generation" => $generation); - - try { - $gcontact = sanitize_gcontact($gcontact); - update_gcontact($gcontact); - } catch (Exception $e) { - logger($e->getMessage(), LOGGER_DEBUG); - } - - logger("Done for profile ".$profile_url, LOGGER_DEBUG); - } - } - return $success; -} - -/** - * @brief Removes unwanted parts from a contact url - * - * @param string $url Contact url - * @return string Contact url with the wanted parts - */ -function clean_contact_url($url) { - $parts = parse_url($url); - - if (!isset($parts["scheme"]) || !isset($parts["host"])) { - return $url; - } - - $new_url = $parts["scheme"]."://".$parts["host"]; - - if (isset($parts["port"])) { - $new_url .= ":".$parts["port"]; - } - - if (isset($parts["path"])) { - $new_url .= $parts["path"]; - } - - if ($new_url != $url) { - logger("Cleaned contact url ".$url." to ".$new_url." - Called by: ".System::callstack(), LOGGER_DEBUG); - } - - return $new_url; -} - -/** - * @brief Replace alternate OStatus user format with the primary one - * - * @param arr $contact contact array (called by reference) - */ -function fix_alternate_contact_address(&$contact) { - if (($contact["network"] == NETWORK_OSTATUS) && poco_alternate_ostatus_url($contact["url"])) { - $data = Probe::uri($contact["url"]); - if ($contact["network"] == NETWORK_OSTATUS) { - logger("Fix primary url from ".$contact["url"]." to ".$data["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); - $contact["url"] = $data["url"]; - $contact["addr"] = $data["addr"]; - $contact["alias"] = $data["alias"]; - $contact["server_url"] = $data["baseurl"]; - } - } -} - -/** - * @brief Fetch the gcontact id, add an entry if not existed - * - * @param arr $contact contact array - * @return bool|int Returns false if not found, integer if contact was found - */ -function get_gcontact_id($contact) { - - $gcontact_id = 0; - $doprobing = false; - - if (in_array($contact["network"], array(NETWORK_PHANTOM))) { - logger("Invalid network for contact url ".$contact["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); - return false; - } - - if ($contact["network"] == NETWORK_STATUSNET) { - $contact["network"] = NETWORK_OSTATUS; - } - - // All new contacts are hidden by default - if (!isset($contact["hide"])) { - $contact["hide"] = true; - } - - // Replace alternate OStatus user format with the primary one - fix_alternate_contact_address($contact); - - // Remove unwanted parts from the contact url (e.g. "?zrl=...") - if (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { - $contact["url"] = clean_contact_url($contact["url"]); - } - - dba::lock('gcontact'); - $r = q("SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", - dbesc(normalise_link($contact["url"]))); - - if (DBM::is_result($r)) { - $gcontact_id = $r[0]["id"]; - - // Update every 90 days - if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) { - $last_failure_str = $r[0]["last_failure"]; - $last_failure = strtotime($r[0]["last_failure"]); - $last_contact_str = $r[0]["last_contact"]; - $last_contact = strtotime($r[0]["last_contact"]); - $doprobing = (((time() - $last_contact) > (90 * 86400)) && ((time() - $last_failure) > (90 * 86400))); - } - } else { - q("INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `hide`, `generation`) - VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)", - dbesc($contact["name"]), - dbesc($contact["nick"]), - dbesc($contact["addr"]), - dbesc($contact["network"]), - dbesc($contact["url"]), - dbesc(normalise_link($contact["url"])), - dbesc($contact["photo"]), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - dbesc($contact["location"]), - dbesc($contact["about"]), - intval($contact["hide"]), - intval($contact["generation"]) - ); - - $r = q("SELECT `id`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2", - dbesc(normalise_link($contact["url"]))); - - if (DBM::is_result($r)) { - $gcontact_id = $r[0]["id"]; - - $doprobing = in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")); - } - } - dba::unlock(); - - if ($doprobing) { - logger("Last Contact: ". $last_contact_str." - Last Failure: ".$last_failure_str." - Checking: ".$contact["url"], LOGGER_DEBUG); - Worker::add(PRIORITY_LOW, 'gprobe', $contact["url"]); - } - - return $gcontact_id; -} - -/** - * @brief Updates the gcontact table from a given array - * - * @param arr $contact contact array - * @return bool|int Returns false if not found, integer if contact was found - */ -function update_gcontact($contact) { - - // Check for invalid "contact-type" value - if (isset($contact['contact-type']) && (intval($contact['contact-type']) < 0)) { - $contact['contact-type'] = 0; - } - - /// @todo update contact table as well - - $gcontact_id = get_gcontact_id($contact); - - if (!$gcontact_id) { - return false; - } - - $r = q("SELECT `name`, `nick`, `photo`, `location`, `about`, `addr`, `generation`, `birthday`, `gender`, `keywords`, - `contact-type`, `hide`, `nsfw`, `network`, `alias`, `notify`, `server_url`, `connect`, `updated`, `url` - FROM `gcontact` WHERE `id` = %d LIMIT 1", - intval($gcontact_id)); - - // Get all field names - $fields = array(); - foreach ($r[0] as $field => $data) { - $fields[$field] = $data; - } - - unset($fields["url"]); - unset($fields["updated"]); - unset($fields["hide"]); - - // Bugfix: We had an error in the storing of keywords which lead to the "0" - // This value is still transmitted via poco. - if ($contact["keywords"] == "0") { - unset($contact["keywords"]); - } - - if ($r[0]["keywords"] == "0") { - $r[0]["keywords"] = ""; - } - - // assign all unassigned fields from the database entry - foreach ($fields as $field => $data) { - if (!isset($contact[$field]) || ($contact[$field] == "")) { - $contact[$field] = $r[0][$field]; - } - } - - if (!isset($contact["hide"])) { - $contact["hide"] = $r[0]["hide"]; - } - - $fields["hide"] = $r[0]["hide"]; - - if ($contact["network"] == NETWORK_STATUSNET) { - $contact["network"] = NETWORK_OSTATUS; - } - - // Replace alternate OStatus user format with the primary one - fix_alternate_contact_address($contact); - - if (!isset($contact["updated"])) { - $contact["updated"] = DBM::date(); - } - - if ($contact["network"] == NETWORK_TWITTER) { - $contact["server_url"] = 'http://twitter.com'; - } - - if ($contact["server_url"] == "") { - $data = Probe::uri($contact["url"]); - if ($data["network"] != NETWORK_PHANTOM) { - $contact["server_url"] = $data['baseurl']; - } - } else { - $contact["server_url"] = normalise_link($contact["server_url"]); - } - - if (($contact["addr"] == "") && ($contact["server_url"] != "") && ($contact["nick"] != "")) { - $hostname = str_replace("http://", "", $contact["server_url"]); - $contact["addr"] = $contact["nick"]."@".$hostname; - } - - // Check if any field changed - $update = false; - unset($fields["generation"]); - - if ((($contact["generation"] > 0) && ($contact["generation"] <= $r[0]["generation"])) || ($r[0]["generation"] == 0)) { - foreach ($fields as $field => $data) { - if ($contact[$field] != $r[0][$field]) { - logger("Difference for contact ".$contact["url"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG); - $update = true; - } - } - - if ($contact["generation"] < $r[0]["generation"]) { - logger("Difference for contact ".$contact["url"]." in field 'generation'. new value: '".$contact["generation"]."', old value '".$r[0]["generation"]."'", LOGGER_DEBUG); - $update = true; - } - } - - if ($update) { - logger("Update gcontact for ".$contact["url"], LOGGER_DEBUG); - $condition = array('`nurl` = ? AND (`generation` = 0 OR `generation` >= ?)', - normalise_link($contact["url"]), $contact["generation"]); - $contact["updated"] = DBM::date($contact["updated"]); - - $updated = array('photo' => $contact['photo'], 'name' => $contact['name'], - 'nick' => $contact['nick'], 'addr' => $contact['addr'], - 'network' => $contact['network'], 'birthday' => $contact['birthday'], - 'gender' => $contact['gender'], 'keywords' => $contact['keywords'], - 'hide' => $contact['hide'], 'nsfw' => $contact['nsfw'], - 'contact-type' => $contact['contact-type'], 'alias' => $contact['alias'], - 'notify' => $contact['notify'], 'url' => $contact['url'], - 'location' => $contact['location'], 'about' => $contact['about'], - 'generation' => $contact['generation'], 'updated' => $contact['updated'], - 'server_url' => $contact['server_url'], 'connect' => $contact['connect']); - - dba::update('gcontact', $updated, $condition, $fields); - - // Now update the contact entry with the user id "0" as well. - // This is used for the shadow copies of public items. - $r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0 ORDER BY `id` LIMIT 1", - dbesc(normalise_link($contact["url"]))); - - if (DBM::is_result($r)) { - logger("Update public contact ".$r[0]["id"], LOGGER_DEBUG); - - update_contact_avatar($contact["photo"], 0, $r[0]["id"]); - - $fields = array('name', 'nick', 'addr', - 'network', 'bd', 'gender', - 'keywords', 'alias', 'contact-type', - 'url', 'location', 'about'); - $old_contact = dba::select('contact', $fields, array('id' => $r[0]["id"]), array('limit' => 1)); - - // Update it with the current values - $fields = array('name' => $contact['name'], 'nick' => $contact['nick'], - 'addr' => $contact['addr'], 'network' => $contact['network'], - 'bd' => $contact['birthday'], 'gender' => $contact['gender'], - 'keywords' => $contact['keywords'], 'alias' => $contact['alias'], - 'contact-type' => $contact['contact-type'], 'url' => $contact['url'], - 'location' => $contact['location'], 'about' => $contact['about']); - - dba::update('contact', $fields, array('id' => $r[0]["id"]), $old_contact); - } - } - - return $gcontact_id; -} - -/** - * @brief Updates the gcontact entry from probe - * - * @param str $url profile link - */ -function update_gcontact_from_probe($url) { - $data = Probe::uri($url); - - if (in_array($data["network"], array(NETWORK_PHANTOM))) { - logger("Invalid network for contact url ".$data["url"]." - Called by: ".System::callstack(), LOGGER_DEBUG); - return; - } - - $data["server_url"] = $data["baseurl"]; - - update_gcontact($data); -} - -/** - * @brief Update the gcontact entry for a given user id - * - * @param int $uid User ID - */ -function update_gcontact_for_user($uid) { - $r = q("SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`, - `profile`.`name`, `profile`.`about`, `profile`.`gender`, - `profile`.`pub_keywords`, `profile`.`dob`, `profile`.`photo`, - `profile`.`net-publish`, `user`.`nickname`, `user`.`hidewall`, - `contact`.`notify`, `contact`.`url`, `contact`.`addr` - FROM `profile` - INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` - INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` - WHERE `profile`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self`", - intval($uid)); - - $location = formatted_location(array("locality" => $r[0]["locality"], "region" => $r[0]["region"], - "country-name" => $r[0]["country-name"])); - - // The "addr" field was added in 3.4.3 so it can be empty for older users - if ($r[0]["addr"] != "") { - $addr = $r[0]["nickname"].'@'.str_replace(array("http://", "https://"), "", System::baseUrl()); - } else { - $addr = $r[0]["addr"]; - } - - $gcontact = array("name" => $r[0]["name"], "location" => $location, "about" => $r[0]["about"], - "gender" => $r[0]["gender"], "keywords" => $r[0]["pub_keywords"], - "birthday" => $r[0]["dob"], "photo" => $r[0]["photo"], - "notify" => $r[0]["notify"], "url" => $r[0]["url"], - "hide" => ($r[0]["hidewall"] || !$r[0]["net-publish"]), - "nick" => $r[0]["nickname"], "addr" => $addr, - "connect" => $addr, "server_url" => System::baseUrl(), - "generation" => 1, "network" => NETWORK_DFRN); - - update_gcontact($gcontact); -} - -/** - * @brief Fetches users of given GNU Social server - * - * If the "Statistics" plugin is enabled (See http://gstools.org/ for details) we query user data with this. - * - * @param str $server Server address - */ -function gs_fetch_users($server) { - - logger("Fetching users from GNU Social server ".$server, LOGGER_DEBUG); - - $url = $server."/main/statistics"; - - $result = z_fetch_url($url); - if (!$result["success"]) { - return false; - } - - $statistics = json_decode($result["body"]); - - if (is_object($statistics->config)) { - if ($statistics->config->instance_with_ssl) { - $server = "https://"; - } else { - $server = "http://"; - } - - $server .= $statistics->config->instance_address; - - $hostname = $statistics->config->instance_address; - } else { - /// @TODO is_object() above means here no object, still $statistics is being used as object - if ($statistics->instance_with_ssl) { - $server = "https://"; - } else { - $server = "http://"; - } - - $server .= $statistics->instance_address; - - $hostname = $statistics->instance_address; - } - - if (is_object($statistics->users)) { - foreach ($statistics->users as $nick => $user) { - $profile_url = $server."/".$user->nickname; - - $contact = array("url" => $profile_url, - "name" => $user->fullname, - "addr" => $user->nickname."@".$hostname, - "nick" => $user->nickname, - "about" => $user->bio, - "network" => NETWORK_OSTATUS, - "photo" => System::baseUrl()."/images/person-175.jpg"); - get_gcontact_id($contact); - } - } -} - -/** - * @brief Asking GNU Social server on a regular base for their user data - * - */ -function gs_discover() { - - $requery_days = intval(Config::get("system", "poco_requery_days")); - - $last_update = date("c", time() - (60 * 60 * 24 * $requery_days)); - - $r = q("SELECT `nurl`, `url` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `network` = '%s' AND `last_poco_query` < '%s' ORDER BY RAND() LIMIT 5", - dbesc(NETWORK_OSTATUS), dbesc($last_update)); - - if (!DBM::is_result($r)) { - return; - } - - foreach ($r as $server) { - gs_fetch_users($server["url"]); - q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"])); - } -} - -/** - * @brief Returns a list of all known servers - * @return array List of server urls - */ -function poco_serverlist() { - $r = q("SELECT `url`, `site_name` AS `displayName`, `network`, `platform`, `version` FROM `gserver` - WHERE `network` IN ('%s', '%s', '%s') AND `last_contact` > `last_failure` - ORDER BY `last_contact` - LIMIT 1000", - dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS)); - if (!DBM::is_result($r)) { - return false; - } - - return $r; -} diff --git a/include/spool_post.php b/include/spool_post.php deleted file mode 100644 index b7b8de396..000000000 --- a/include/spool_post.php +++ /dev/null @@ -1,57 +0,0 @@ - $uid), + array("limit" => 1) + ); + $url = System::removedBaseUrl($contact['url']); + + foreach ($r as $rr) { + $tag['level'] = $rr[2]; + $tag['url'] = $url."?tag=".urlencode($rr[0]); + $tag['name'] = $rr[0]; + + $tags[] = $tag; + } + + $tpl = get_markup_template("tagblock_widget.tpl"); + $o = replace_macros($tpl, array( + '$title' => t('Tags'), + '$tags' => $tags + )); + + } + return $o; +} + +/** + * @brief Calculate weighting of tags according to the frequency of use. + * + * @param array $arr Array of tags/terms with tag/term name and total count of use. + * @return array Alphabetical sorted array of used tags/terms of an user. + */ +function tag_calc($arr) { + $tags = array(); + $min = 1e9; + $max = -1e9; + $x = 0; + + if (!$arr) { + return array(); + } + + foreach ($arr as $rr) { + $tags[$x][0] = $rr['term']; + $tags[$x][1] = log($rr['total']); + $tags[$x][2] = 0; + $min = min($min, $tags[$x][1]); + $max = max($max, $tags[$x][1]); + $x ++; + } + + usort($tags, 'tags_sort'); + $range = max(.01, $max - $min) * 1.0001; + + for ($x = 0; $x < count($tags); $x ++) { + $tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range); + } + + return $tags; +} + +/** + * @brief Compare function to sort tags/terms alphabetically. + * + * @param type $a + * @param type $b + * + * @return int + */ +function tags_sort($a, $b) { + if (strtolower($a[0]) == strtolower($b[0])) { + return 0; + } + return ((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1); +} + +/** + * @brief Insert a tag cloud widget for the present profile. + * + * @param int $limit Max number of displayed tags. + * @return string HTML formattat output. + */ +function tagcloud_wall_widget($limit = 50) { + $a = get_app(); + + if(!$a->profile['profile_uid'] || !$a->profile['url']) { + return ""; + } + + if(feature_enabled($a->profile['profile_uid'], 'tagadelic')) { + $owner_id = Contact::getIdForURL($a->profile['url']); + + if(!$owner_id) { + return ""; + } + return wtagblock($a->profile['profile_uid'], $limit, $owner_id, 'wall'); + } + + return ""; +} diff --git a/include/tagupdate.php b/include/tagupdate.php deleted file mode 100644 index 1e97135c5..000000000 --- a/include/tagupdate.php +++ /dev/null @@ -1,6 +0,0 @@ - 5.3, not certain how to code around it for unit tests -// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; - default: - //die("Unknown preg error."); - return; - } - echo " "; - debug_print_backtrace(); - die(); - } - - private function _push_stack() { - $this->stack[] = array($this->r, $this->nodes); - } - - private function _pop_stack() { - list($this->r, $this->nodes) = array_pop($this->stack); - } - - private function _get_var($name, $retNoKey = false) { - $keys = array_map('trim', explode(".", $name)); - if ($retNoKey && !array_key_exists($keys[0], $this->r)) - return KEY_NOT_EXISTS; - $val = $this->r; - foreach ($keys as $k) { - $val = (isset($val[$k]) ? $val[$k] : null); - } - return $val; - } - - /** - * IF node - * - * {{ if <$var> }}...[{{ else }} ...] {{ endif }} - * {{ if <$var>==}}...[{{ else }} ...]{{ endif }} - * {{ if <$var>!= }}...[{{ else }} ...]{{ endif }} - */ - private function _replcb_if ($args) { - if (strpos($args[2], "==") > 0) { - list($a, $b) = array_map("trim", explode("==", $args[2])); - $a = $this->_get_var($a); - if ($b[0] == "$") - $b = $this->_get_var($b); - $val = ($a == $b); - } else if (strpos($args[2], "!=") > 0) { - list($a, $b) = array_map("trim", explode("!=", $args[2])); - $a = $this->_get_var($a); - if ($b[0] == "$") - $b = $this->_get_var($b); - $val = ($a != $b); - } else { - $val = $this->_get_var($args[2]); - } - $x = preg_split("|{{ *else *}}|", $args[3]); - return ( $val ? $x[0] : (isset($x[1]) ? $x[1] : "")); - } - - /** - * FOR node - * - * {{ for <$var> as $name }}...{{ endfor }} - * {{ for <$var> as $key=>$name }}...{{ endfor }} - */ - private function _replcb_for ($args) { - $m = array_map('trim', explode(" as ", $args[2])); - $x = explode("=>", $m[1]); - if (count($x) == 1) { - $varname = $x[0]; - $keyname = ""; - } else { - list($keyname, $varname) = $x; - } - if ($m[0] == "" || $varname == "" || is_null($varname)) - die("template error: 'for " . $m[0] . " as " . $varname . "'"); - //$vals = $this->r[$m[0]]; - $vals = $this->_get_var($m[0]); - $ret = ""; - if (!is_array($vals)) { - return $ret; - } - foreach ($vals as $k => $v) { - $this->_push_stack(); - $r = $this->r; - $r[$varname] = $v; - if ($keyname != '') { - $r[$keyname] = (($k === 0) ? '0' : $k); - } - $ret .= $this->replace($args[3], $r); - $this->_pop_stack(); - } - return $ret; - } - - /** - * INC node - * - * {{ inc [with $var1=$var2] }}{{ endinc }} - */ - private function _replcb_inc($args) { - if (strpos($args[2], "with")) { - list($tplfile, $newctx) = array_map('trim', explode("with", $args[2])); - } else { - $tplfile = trim($args[2]); - $newctx = null; - } - - if ($tplfile[0] == "$") - $tplfile = $this->_get_var($tplfile); - - $this->_push_stack(); - $r = $this->r; - if (!is_null($newctx)) { - list($a, $b) = array_map('trim', explode("=", $newctx)); - $r[$a] = $this->_get_var($b); - } - $this->nodes = Array(); - $tpl = get_markup_template($tplfile); - $ret = $this->replace($tpl, $r); - $this->_pop_stack(); - return $ret; - } - - /** - * DEBUG node - * - * {{ debug $var [$var [$var [...]]] }}{{ enddebug }} - * - * replace node with var_dump($var, $var, ...);- */ - private function _replcb_debug($args) { - $vars = array_map('trim', explode(" ", $args[2])); - $vars[] = $args[1]; - - $ret = ""; - foreach ($vars as $var) { - $ret .= htmlspecialchars(var_export($this->_get_var($var), true)); - $ret .= "\n"; - } - $ret .= ""; - return $ret; - } - - private function _replcb_node($m) { - $node = $this->nodes[$m[1]]; - if (method_exists($this, "_replcb_" . $node[1])) { - $s = call_user_func(array($this, "_replcb_" . $node[1]), $node); - } else { - $s = ""; - } - $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); - return $s; - } - - private function _replcb($m) { - //var_dump(array_map('htmlspecialchars', $m)); - $this->done = false; - $this->nodes[] = (array) $m; - return "||" . (count($this->nodes) - 1) . "||"; - } - - private function _build_nodes($s) { - $this->done = false; - while (!$this->done) { - $this->done = true; - $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s); - if ($s == Null) - $this->_preg_error(); - } - //({{ *else *}}[^{]*)? - krsort($this->nodes); - return $s; - } - - private function var_replace($s) { - $m = array(); - /** regexp: - * \$ literal $ - * (\[)? optional open square bracket - * ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional - * dot, repeated at least 1 time - * (|[a-zA-Z0-9-_:]+)* pipe followed by filter name and args, zero or many - * (?(1)\]) if there was opened square bracket - * (subgrup 1), match close bracket - */ - if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(\|[a-zA-Z0-9-_:]+)*(?(1)\])/', $s, $m)) { - foreach ($m[0] as $var) { - - $exp = str_replace(array("[", "]"), array("", ""), $var); - $exptks = explode("|", $exp); - - $varn = $exptks[0]; - unset($exptks[0]); - $val = $this->_get_var($varn, true); - if ($val != KEY_NOT_EXISTS) { - /* run filters */ - /* - * Filter are in form of: - * filtername:arg:arg:arg - * - * "filtername" is function name - * "arg"s are optional, var value is appended to the end - * if one "arg"==='x' , is replaced with var value - * - * examples: - * $item.body|htmlspecialchars // escape html chars - * $item.body|htmlspecialchars|strtoupper // escape html and uppercase result - * $item.created|date:%Y %M %j // format date (created is a timestamp) - * $item.body|str_replace:cat:dog // replace all "cat" with "dog" - * $item.body|str_replace:cat:dog:x:1 // replace one "cat" with "dog" - - */ - foreach ($exptks as $filterstr) { - $filter = explode(":", $filterstr); - $filtername = $filter[0]; - unset($filter[0]); - $valkey = array_search("x", $filter); - if ($valkey === false) { - $filter[] = $val; - } else { - $filter[$valkey] = $val; - } - if (function_exists($filtername)) { - $val = call_user_func_array($filtername, $filter); - } - } - $s = str_replace($var, $val, $s); - } - } - } - - return $s; - } - - // TemplateEngine interface - public function replace_macros($s, $r) { - $this->r = $r; - - // remove comments block - $s = preg_replace('/{#(.*?\s*?)*?#}/', "", $s); - - $s = $this->_build_nodes($s); - - $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); - if ($s == Null) - $this->_preg_error(); - - // replace strings recursively (limit to 10 loops) - $os = ""; - $count = 0; - while ($os != $s && $count < 10) { - $os = $s; - $count++; - $s = $this->var_replace($s); - } - return template_unescape($s); - } - - public function get_template_file($file, $root='') { - $a = get_app(); - $template_file = get_template_file($a, $file, $root); - $content = file_get_contents($template_file); - return $content; - } - -} - - -function template_escape($s) { - - return str_replace(array('$', '{{'), array('!_Doll^Ars1Az_!', '!_DoubLe^BraceS4Rw_!'), $s); -} - -function template_unescape($s) { - - return str_replace(array('!_Doll^Ars1Az_!', '!_DoubLe^BraceS4Rw_!'), array('$', '{{'), $s); -} - diff --git a/include/text.php b/include/text.php index 54595452c..9a3d24bd1 100644 --- a/include/text.php +++ b/include/text.php @@ -1,16 +1,16 @@ template_engine(); try { - $output = $t->replace_macros($s, $r); + $output = $t->replaceMacros($s, $r); } catch (Exception $e) { echo "" . __FUNCTION__ . ": " . $e->getMessage() . ""; killme(); @@ -42,18 +42,21 @@ function replace_macros($s, $r) { return $output; } +/** + * @brief Generates a pseudo-random string of hexadecimal characters + * + * @param int $size + * @return string + */ +function random_string($size = 64) +{ + $byte_size = ceil($size / 2); -// random string, there are 86 characters max in text mode, 128 for hex -// output is urlsafe + $bytes = random_bytes($byte_size); -define('RANDOM_STRING_HEX', 0x00); -define('RANDOM_STRING_TEXT', 0x01); + $return = substr(bin2hex($bytes), 0, $size); -function random_string($size = 64, $type = RANDOM_STRING_HEX) { - // generate a bit of entropy and run it through the whirlpool - $s = hash('whirlpool', (string) rand() . uniqid(rand(),true) . (string) rand(), (($type == RANDOM_STRING_TEXT) ? true : false)); - $s = (($type == RANDOM_STRING_TEXT) ? str_replace("\n", "", base64url_encode($s,true)) : $s); - return substr($s,0,$size); + return $return; } /** @@ -592,7 +595,7 @@ function get_markup_template($s, $root = '') { $a = get_app(); $t = $a->template_engine(); try { - $template = $t->get_template_file($s, $root); + $template = $t->getTemplateFile($s, $root); } catch (Exception $e) { echo "" . __FUNCTION__ . ": " . $e->getMessage() . ""; killme(); @@ -1148,7 +1151,7 @@ function get_mood_verbs() { /** * @brief Translate days and months names. - * + * * @param string $s String with day or month name. * @return string Translated string. */ @@ -1166,7 +1169,7 @@ function day_translate($s) { /** * @brief Translate short days and months names. - * + * * @param string $s String with short day or month name. * @return string Translated string. */ diff --git a/include/threads.php b/include/threads.php index 16d4915fd..00848ccc6 100644 --- a/include/threads.php +++ b/include/threads.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Object\Contact; function add_thread($itemid, $onlyshadow = false) { $items = q("SELECT `uid`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, @@ -58,7 +59,7 @@ function add_shadow_thread($itemid) { } // Is the public contact configured as hidden? - if (hiddenContact($item["owner-id"]) || hiddenContact($item["author-id"])) { + if (Contact::isHidden($item["owner-id"]) || Contact::isHidden($item["author-id"])) { return; } @@ -98,13 +99,12 @@ function add_shadow_thread($itemid) { if (!DBM::is_result($r)) { // Preparing public shadow (removing user specific data) require_once("include/items.php"); - require_once("include/Contact.php"); unset($item[0]['id']); $item[0]['uid'] = 0; $item[0]['origin'] = 0; $item[0]['wall'] = 0; - $item[0]['contact-id'] = get_contact($item[0]['author-link'], 0); + $item[0]['contact-id'] = Contact::getIdForURL($item[0]['author-link'], 0); if (in_array($item[0]['type'], array("net-comment", "wall-comment"))) { $item[0]['type'] = 'remote-comment'; @@ -158,13 +158,12 @@ function add_shadow_entry($itemid) { // Preparing public shadow (removing user specific data) require_once("include/items.php"); - require_once("include/Contact.php"); unset($item['id']); $item['uid'] = 0; $item['origin'] = 0; $item['wall'] = 0; - $item['contact-id'] = get_contact($item['author-link'], 0); + $item['contact-id'] = Contact::getIdForURL($item['author-link'], 0); if (in_array($item['type'], array("net-comment", "wall-comment"))) { $item['type'] = 'remote-comment'; @@ -252,7 +251,7 @@ function delete_thread($itemid, $itemuri = "") { } // Using dba::delete at this time could delete the associated item entries - $result = q("DELETE FROM `thread` WHERE `iid` = %d", intval($itemid)); + $result = dba::e("DELETE FROM `thread` WHERE `iid` = ?", $itemid); logger("delete_thread: Deleted thread for item ".$itemid." - ".print_r($result, true), LOGGER_DEBUG); diff --git a/include/threadupdate.php b/include/threadupdate.php deleted file mode 100644 index 3a4028603..000000000 --- a/include/threadupdate.php +++ /dev/null @@ -1,7 +0,0 @@ -"; var_dump($r, $query, mysql_error()); killme(); logger("uimport:insert user : ERROR : " . dba::errorMessage(), LOGGER_NORMAL); notice(t("User creation error")); return; @@ -189,7 +188,7 @@ function import_account(App $a, $file) { } } if ($contact['uid'] == $olduid && $contact['self'] == '0') { - // set contacts 'avatar-date' to NULL_DATE to let poller to update urls + // set contacts 'avatar-date' to NULL_DATE to let worker to update urls $contact["avatar-date"] = NULL_DATE; switch ($contact['network']) { @@ -286,7 +285,7 @@ function import_account(App $a, $file) { } // send relocate messages - Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', $newuid); + Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $newuid); info(t("Done. You can now login with your username and password")); goaway(System::baseUrl() . "/login"); diff --git a/include/update_gcontact.php b/include/update_gcontact.php deleted file mode 100644 index cd7a9366f..000000000 --- a/include/update_gcontact.php +++ /dev/null @@ -1,80 +0,0 @@ - 1) && (intval($argv[1]))) { - $contact_id = intval($argv[1]); - } - - if (!$contact_id) { - logger('update_gcontact: no contact'); - return; - } - - $r = q("SELECT * FROM `gcontact` WHERE `id` = %d", intval($contact_id)); - - if (!DBM::is_result($r)) { - return; - } - - if (!in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { - return; - } - - $data = Probe::uri($r[0]["url"]); - - if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { - if ($r[0]["server_url"] != "") - poco_check_server($r[0]["server_url"], $r[0]["network"]); - - q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `id` = %d", - dbesc(datetime_convert()), intval($contact_id)); - return; - } - - if (($data["name"] == "") && ($r[0]['name'] != "")) - $data["name"] = $r[0]['name']; - - if (($data["nick"] == "") && ($r[0]['nick'] != "")) - $data["nick"] = $r[0]['nick']; - - if (($data["addr"] == "") && ($r[0]['addr'] != "")) - $data["addr"] = $r[0]['addr']; - - if (($data["photo"] == "") && ($r[0]['photo'] != "")) - $data["photo"] = $r[0]['photo']; - - - q("UPDATE `gcontact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `photo` = '%s' - WHERE `id` = %d", - dbesc($data["name"]), - dbesc($data["nick"]), - dbesc($data["addr"]), - dbesc($data["photo"]), - intval($contact_id) - ); - - q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `photo` = '%s' - WHERE `uid` = 0 AND `addr` = '' AND `nurl` = '%s'", - dbesc($data["name"]), - dbesc($data["nick"]), - dbesc($data["addr"]), - dbesc($data["photo"]), - dbesc(normalise_link($data["url"])) - ); - - q("UPDATE `contact` SET `addr` = '%s' - WHERE `uid` != 0 AND `addr` = '' AND `nurl` = '%s'", - dbesc($data["addr"]), - dbesc(normalise_link($data["url"])) - ); -} diff --git a/include/user.php b/include/user.php index be03637df..d82671b86 100644 --- a/include/user.php +++ b/include/user.php @@ -4,13 +4,12 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; -require_once('include/network.php'); -require_once('include/plugin.php'); -require_once('include/text.php'); -require_once('include/pgettext.php'); -require_once('include/datetime.php'); -require_once('include/enotify.php'); - +require_once 'include/network.php'; +require_once 'include/plugin.php'; +require_once 'include/text.php'; +require_once 'include/pgettext.php'; +require_once 'include/datetime.php'; +require_once 'include/enotify.php'; function create_user($arr) { @@ -388,7 +387,7 @@ function user_create_self_contact($uid) { * @param string $email * @param string $sitename * @param string $username - * @return NULL|boolean from notification() and email() inherited + * @return NULL|boolean from notification() and email() inherited */ function send_register_pending_eml($email, $sitename, $username) { $body = deindent(t(' diff --git a/index.php b/index.php index 591549890..0290a38be 100644 --- a/index.php +++ b/index.php @@ -1,42 +1,35 @@ backend = false; /** - * * Load the configuration file which contains our DB credentials. * Ignore errors. If the file doesn't exist or is empty, we are running in * installation mode. - * */ $install = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? false : true); @@ -47,9 +40,7 @@ if (!$install) { } /** - * * Try to open the database; - * */ require_once "include/dba.php"; @@ -71,9 +62,10 @@ if (!$install) { die("System is currently unavailable. Please try again later"); } - if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") && - (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL) && - (substr(System::baseUrl(), 0, 8) == "https://")) { + if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") + && (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL) + && (substr(System::baseUrl(), 0, 8) == "https://") + ) { header("HTTP/1.1 302 Moved Temporarily"); header("Location: " . System::baseUrl() . "/" . $a->query_string); exit(); @@ -91,14 +83,12 @@ $lang = get_browser_language(); load_translation_table($lang); /** - * * Important stuff we always need to do. * * The order of these may be important so use caution if you think they're all * intertwingled with no logical order and decide to sort it out. Some of the * dependencies have changed, but at least at one time in the recent past - the * order was critical to everything working properly - * */ // Exclude the backend processes from the session management @@ -114,7 +104,7 @@ if (!$a->is_backend()) { * Language was set earlier, but we can over-ride it in the session. * We have to do it here because the session was just now opened. */ -if (x($_SESSION,'authenticated') && !x($_SESSION,'language')) { +if (x($_SESSION, 'authenticated') && !x($_SESSION, 'language')) { // we didn't loaded user data yet, but we need user language $r = dba::select('user', array('language'), array('uid' => $_SESSION['uid']), array('limit' => 1)); $_SESSION['language'] = $lang; @@ -123,18 +113,19 @@ if (x($_SESSION,'authenticated') && !x($_SESSION,'language')) { } } -if ((x($_SESSION,'language')) && ($_SESSION['language'] !== $lang)) { +if ((x($_SESSION, 'language')) && ($_SESSION['language'] !== $lang)) { $lang = $_SESSION['language']; load_translation_table($lang); } -if ((x($_GET,'zrl')) && (!$install && !$maintenance)) { +if ((x($_GET, 'zrl')) && (!$install && !$maintenance)) { // Only continue when the given profile link seems valid // Valid profile links contain a path with "/profile/" and no query parameters - if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "") && - strstr(parse_url($_GET['zrl'], PHP_URL_PATH), "/profile/")) { + if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "") + && strstr(parse_url($_GET['zrl'], PHP_URL_PATH), "/profile/") + ) { $_SESSION['my_url'] = $_GET['zrl']; - $a->query_string = preg_replace('/[\?&]zrl=(.*?)([\?&]|$)/is','',$a->query_string); + $a->query_string = preg_replace('/[\?&]zrl=(.*?)([\?&]|$)/is', '', $a->query_string); zrl_init($a); } else { // Someone came with an invalid parameter, maybe as a DDoS attempt @@ -147,23 +138,21 @@ if ((x($_GET,'zrl')) && (!$install && !$maintenance)) { } /** - * * For Mozilla auth manager - still needs sorting, and this might conflict with LRDD header. * Apache/PHP lumps the Link: headers into one - and other services might not be able to parse it * this way. There's a PHP flag to link the headers because by default this will over-write any other * link header. * * What we really need to do is output the raw headers ourselves so we can keep them separate. - * */ // header('Link: <' . System::baseUrl() . '/amcd>; rel="acct-mgmt";'); -if (x($_COOKIE["Friendica"]) || (x($_SESSION,'authenticated')) || (x($_POST,'auth-params')) || ($a->module === 'login')) { - require("include/auth.php"); +if (x($_COOKIE["Friendica"]) || (x($_SESSION, 'authenticated')) || (x($_POST, 'auth-params')) || ($a->module === 'login')) { + require "include/auth.php"; } -if (! x($_SESSION,'authenticated')) { +if (! x($_SESSION, 'authenticated')) { header('X-Account-Management-Status: none'); } @@ -172,16 +161,16 @@ $a->page['htmlhead'] = ''; $a->page['end'] = ''; -if (! x($_SESSION,'sysmsg')) { +if (! x($_SESSION, 'sysmsg')) { $_SESSION['sysmsg'] = array(); } -if (! x($_SESSION,'sysmsg_info')) { +if (! x($_SESSION, 'sysmsg_info')) { $_SESSION['sysmsg_info'] = array(); } // Array for informations about last received items -if (! x($_SESSION,'last_updated')) { +if (! x($_SESSION, 'last_updated')) { $_SESSION['last_updated'] = array(); } /* @@ -205,7 +194,7 @@ if ($install && $a->module!="view") { nav_set_selected('nothing'); //Don't populate apps_menu if apps are private -$privateapps = Config::get('config','private_addons'); +$privateapps = Config::get('config', 'private_addons'); if ((local_user()) || (! $privateapps === "1")) { $arr = array('app_menu' => $a->apps); @@ -215,7 +204,6 @@ if ((local_user()) || (! $privateapps === "1")) { } /** - * * We have already parsed the server path into $a->argc and $a->argv * * $a->argv[0] is our module name. We will load the file mod/{$a->argv[0]}.php @@ -236,10 +224,8 @@ if ((local_user()) || (! $privateapps === "1")) { if (strlen($a->module)) { /** - * * We will always have a module name. * First see if we have a plugin which is masquerading as a module. - * */ // Compatibility with the Android Diaspora client @@ -252,14 +238,14 @@ if (strlen($a->module)) { $a->module = "login"; } - $privateapps = Config::get('config','private_addons'); + $privateapps = Config::get('config', 'private_addons'); - if (is_array($a->plugins) && in_array($a->module,$a->plugins) && file_exists("addon/{$a->module}/{$a->module}.php")) { + if (is_array($a->plugins) && in_array($a->module, $a->plugins) && file_exists("addon/{$a->module}/{$a->module}.php")) { //Check if module is an app and if public access to apps is allowed or not if ((!local_user()) && plugin_is_app($a->module) && $privateapps === "1") { - info( t("You must be logged in to use addons. ")); + info(t("You must be logged in to use addons. ")); } else { - include_once("addon/{$a->module}/{$a->module}.php"); + include_once "addon/{$a->module}/{$a->module}.php"; if (function_exists($a->module . '_module')) { $a->module_loaded = true; } @@ -271,12 +257,11 @@ if (strlen($a->module)) { */ if ((! $a->module_loaded) && (file_exists("mod/{$a->module}.php"))) { - include_once("mod/{$a->module}.php"); + include_once "mod/{$a->module}.php"; $a->module_loaded = true; } /** - * * The URL provided does not resolve to a valid module. * * On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'. @@ -285,17 +270,15 @@ if (strlen($a->module)) { * this will often succeed and eventually do the right thing. * * Otherwise we are going to emit a 404 not found. - * */ if (! $a->module_loaded) { - // Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit. - if ((x($_SERVER,'QUERY_STRING')) && preg_match('/{[0-9]}/',$_SERVER['QUERY_STRING']) !== 0) { + if ((x($_SERVER, 'QUERY_STRING')) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) { killme(); } - if ((x($_SERVER,'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) { + if ((x($_SERVER, 'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) { logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']); goaway(System::baseUrl() . $_SERVER['REQUEST_URI']); } @@ -303,29 +286,31 @@ if (strlen($a->module)) { logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG); header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . t('Not Found')); $tpl = get_markup_template("404.tpl"); - $a->page['content'] = replace_macros($tpl, array( - '$message' => t('Page not found.' ) - )); + $a->page['content'] = replace_macros( + $tpl, + array( + '$message' => t('Page not found.')) + ); } } /** - * load current theme info + * Load current theme info */ $theme_info_file = "view/theme/".current_theme()."/theme.php"; -if (file_exists($theme_info_file)){ - require_once($theme_info_file); +if (file_exists($theme_info_file)) { + require_once $theme_info_file; } /* initialise content region */ -if (! x($a->page,'content')) { +if (! x($a->page, 'content')) { $a->page['content'] = ''; } if (!$install && !$maintenance) { - call_hooks('page_content_top',$a->page['content']); + call_hooks('page_content_top', $a->page['content']); } /** @@ -342,21 +327,22 @@ if ($a->module_loaded) { $func($a); } - if (function_exists(str_replace('-','_',current_theme()) . '_init')) { - $func = str_replace('-','_',current_theme()) . '_init'; + if (function_exists(str_replace('-', '_', current_theme()) . '_init')) { + $func = str_replace('-', '_', current_theme()) . '_init'; $func($a); } if (($_SERVER['REQUEST_METHOD'] === 'POST') && (! $a->error) && (function_exists($a->module . '_post')) - && (! x($_POST,'auth-params'))) { + && (! x($_POST, 'auth-params')) + ) { call_hooks($a->module . '_mod_post', $_POST); $func = $a->module . '_post'; $func($a); } if ((! $a->error) && (function_exists($a->module . '_afterpost'))) { - call_hooks($a->module . '_mod_afterpost',$placeholder); + call_hooks($a->module . '_mod_afterpost', $placeholder); $func = $a->module . '_afterpost'; $func($a); } @@ -371,8 +357,8 @@ if ($a->module_loaded) { $a->page['content'] .= $arr['content']; } - if (function_exists(str_replace('-','_',current_theme()) . '_content_loaded')) { - $func = str_replace('-','_',current_theme()) . '_content_loaded'; + if (function_exists(str_replace('-', '_', current_theme()) . '_content_loaded')) { + $func = str_replace('-', '_', current_theme()) . '_content_loaded'; $func($a); } } @@ -434,10 +420,12 @@ if ($a->is_mobile || $a->is_tablet) { } else { $link = 'toggle_mobile?off=1&address=' . curPageURL(); } - $a->page['footer'] = replace_macros(get_markup_template("toggle_mobile_footer.tpl"), array( - '$toggle_link' => $link, - '$toggle_text' => t('toggle mobile') - )); + $a->page['footer'] = replace_macros( + get_markup_template("toggle_mobile_footer.tpl"), + array( + '$toggle_link' => $link, + '$toggle_text' => t('toggle mobile')) + ); } /** @@ -450,7 +438,7 @@ if (!$a->theme['stylesheet']) { $stylesheet = $a->theme['stylesheet']; } -$a->page['htmlhead'] = str_replace('{{$stylesheet}}',$stylesheet,$a->page['htmlhead']); +$a->page['htmlhead'] = str_replace('{{$stylesheet}}', $stylesheet, $a->page['htmlhead']); //$a->page['htmlhead'] = replace_macros($a->page['htmlhead'], array('$stylesheet' => $stylesheet)); if (isset($_GET["mode"]) && (($_GET["mode"] == "raw") || ($_GET["mode"] == "minimal"))) { @@ -477,7 +465,6 @@ if (isset($_GET["mode"]) && (($_GET["mode"] == "raw") || ($_GET["mode"] == "mini } if (isset($_GET["mode"]) && ($_GET["mode"] == "raw")) { - header("Content-type: text/html; charset=utf-8"); echo substr($target->saveHTML(), 6, -8); diff --git a/js/acl.js b/js/acl.js index 9a575729f..257e2c158 100644 --- a/js/acl.js +++ b/js/acl.js @@ -7,12 +7,15 @@ function ACL(backend_url, preset, automention, is_mobile){ this.kp_timer = null; - if (preset==undefined) preset = []; + if (preset == undefined) { + preset = []; + } this.allow_cid = (preset[0] || []); this.allow_gid = (preset[1] || []); this.deny_cid = (preset[2] || []); this.deny_gid = (preset[3] || []); this.group_uids = []; + this.forumCache = null; if (this.is_mobile) { this.nw = 1; @@ -25,7 +28,9 @@ function ACL(backend_url, preset, automention, is_mobile){ this.item_tpl = unescape($(".acl-list-item[rel=acl-template]").html()); this.showall = $("#acl-showall"); - if (preset.length==0) this.showall.addClass("selected"); + if (preset.length==0) { + this.showall.addClass("selected"); + } /*events*/ this.showall.click(this.on_showall.bind(this)); @@ -61,7 +66,7 @@ ACL.prototype.remove_mention = function(id) { } var end = start + searchText.length; this.element.setSelection(start, end).replaceSelectedText('').collapseSelection(false); -} +}; ACL.prototype.add_mention = function(id) { if (!this.automention) { @@ -96,18 +101,18 @@ ACL.prototype.on_submit = function(){ $(this.deny_cid).each(function(i,v){ aclfields.append(""); }); -} +}; ACL.prototype.search = function(){ var srcstr = $("#acl-search").val(); this.list_content.html(""); this.get(0,100, srcstr); -} +}; ACL.prototype.on_search = function(event){ if (this.kp_timer) clearTimeout(this.kp_timer); this.kp_timer = setTimeout( this.search.bind(this), 1000); -} +}; ACL.prototype.on_showall = function(event){ event.preventDefault() @@ -126,7 +131,7 @@ ACL.prototype.on_showall = function(event){ this.update_view(); return false; -} +}; ACL.prototype.on_button_show = function(event){ event.preventDefault() @@ -136,7 +141,8 @@ ACL.prototype.on_button_show = function(event){ this.set_allow($(event.target).parent().attr('id')); return false; -} +}; + ACL.prototype.on_button_hide = function(event){ event.preventDefault() event.stopImmediatePropagation() @@ -145,34 +151,50 @@ ACL.prototype.on_button_hide = function(event){ this.set_deny($(event.target).parent().attr('id')); return false; -} +}; -ACL.prototype.set_allow = function(itemid){ +ACL.prototype.set_allow = function(itemid) { type = itemid[0]; - id = parseInt(itemid.substr(1)); + id = parseInt(itemid.substr(1)); - switch(type){ + switch (type){ case "g": - if (this.allow_gid.indexOf(id)<0){ - this.allow_gid.push(id) + if (this.allow_gid.indexOf(id) < 0) { + this.allow_gid.push(id); }else { this.allow_gid.remove(id); } - if (this.deny_gid.indexOf(id)>=0) this.deny_gid.remove(id); + if (this.deny_gid.indexOf(id) >= 0) { + this.deny_gid.remove(id); + } break; case "c": - if (this.allow_cid.indexOf(id)<0){ - this.allow_cid.push(id) - if (this.data[id].forum=="1") this.add_mention(id); + if (this.allow_cid.indexOf(id) < 0){ + this.allow_cid.push(id); + if (this.data[id].forum == "1") { + // If we have select already a forum, + // we need to remove the old one (because friendica does + // allow only one forum as receiver). + if (this.forumCache !== null && this.forumCache !== id) { + this.deselectCid(this.forumCache); + } + // Update the forum cache. + this.forumCache = id; + this.add_mention(id); + } } else { this.allow_cid.remove(id); - if (this.data[id].forum=="1") this.remove_mention(id); + if (this.data[id].forum == "1") { + this.remove_mention(id); + } + } + if (this.deny_cid.indexOf(id) >=0 ) { + this.deny_cid.remove(id); } - if (this.deny_cid.indexOf(id)>=0) this.deny_cid.remove(id); break; } this.update_view(); -} +}; ACL.prototype.set_deny = function(itemid){ type = itemid[0]; @@ -198,12 +220,12 @@ ACL.prototype.set_deny = function(itemid){ break; } this.update_view(); -} +}; ACL.prototype.is_show_all = function() { return (this.allow_gid.length==0 && this.allow_cid.length==0 && this.deny_gid.length==0 && this.deny_cid.length==0); -} +}; ACL.prototype.update_view = function(){ if (this.is_show_all()){ @@ -279,7 +301,6 @@ ACL.prototype.update_view = function(){ } - ACL.prototype.get = function(start,count, search){ var postdata = { start:start, @@ -294,7 +315,7 @@ ACL.prototype.get = function(start,count, search){ dataType: 'json', success:this.populate.bind(this) }); -} +}; ACL.prototype.populate = function(data){ var height = Math.ceil(data.tot / this.nw) * 42; @@ -319,5 +340,20 @@ ACL.prototype.populate = function(data){ }); this.update_view(); -} +}; +/** + * @brief Deselect previous selected contact. + * + * @param {int} id The contact ID. + * @returns {void} + */ +ACL.prototype.deselectCid = function(id) { + if (this.allow_cid.indexOf(id) >= 0) { + this.allow_cid.remove(id); + } + if (this.deny_cid.indexOf(id) >=0 ) { + this.deny_cid.remove(id); + } + this.remove_mention(id); +}; diff --git a/mod/admin.php b/mod/admin.php index 78e37afef..4b034b8cc 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -11,10 +11,11 @@ use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\User; -require_once("include/enotify.php"); -require_once("include/text.php"); -require_once('include/items.php'); +require_once 'include/enotify.php'; +require_once 'include/text.php'; +require_once 'include/items.php'; /** * @brief Process send data from the admin panels subpages @@ -705,7 +706,7 @@ function admin_page_site_post(App $a) { check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); if (!empty($_POST['republish_directory'])) { - Worker::add(PRIORITY_LOW, 'directory'); + Worker::add(PRIORITY_LOW, 'Directory'); return; } @@ -778,7 +779,7 @@ function admin_page_site_post(App $a) { $users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0"); foreach ($users as $user) { - Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', $user['uid']); + Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $user['uid']); } info("Relocation started. Could take a while to complete."); @@ -813,7 +814,6 @@ function admin_page_site_post(App $a) { $block_public = ((x($_POST,'block_public')) ? True : False); $force_publish = ((x($_POST,'publish_all')) ? True : False); $global_directory = ((x($_POST,'directory')) ? notags(trim($_POST['directory'])) : ''); - $thread_allow = ((x($_POST,'thread_allow')) ? True : False); $newuser_private = ((x($_POST,'newuser_private')) ? True : False); $enotify_no_content = ((x($_POST,'enotify_no_content')) ? True : False); $private_addons = ((x($_POST,'private_addons')) ? True : False); @@ -867,15 +867,12 @@ function admin_page_site_post(App $a) { // Has the directory url changed? If yes, then resubmit the existing profiles there if ($global_directory != Config::get('system', 'directory') && ($global_directory != '')) { Config::set('system', 'directory', $global_directory); - Worker::add(PRIORITY_LOW, 'directory'); + Worker::add(PRIORITY_LOW, 'Directory'); } if ($a->get_path() != "") { $diaspora_enabled = false; } - if (!$thread_allow) { - $ostatus_disabled = true; - } if ($ssl_policy != intval(Config::get('system','ssl_policy'))) { if ($ssl_policy == SSL_POLICY_FULL) { q("UPDATE `contact` SET @@ -974,7 +971,6 @@ function admin_page_site_post(App $a) { Config::set('system', 'allowed_email', $allowed_email); Config::set('system', 'block_public', $block_public); Config::set('system', 'publish_all', $force_publish); - Config::set('system', 'thread_allow', $thread_allow); Config::set('system', 'newuser_private', $newuser_private); Config::set('system', 'enotify_no_content', $enotify_no_content); Config::set('system', 'disable_embedded', $disable_embedded); @@ -1213,7 +1209,6 @@ function admin_page_site(App $a) { '$block_public' => array('block_public', t("Block public"), Config::get('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")), '$force_publish' => array('publish_all', t("Force publish"), Config::get('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")), '$global_directory' => array('directory', t("Global directory URL"), Config::get('system','directory'), t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")), - '$thread_allow' => array('thread_allow', t("Allow threaded items"), Config::get('system','thread_allow'), t("Allow infinite level threading for items on this site.")), '$newuser_private' => array('newuser_private', t("Private posts by default for new users"), Config::get('system','newuser_private'), t("Set default post permissions for all new members to the default privacy group rather than public.")), '$enotify_no_content' => array('enotify_no_content', t("Don't include post content in email notifications"), Config::get('system','enotify_no_content'), t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")), '$private_addons' => array('private_addons', t("Disallow public access to addons listed in the apps menu."), Config::get('config','private_addons'), t("Checking this box will restrict addons listed in the apps menu to members only.")), @@ -1237,7 +1232,7 @@ function admin_page_site(App $a) { '$timeout' => array('timeout', t("Network timeout"), (x(Config::get('system','curl_timeout'))?Config::get('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")), '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(Config::get('system','maxloadavg')) > 0)?Config::get('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")), '$maxloadavg_frontend' => array('maxloadavg_frontend', t("Maximum Load Average (Frontend)"), ((intval(Config::get('system','maxloadavg_frontend')) > 0)?Config::get('system','maxloadavg_frontend'):50), t("Maximum system load before the frontend quits service - default 50.")), - '$min_memory' => array('min_memory', t("Minimal Memory"), ((intval(Config::get('system','min_memory')) > 0)?Config::get('system','min_memory'):0), t("Minimal free memory in MB for the poller. Needs access to /proc/meminfo - default 0 (deactivated).")), + '$min_memory' => array('min_memory', t("Minimal Memory"), ((intval(Config::get('system','min_memory')) > 0)?Config::get('system','min_memory'):0), t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 (deactivated).")), '$optimize_max_tablesize'=> array('optimize_max_tablesize', t("Maximum table size for optimization"), $optimize_max_tablesize, t("Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it.")), '$optimize_fragmentation'=> array('optimize_fragmentation', t("Minimum level of fragmentation"), ((intval(Config::get('system','optimize_fragmentation')) > 0)?Config::get('system','optimize_fragmentation'):30), t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")), @@ -1264,7 +1259,7 @@ function admin_page_site(App $a) { '$rino' => array('rino', t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), t("Encryption layer between nodes."), array("Disabled", "RINO1 (deprecated)", "RINO2")), '$worker_queues' => array('worker_queues', t("Maximum number of parallel workers"), Config::get('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")), - '$worker_dont_fork' => array('worker_dont_fork', t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of poller calls in your crontab.")), + '$worker_dont_fork' => array('worker_dont_fork', t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")), '$worker_fastlane' => array('worker_fastlane', t("Enable fastlane"), Config::get('system','worker_fastlane'), t("When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.")), '$worker_frontend' => array('worker_frontend', t('Enable frontend worker'), Config::get('system','frontend_worker'), sprintf(t('When enabled the Worker process is triggered when backend access is performed (e.g. messages being delivered). On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.'), System::baseUrl())), @@ -1443,9 +1438,8 @@ function admin_page_users_post(App $a) { notice(sprintf(tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users))); } if (x($_POST,'page_users_delete')) { - require_once("include/Contact.php"); foreach ($users as $uid) { - user_remove($uid); + User::remove($uid); } notice(sprintf(tt("%s user deleted", "%s users deleted", count($users)), count($users))); } @@ -1491,8 +1485,7 @@ function admin_page_users(App $a) { case "delete": check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); // delete user - require_once("include/Contact.php"); - user_remove($uid); + User::remove($uid); notice(sprintf(t("User '%s' deleted"), $user[0]['username']).EOL); break; diff --git a/mod/allfriends.php b/mod/allfriends.php index ce9e68f01..3cfe6c0f9 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -1,13 +1,15 @@ page['aside'] = ""; - profile_load($a, "", 0, get_contact_details_by_url($c[0]["url"])); + profile_load($a, "", 0, Contact::getDetailsByURL($c[0]["url"])); - $total = count_all_friends(local_user(), $cid); + $total = GlobalContact::countAllFriends(local_user(), $cid); if(count($total)) $a->set_pager_total($total); - $r = all_friends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); + $r = GlobalContact::allFriends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); if (! DBM::is_result($r)) { $o .= t('No friends to display.'); @@ -56,7 +58,7 @@ function allfriends_content(App $a) { foreach ($r as $rr) { //get further details of the contact - $contact_details = get_contact_details_by_url($rr['url'], $uid, $rr); + $contact_details = Contact::getDetailsByURL($rr['url'], $uid, $rr); $photo_menu = ''; @@ -64,7 +66,7 @@ function allfriends_content(App $a) { // If the contact is not common to the user, Connect/Follow' will be added to the photo menu if ($rr[cid]) { $rr[id] = $rr[cid]; - $photo_menu = contact_photo_menu ($rr); + $photo_menu = Contact::photoMenu ($rr); } else { $connlnk = System::baseUrl() . '/follow/?url=' . $rr['url']; @@ -83,7 +85,7 @@ function allfriends_content(App $a) { 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' => account_type($contact_details), + 'account_type' => Contact::getAccountType($contact_details), 'network' => network_to_name($contact_details['network'], $contact_details['url']), 'photo_menu' => $photo_menu, 'conntxt' => t('Connect'), diff --git a/mod/cal.php b/mod/cal.php index 1bfc8d95d..170e7ea4c 100644 --- a/mod/cal.php +++ b/mod/cal.php @@ -11,9 +11,10 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Object\Contact; -require_once('include/event.php'); -require_once('include/redir.php'); +require_once 'include/event.php'; +require_once 'include/redir.php'; function cal_init(App $a) { if($a->argc > 1) @@ -46,7 +47,7 @@ function cal_init(App $a) { $profile = get_profiledata_by_nick($nick, $a->profile_uid); - $account_type = account_type($profile); + $account_type = Contact::getAccountType($profile); $tpl = get_markup_template("vcard-widget.tpl"); diff --git a/mod/common.php b/mod/common.php index 12f1ba273..9933c3f51 100644 --- a/mod/common.php +++ b/mod/common.php @@ -1,12 +1,14 @@ page['aside'] = ""; - profile_load($a, "", 0, get_contact_details_by_url($c[0]["url"])); + profile_load($a, "", 0, Contact::getDetailsByURL($c[0]["url"])); } else { $c = q("SELECT `name`, `url`, `photo` FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid) @@ -83,23 +85,23 @@ function common_content(App $a) { } if ($cid) { - $t = count_common_friends($uid, $cid); + $t = GlobalContact::countCommonFriends($uid, $cid); } else { - $t = count_common_friends_zcid($uid, $zcid); + $t = GlobalContact::countCommonFriendsZcid($uid, $zcid); } if (count($t)) { $a->set_pager_total($t); } else { - notice( t('No contacts in common.') . EOL); + notice(t('No contacts in common.') . EOL); return $o; } if ($cid) { - $r = common_friends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); + $r = GlobalContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); } else { - $r = common_friends_zcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); + $r = GlobalContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); } @@ -112,14 +114,14 @@ function common_content(App $a) { foreach ($r as $rr) { //get further details of the contact - $contact_details = get_contact_details_by_url($rr['url'], $uid); + $contact_details = Contact::getDetailsByURL($rr['url'], $uid); // $rr['id'] is needed to use contact_photo_menu() /// @TODO Adding '/" here avoids E_NOTICE on missing constants $rr['id'] = $rr['cid']; $photo_menu = ''; - $photo_menu = contact_photo_menu($rr); + $photo_menu = Contact::photoMenu($rr); $entry = array( 'url' => $rr['url'], @@ -130,7 +132,7 @@ function common_content(App $a) { 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' => account_type($contact_details), + 'account_type' => Contact::getAccountType($contact_details), 'network' => network_to_name($contact_details['network'], $contact_details['url']), 'photo_menu' => $photo_menu, 'id' => ++$id, diff --git a/mod/contacts.php b/mod/contacts.php index 5c810b179..35be8e79e 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -4,10 +4,10 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBM; +use Friendica\Model\GlobalContact; use Friendica\Network\Probe; +use Friendica\Object\Contact; -require_once 'include/Contact.php'; -require_once 'include/socgraph.php'; require_once 'include/contact_selectors.php'; require_once 'mod/proxy.php'; require_once 'include/Photo.php'; @@ -58,7 +58,7 @@ function contacts_init(App $a) { '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), '$network_name' => $networkname, '$network' => t('Network:'), - '$account_type' => account_type($a->data['contact']) + '$account_type' => Contact::getAccountType($a->data['contact']) )); $finpeople_widget = ''; @@ -131,7 +131,7 @@ function contacts_batch_actions(App $a) { if ($r) $count_actions++; } if (x($_POST, 'contacts_batch_drop')) { - _contact_drop($contact_id, $orig_record); + _contact_drop($orig_record); $count_actions++; } } @@ -252,7 +252,7 @@ function _contact_update($contact_id) { intval($contact_id)); } else // pull feed and consume it, which should subscribe to the hub. - Worker::add(PRIORITY_HIGH, "onepoll", $contact_id, "force"); + Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force"); } function _contact_update_profile($contact_id) { @@ -312,7 +312,7 @@ function _contact_update_profile($contact_id) { update_contact_avatar($data['photo'], local_user(), $contact_id, true); // Update the entry in the gcontact table - update_gcontact_from_probe($data["url"]); + GlobalContact::updateFromProbe($data["url"]); } function _contact_block($contact_id, $orig_record) { @@ -346,7 +346,9 @@ function _contact_archive($contact_id, $orig_record) { } return $r; } -function _contact_drop($contact_id, $orig_record) { + +function _contact_drop($orig_record) +{ $a = get_app(); $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` @@ -357,9 +359,8 @@ function _contact_drop($contact_id, $orig_record) { return; } - $self = ""; // Unused parameter - terminate_friendship($r[0], $self, $orig_record); - contact_remove($orig_record['id']); + Contact::terminateFriendship($r[0], $orig_record); + Contact::remove($orig_record['id']); } @@ -479,7 +480,7 @@ function contacts_content(App $a) { } } - _contact_drop($contact_id, $orig_record[0]); + _contact_drop($orig_record[0]); info( t('Contact has been removed.') . EOL ); if (x($_SESSION,'return_url')) { goaway('' . $_SESSION['return_url']); @@ -561,12 +562,12 @@ function contacts_content(App $a) { $nettype = sprintf( t('Network type: %s'),network_to_name($contact['network'], $contact["url"])); - //$common = count_common_friends(local_user(),$contact['id']); + //$common = GlobalContact::countCommonFriends(local_user(),$contact['id']); //$common_text = (($common) ? sprintf( tt('%d contact in common','%d contacts in common', $common),$common) : ''); $polling = (($contact['network'] === NETWORK_MAIL | $contact['network'] === NETWORK_FEED) ? 'polling' : ''); - //$x = count_all_friends(local_user(), $contact['id']); + //$x = GlobalContact::countAllFriends(local_user(), $contact['id']); //$all_friends = (($x) ? t('View all contacts') : ''); // tabs @@ -575,8 +576,14 @@ function contacts_content(App $a) { $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : ''); if ($contact['network'] == NETWORK_FEED) { - $fetch_further_information = array('fetch_further_information', t('Fetch further information for feeds'), $contact['fetch_further_information'], t('Fetch further information for feeds'), - array('0'=>t('Disabled'), '1'=>t('Fetch information'), '2'=>t('Fetch information and keywords'))); + $fetch_further_information = array('fetch_further_information', + t('Fetch further information for feeds'), + $contact['fetch_further_information'], + t("Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn't contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags."), + array('0' => t('Disabled'), + '1' => t('Fetch information'), + '3' => t('Fetch keywords'), + '2' => t('Fetch information and keywords'))); } if (in_array($contact['network'], array(NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2))) $poll_interval = contact_poll_interval($contact['priority'],(! $poll_enabled)); @@ -640,6 +647,7 @@ function contacts_content(App $a) { '$blocked' => (($contact['blocked']) ? t('Currently blocked') : ''), '$ignored' => (($contact['readonly']) ? t('Currently ignored') : ''), '$archived' => (($contact['archive']) ? t('Currently archived') : ''), + '$pending' => (($contact['pending']) ? t('Awaiting connection acknowledge') : ''), '$hidden' => array('hidden', t('Hide this contact from others'), ($contact['hidden'] == 1), t('Replies/likes to your public posts may still be visible')), '$notify' => array('notify', t('Notification for new posts'), ($contact['notify_new_posts'] == 1), t('Send a notification of every new post of this contact')), '$fetch_further_information' => $fetch_further_information, @@ -653,7 +661,7 @@ function contacts_content(App $a) { '$url' => $url, '$profileurllabel' => t('Profile URL'), '$profileurl' => $contact['url'], - '$account_type' => account_type($contact), + '$account_type' => Contact::getAccountType($contact), '$location' => bbcode($contact["location"]), '$location_label' => t("Location:"), '$xmpp' => bbcode($contact["xmpp"]), @@ -878,7 +886,7 @@ function contacts_tab($a, $contact_id, $active_tab) { ); // Show this tab only if there is visible friend list - $x = count_all_friends(local_user(), $contact_id); + $x = GlobalContact::countAllFriends(local_user(), $contact_id); if ($x) $tabs[] = array('label'=>t('Contacts'), 'url' => "allfriends/".$contact_id, @@ -888,7 +896,7 @@ function contacts_tab($a, $contact_id, $active_tab) { 'accesskey' => 't'); // Show this tab only if there is visible common friend list - $common = count_common_friends(local_user(),$contact_id); + $common = GlobalContact::countCommonFriends(local_user(), $contact_id); if ($common) $tabs[] = array('label'=>t('Common Friends'), 'url' => "common/loc/".local_user()."/".$contact_id, @@ -916,7 +924,7 @@ function contact_posts($a, $contact_id) { if ($r) { $contact = $r[0]; $a->page['aside'] = ""; - profile_load($a, "", 0, get_contact_details_by_url($contact["url"])); + profile_load($a, "", 0, Contact::getDetailsByURL($contact["url"])); } else $profile = ""; @@ -924,7 +932,7 @@ function contact_posts($a, $contact_id) { $o .= $tab_str; - $o .= posts_from_contact_url($a, $contact["url"]); + $o .= Contact::getPostsFromUrl($contact["url"]); return $o; } @@ -959,14 +967,14 @@ function _contact_detail_for_template($rr){ return array( 'img_hover' => sprintf( t('Visit %s\'s profile [%s]'),$rr['name'],$rr['url']), 'edit_hover' => t('Edit contact'), - 'photo_menu' => contact_photo_menu($rr), + 'photo_menu' => Contact::photoMenu($rr), 'id' => $rr['id'], 'alt_text' => $alt_text, 'dir_icon' => $dir_icon, 'thumb' => proxy_url($rr['thumb'], false, PROXY_SIZE_THUMB), 'name' => htmlentities($rr['name']), 'username' => htmlentities($rr['name']), - 'account_type' => account_type($rr), + 'account_type' => Contact::getAccountType($rr), 'sparkle' => $sparkle, 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), 'url' => $url, diff --git a/mod/crepair.php b/mod/crepair.php index a73429e15..754078316 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -3,9 +3,10 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Object\Contact; -require_once("include/contact_selectors.php"); -require_once("mod/contacts.php"); +require_once 'include/contact_selectors.php'; +require_once 'mod/contacts.php'; function crepair_init(App $a) { if (! local_user()) { @@ -31,7 +32,7 @@ function crepair_init(App $a) { if($contact_id) { $a->data['contact'] = $r[0]; $contact = $r[0]; - profile_load($a, "", 0, get_contact_details_by_url($contact["url"])); + profile_load($a, "", 0, Contact::getDetailsByURL($contact["url"])); } } diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 98bdfbe15..47871debd 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -440,7 +440,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { if ((isset($new_relation) && $new_relation == CONTACT_IS_FRIEND)) { if (($contact) && ($contact['network'] === NETWORK_DIASPORA)) { - $ret = Diaspora::send_share($user[0],$r[0]); + $ret = Diaspora::sendShare($user[0],$r[0]); logger('share returns: ' . $ret); } @@ -498,7 +498,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $i = item_store($arr); if($i) - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); } } } @@ -800,7 +800,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $i = item_store($arr); if($i) - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); } } diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 15cda13ad..61be7966e 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Object\Contact; use Friendica\Protocol\DFRN; require_once 'include/items.php'; @@ -127,13 +128,8 @@ function dfrn_notify_post(App $a) { logger('dfrn_notify: data: ' . $data, LOGGER_DATA); if ($dissolve == 1) { - - /* - * Relationship is dissolved permanently - */ - - require_once('include/Contact.php'); - contact_remove($importer['id']); + // Relationship is dissolved permanently + Contact::remove($importer['id']); logger('relationship dissolved : ' . $importer['name'] . ' dissolved ' . $importer['username']); xml_status(0, 'relationship dissolved'); } @@ -179,7 +175,7 @@ function dfrn_notify_post(App $a) { *we got a key. old code send only the key, without RINO version. * we assume RINO 1 if key and no RINO version */ - $data = DFRN::aes_decrypt(hex2bin($data), $final_key); + $data = DFRN::aesDecrypt(hex2bin($data), $final_key); break; case 2: try { diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index 0e967301e..1e0724287 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -1,14 +1,16 @@ argc > 1) && ($dfrn_id == '') && !strstr($_SERVER["HTTP_USER_AGENT"], 'Friendica')) { $nickname = $a->argv[1]; header("Content-type: application/atom+xml"); - echo ostatus::feed($a, $nickname, $last_update, 10); + echo OStatus::feed($a, $nickname, $last_update, 10); killme(); } diff --git a/mod/directory.php b/mod/directory.php index b32a58b35..d8ad6aeab 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBM; +use Friendica\Object\Contact; function directory_init(App $a) { $a->set_pager_itemspage(60); @@ -142,12 +143,7 @@ function directory_content(App $a) { $about = ((x($profile,'about') == 1) ? t('About:') : False); - if($a->theme['template_engine'] === 'internal') { - $location_e = template_escape($location); - } - else { - $location_e = $location; - } + $location_e = $location; $photo_menu = array( 'profile' => array(t("View Profile"), zrl($profile_link)) @@ -161,7 +157,7 @@ function directory_content(App $a) { 'img_hover' => $rr['name'], 'name' => $rr['name'], 'details' => $details, - 'account_type' => account_type($rr), + 'account_type' => Contact::getAccountType($rr), 'profile' => $profile, 'location' => $location_e, 'tags' => $rr['pub_keywords'], diff --git a/mod/dirfind.php b/mod/dirfind.php index 5d65813e3..4ba122b56 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -1,14 +1,17 @@ tags = ""; $objresult->network = $user_data["network"]; - $contact = get_contact_details_by_url($user_data["url"], local_user()); + $contact = Contact::getDetailsByURL($user_data["url"], local_user()); $objresult->cid = $contact["cid"]; $j->results[] = $objresult; // Add the contact to the global contacts if it isn't already in our system if (($contact["cid"] == 0) && ($contact["zid"] == 0) && ($contact["gid"] == 0)) { - update_gcontact($user_data); + GlobalContact::update($user_data); } } elseif ($local) { @@ -142,11 +145,11 @@ function dirfind_content(App $a, $prefix = "") { $j->items_page = $perpage; $j->page = $a->pager['page']; foreach ($results AS $result) { - if (poco_alternate_ostatus_url($result["url"])) { + if (PortableContact::alternateOStatusUrl($result["url"])) { continue; } - $result = get_contact_details_by_url($result["url"], local_user(), $result); + $result = Contact::getDetailsByURL($result["url"], local_user(), $result); if ($result["name"] == "") { $urlparts = parse_url($result["url"]); @@ -166,7 +169,7 @@ function dirfind_content(App $a, $prefix = "") { } // Add found profiles from the global directory to the local directory - Worker::add(PRIORITY_LOW, 'discover_poco', "dirsearch", urlencode($search)); + Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search)); } else { $p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : ''); @@ -190,7 +193,7 @@ function dirfind_content(App $a, $prefix = "") { $alt_text = ""; - $contact_details = get_contact_details_by_url($jj->url, local_user()); + $contact_details = Contact::getDetailsByURL($jj->url, local_user()); $itemurl = (($contact_details["addr"] != "") ? $contact_details["addr"] : $jj->url); @@ -201,7 +204,7 @@ function dirfind_content(App $a, $prefix = "") { $contact = q("SELECT * FROM `contact` WHERE `id` = %d", intval($jj->cid)); if ($contact) { - $photo_menu = contact_photo_menu($contact[0]); + $photo_menu = Contact::photoMenu($contact[0]); $details = _contact_detail_for_template($contact[0]); $alt_text = $details['alt_text']; } else { @@ -231,7 +234,7 @@ function dirfind_content(App $a, $prefix = "") { 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' => account_type($contact_details), + 'account_type' => Contact::getAccountType($contact_details), 'network' => network_to_name($jj->network, $jj->url), 'id' => ++$id, ); diff --git a/mod/display.php b/mod/display.php index 570582343..e81e654ac 100644 --- a/mod/display.php +++ b/mod/display.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Object\Contact; use Friendica\Protocol\DFRN; function display_init(App $a) { @@ -114,8 +115,6 @@ function display_init(App $a) { function display_fetchauthor($a, $item) { - require_once("include/Contact.php"); - $profiledata = array(); $profiledata["uid"] = -1; $profiledata["nickname"] = $item["author-name"]; @@ -181,7 +180,7 @@ function display_fetchauthor($a, $item) { $profiledata["about"] = ""; } - $profiledata = get_contact_details_by_url($profiledata["url"], local_user(), $profiledata); + $profiledata = Contact::getDetailsByURL($profiledata["url"], local_user(), $profiledata); $profiledata["photo"] = System::removedBaseUrl($profiledata["photo"]); diff --git a/mod/events.php b/mod/events.php index b72c8f188..7a05274e2 100644 --- a/mod/events.php +++ b/mod/events.php @@ -180,7 +180,7 @@ function events_post(App $a) { $item_id = event_store($datarray); if (! $cid) { - Worker::add(PRIORITY_HIGH, "notifier", "event", $item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id); } goaway($_SESSION['return_url']); diff --git a/mod/fbrowser.php b/mod/fbrowser.php index ce90eaee9..9c0b7bb5a 100644 --- a/mod/fbrowser.php +++ b/mod/fbrowser.php @@ -69,13 +69,7 @@ function fbrowser_content(App $a) { $a = get_app(); $types = Photo::supportedTypes(); $ext = $types[$rr['type']]; - - if($a->theme['template_engine'] === 'internal') { - $filename_e = template_escape($rr['filename']); - } - else { - $filename_e = $rr['filename']; - } + $filename_e = $rr['filename']; // Take the largest picture that is smaller or equal 640 pixels $p = q("SELECT `scale` FROM `photo` WHERE `resource-id` = '%s' AND `height` <= 640 AND `width` <= 640 ORDER BY `resource-id`, `scale` LIMIT 1", @@ -117,14 +111,9 @@ function fbrowser_content(App $a) { $a = get_app(); list($m1,$m2) = explode("/",$rr['filetype']); $filetype = ( (file_exists("images/icons/$m1.png"))?$m1:"zip"); + $filename_e = $rr['filename']; - if ($a->theme['template_engine'] === 'internal') { - $filename_e = template_escape($rr['filename']); - } else { - $filename_e = $rr['filename']; - } - - return array( System::baseUrl() . '/attach/' . $rr['id'], $filename_e, System::baseUrl() . '/images/icons/16/' . $filetype . '.png'); + return array(System::baseUrl() . '/attach/' . $rr['id'], $filename_e, System::baseUrl() . '/images/icons/16/' . $filetype . '.png'); } $files = array_map("_map_files2", $files); diff --git a/mod/fetch.php b/mod/fetch.php index 8685504ff..68f6acc91 100644 --- a/mod/fetch.php +++ b/mod/fetch.php @@ -68,12 +68,12 @@ function fetch_init(App $a) } $user = $r[0]; - $status = Diaspora::build_status($item[0], $user); - $xml = Diaspora::build_post_xml($status["type"], $status["message"]); + $status = Diaspora::buildStatus($item[0], $user); + $xml = Diaspora::buildPostXml($status["type"], $status["message"]); // Send the envelope header("Content-Type: application/magic-envelope+xml; charset=utf-8"); - echo Diaspora::build_magic_envelope($xml, $user); + echo Diaspora::buildMagicEnvelope($xml, $user); killme(); } diff --git a/mod/follow.php b/mod/follow.php index 38ec83dc0..b5e73ca9a 100644 --- a/mod/follow.php +++ b/mod/follow.php @@ -4,9 +4,9 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Network\Probe; +use Friendica\Object\Contact; require_once 'include/follow.php'; -require_once 'include/Contact.php'; require_once 'include/contact_selectors.php'; function follow_post(App $a) { @@ -176,7 +176,7 @@ function follow_content(App $a) { )); $a->page['aside'] = ""; - profile_load($a, "", 0, get_contact_details_by_url($ret["url"])); + profile_load($a, "", 0, Contact::getDetailsByURL($ret["url"])); if ($gcontact_id <> 0) { $o .= replace_macros(get_markup_template('section_title.tpl'), @@ -184,7 +184,7 @@ function follow_content(App $a) { )); // Show last public posts - $o .= posts_from_contact_url($a, $ret["url"]); + $o .= Contact::getPostsFromUrl($ret["url"]); } return $o; diff --git a/mod/fsuggest.php b/mod/fsuggest.php index 124abd464..dd698db58 100644 --- a/mod/fsuggest.php +++ b/mod/fsuggest.php @@ -61,7 +61,7 @@ function fsuggest_post(App $a) { intval($fsuggest_id), intval(local_user()) ); - Worker::add(PRIORITY_HIGH, 'notifier', 'suggest', $fsuggest_id); + Worker::add(PRIORITY_HIGH, 'Notifier', 'suggest', $fsuggest_id); } info( t('Friend suggestion sent.') . EOL); @@ -74,38 +74,44 @@ function fsuggest_post(App $a) { -function fsuggest_content(App $a) { - - require_once('include/acl_selectors.php'); +function fsuggest_content(App $a) +{ + require_once 'include/acl_selectors.php'; if (! local_user()) { - notice( t('Permission denied.') . EOL); + notice(t('Permission denied.') . EOL); return; } - if($a->argc != 2) + if ($a->argc != 2) { return; + } $contact_id = intval($a->argv[1]); - $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", + $r = q( + "SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($contact_id), intval(local_user()) ); if (! DBM::is_result($r)) { - notice( t('Contact not found.') . EOL); + notice(t('Contact not found.') . EOL); return; } $contact = $r[0]; $o = '' . t('Suggest Friends') . '
'; - $o .= '' . sprintf( t('Suggest a friend for %s'), $contact['name']) . ''; + $o .= '' . sprintf(t('Suggest a friend for %s'), $contact['name']) . ''; $o .= '