1
1
Fork 0

Merge branch 'develop' into issue/missing-private-image-src

This commit is contained in:
Hypolite Petovan 2016-12-03 10:34:48 -05:00
commit 0f2c27e041
1094 changed files with 12617 additions and 157734 deletions

50
Vagrantfile vendored
View file

@ -1,31 +1,55 @@
server_ip = "192.168.22.10"
server_ip_trusty = "192.168.22.10"
server_ip_xenial = "192.168.22.11"
server_memory = "1024" # MB
server_timezone = "UTC"
public_folder = "/vagrant"
Vagrant.configure(2) do |config|
######################################################################
# Set server to Ubuntu 14.04
config.vm.box = "ubuntu/trusty64"
config.vm.define "trusty" do |trusty|
trusty.vm.box = "ubuntu/trusty64"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a hostname, don't forget to put it to the `hosts` file
# This will point to the server's default virtual host
# TO DO: Make this work with virtualhost along-side xip.io URL
config.vm.hostname = "friendica.dev"
# Create a hostname, don't forget to put it to the `hosts` file
# This will point to the server's default virtual host
# TO DO: Make this work with virtualhost along-side xip.io URL
trusty.vm.hostname = "friendica-trusty.dev"
# Create a static IP
config.vm.network :private_network, ip: server_ip
# Create a static IP
trusty.vm.network :private_network, ip: server_ip_trusty
end
######################################################################
# Set server to Ubuntu 16.04
config.vm.define "xenial" do |xenial|
xenial.vm.box = "boxcutter/ubuntu1604"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a hostname, don't forget to put it to the `hosts` file
# This will point to the server's default virtual host
# TO DO: Make this work with virtualhost along-side xip.io URL
xenial.vm.hostname = "friendica-xenial.dev"
# Create a static IP
xenial.vm.network :private_network, ip: server_ip_xenial
end
######################################################################
# Share a folder between host and guest
config.vm.synced_folder "./", "/vagrant/", owner: "www-data", group: "vagrant"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
config.vm.provider "virtualbox" do |vb|

View file

@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Asparagus');
define ( 'FRIENDICA_VERSION', '3.5.1-dev' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1208 );
define ( 'DB_UPDATE_VERSION', 1209 );
/**
* @brief Constant with a HTML line break.
@ -530,6 +530,7 @@ class App {
public $videoheight = 350;
public $force_max_items = 0;
public $theme_thread_allow = true;
public $theme_richtext_editor = true;
public $theme_events_in_profile = true;
/**
@ -609,6 +610,7 @@ class App {
$this->performance["markstart"] = microtime(true);
$this->callstack["database"] = array();
$this->callstack["database_write"] = array();
$this->callstack["network"] = array();
$this->callstack["file"] = array();
$this->callstack["rendering"] = array();
@ -1384,6 +1386,10 @@ class App {
function proc_run($args) {
if (!function_exists("proc_open")) {
return;
}
// Add the php path if it is a php call
if (count($args) && ($args[0] === 'php' OR !is_string($args[0]))) {
@ -2359,6 +2365,36 @@ function get_lockpath() {
return "";
}
/**
* @brief Returns the path where spool files are stored
*
* @return string Spool path
*/
function get_spoolpath() {
$spoolpath = get_config('system','spoolpath');
if (($spoolpath != "") AND is_dir($spoolpath) AND is_writable($spoolpath)) {
return($spoolpath);
}
$temppath = get_temppath();
if ($temppath != "") {
$spoolpath = $temppath."/spool";
if (!is_dir($spoolpath)) {
mkdir($spoolpath);
} elseif (!is_writable($spoolpath)) {
$spoolpath = $temppath;
}
if (is_dir($spoolpath) AND is_writable($spoolpath)) {
set_config("system", "spoolpath", $spoolpath);
return($spoolpath);
}
}
return "";
}
function get_temppath() {
$a = get_app();

View file

@ -1,19 +0,0 @@
ALTER TABLE `profile` DROP INDEX `pub_keywords` ;
ALTER TABLE `profile` DROP INDEX `prv_keywords` ;
ALTER TABLE `item` DROP INDEX `title` ;
ALTER TABLE `item` DROP INDEX `body` ;
ALTER TABLE `item` DROP INDEX `allow_cid` ;
ALTER TABLE `item` DROP INDEX `allow_gid` ;
ALTER TABLE `item` DROP INDEX `deny_cid` ;
ALTER TABLE `item` DROP INDEX `deny_gid` ;
ALTER TABLE `item` DROP INDEX `tag` ;
ALTER TABLE `item` DROP INDEX `file` ;
SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' engine=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM';

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 3.5.1-dev (Asparagus)
-- DB_UPDATE_VERSION 1205
-- DB_UPDATE_VERSION 1208
-- ------------------------------------------
@ -59,7 +59,8 @@ CREATE TABLE IF NOT EXISTS `cache` (
`expire_mode` int(11) NOT NULL DEFAULT 0,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY(`k`(191)),
INDEX `updated` (`updated`)
INDEX `updated` (`updated`),
INDEX `expire_mode_updated` (`expire_mode`,`updated`)
) DEFAULT CHARSET=utf8mb4;
--
@ -174,6 +175,7 @@ CREATE TABLE IF NOT EXISTS `contact` (
`ffi_keyword_blacklist` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `addr_uid` (`addr`,`uid`),
INDEX `nurl` (`nurl`)
) DEFAULT CHARSET=utf8mb4;
@ -201,7 +203,8 @@ CREATE TABLE IF NOT EXISTS `deliverq` (
`cmd` varchar(32) NOT NULL DEFAULT '',
`item` int(11) NOT NULL DEFAULT 0,
`contact` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
PRIMARY KEY(`id`),
UNIQUE INDEX `cmd_item_contact` (`cmd`,`item`,`contact`)
) DEFAULT CHARSET=utf8mb4;
--
@ -656,7 +659,7 @@ CREATE TABLE IF NOT EXISTS `notify` (
`verb` varchar(255) NOT NULL DEFAULT '',
`otype` varchar(16) NOT NULL DEFAULT '',
`name_cache` tinytext,
`msg_name` mediumtext,
`msg_cache` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
) DEFAULT CHARSET=utf8mb4;
@ -739,7 +742,9 @@ CREATE TABLE IF NOT EXISTS `photo` (
`deny_cid` mediumtext,
`deny_gid` mediumtext,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`),
INDEX `uid_contactid` (`uid`,`contact-id`),
INDEX `uid_profile` (`uid`,`profile`),
INDEX `uid_album_created` (`uid`,`album`,`created`),
INDEX `resource-id` (`resource-id`),
INDEX `guid` (`guid`)
) DEFAULT CHARSET=utf8mb4;
@ -894,6 +899,7 @@ CREATE TABLE IF NOT EXISTS `register` (
`uid` int(11) unsigned NOT NULL DEFAULT 0,
`password` varchar(255) NOT NULL DEFAULT '',
`language` varchar(16) NOT NULL DEFAULT '',
`note` text,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8mb4;
@ -974,6 +980,7 @@ CREATE TABLE IF NOT EXISTS `term` (
INDEX `type_term` (`type`,`term`),
INDEX `uid_otype_type_term_global_created` (`uid`,`otype`,`type`,`term`,`global`,`created`),
INDEX `otype_type_term_tid` (`otype`,`type`,`term`,`tid`),
INDEX `uid_otype_type_url` (`uid`,`otype`,`type`,`url`),
INDEX `guid` (`guid`)
) DEFAULT CHARSET=utf8mb4;

View file

@ -473,6 +473,10 @@ You can embed video, audio and more in a message.
<td>[vimeo]Vimeo video ID[/vimeo]</td>
<td>Vimeo player iframe embed.</td>
</tr>
<tr>
<td>[embed]URL[/embed]</td>
<td>Embed OEmbed rich content.</td>
</tr>
<tr>
<td>[iframe]URL[/iframe]</td>
<td>General embed, iframe size is limited by the theme size for video players.</td>

View file

@ -7,11 +7,11 @@ Friendica Documentation and Resources
* [Account Basics](help/Account-Basics)
* [New User Quick Start](help/Quick-Start-guide)
* [Creating posts](help/Text_editor)
* [BBCode tag reference](help/BBCode)
* [BBCode tag reference](help/BBCode)
* [Comment, sort and delete posts](help/Text_comment)
* [Profiles](help/Profiles)
* [Accesskey reference](help/Accesskeys)
* [Events](help/events)
* [Events](help/events)
* You and other users
* [Connectors](help/Connectors)
* [Making Friends](help/Making-Friends)
@ -31,9 +31,7 @@ Friendica Documentation and Resources
* [Settings & Admin Panel](help/Settings)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd)
* [Message Flow](help/Message-Flow)
* [Using SSL with Friendica](help/SSL)
* [Twitter/GNU Social API Functions](help/api)
* [Config values that can only be set in .htconfig.php](help/htconfig)
**Developer Manual**
@ -46,9 +44,11 @@ Friendica Documentation and Resources
* [Plugin Development](help/Plugins)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
* [Protocol Documentation](help/Protocol)
* [Database schema documantation](help/database)
* [Class Autoloading](help/autoloader)
* [Code - Reference(Doxygen generated - sets cookies)](doc/html/)
* [Twitter/GNU Social API Functions](help/api)
**External Resources**

View file

@ -4,7 +4,7 @@ Friendica Message Flow
This page documents some of the details of how messages get from one person to another in the Friendica network.
There are multiple paths, using multiple protocols and message formats.
Those attempting to understand these message flows should become familiar with (at the minimum) the [DFRN protocol document](http://dfrn.org/dfrn.pdf) and the message passing elements of the OStatus stack (salmon and Pubsubhubbub).
Those attempting to understand these message flows should become familiar with (at the minimum) the [DFRN protocol document](https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf) and the message passing elements of the OStatus stack (salmon and Pubsubhubbub).
Most message passing involves the file include/items.php, which has functions for several feed-related import/export activities.
@ -21,8 +21,8 @@ Push (pubsubhubbub) feeds arrive via mod/pubsub.php
DFRN-poll feed imports arrive via include/poller.php as a scheduled task, this implements the local side of the DFRN-poll protocol.
Scenario #1. Bob posts a public status message
---
### Scenario #1. Bob posts a public status message
This is a public message with no conversation members so no private transport is used.
There are two paths it can take - as a bbcode path to DFRN clients, and converted to HTML with the server's PuSH (pubsubhubbub) hubs notified.
When a PuSH hub is operational, dfrn-poll clients prefer to receive their information through the PuSH channel.
@ -30,31 +30,31 @@ They will fall back on a daily poll in case the hub has delivery issues (this is
If there is no specified hub or hubs, DFRN clients will poll at a configurable (per-contact) rate at up to 5-minute intervals.
Feeds retrieved via dfrn-poll are bbcode and may also contain private conversations which the poller has permissions to see.
Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network.
---
### Scenario #2. Jack replies to Bob's public message. Jack is on the Friendica/DFRN network.
Jack uses dfrn-notify to send a direct reply to Bob.
Bob then creates a feed of the conversation and sends it to everybody involved in the conversation using dfrn-notify.
PuSH hubs are notified that new content is available.
The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks).
Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network.
---
### Scenario #3. Mary replies to Bob's public message. Mary is on the Friendica/DFRN network.
Mary uses dfrn-notify to send a direct reply to Bob.
Bob then creates a feed of the conversation and sends it to everybody involved in the conversation (excluding himself, the conversation is now sent to both Jack and Mary).
Messages are sent using dfrn-notify.
Push hubs are also notified that new content is available.
The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks).
Scenario #4. William replies to Bob's public message. William is on the OStatus network.
---
### Scenario #4. William replies to Bob's public message. William is on the OStatus network.
William uses salmon to notify Bob of the reply.
Content is html embedded in salmon magic envelope.
Bob then creates a feed of the conversation and sends it to all Friendica participants involved in the conversation using dfrn-notify (excluding himself, the conversation is sent to both Jack and Mary).
Push hubs are notified that new content is available.
The hub or hubs will then retrieve the latest feed and transmit it to all hub subscribers (which may be on different networks).
Scenario #5. Bob posts a private message to Mary and Jack.
---
### Scenario #5. Bob posts a private message to Mary and Jack.
Message is delivered immediately to Mary and Jack using dfrn_notify.
Public hubs are not notified.
Requeueing is attempted in case of timeout.

40
doc/Protocol.md Normal file
View file

@ -0,0 +1,40 @@
Used Protocols
===============
Friendicas DFRN Protocol
---
* [Document with the DFRN specification](spec/dfrn2.pdf)
* [Schema of the contact request process](spec/dfrn2_contact_request.png)
* [Schema of the contact request confirmation](spec/dfrn2_contact_confirmation.png)
* [Description of the message flow](help/Message-Flow)
ActivityStreams
---
Friendica is using ActivityStreams in version 1.0 for its activities and object types.
Additional types are used for non standard activities.
* [Link to the specification](http://activitystrea.ms/head/activity-schema.html)
* [List of used ActivityStreams verbs and object types.](https://github.com/friendica/friendica/wiki/ActivityStreams)
Salmon
---
Salmon is used as a message exchange protocol for replies and mentions.
* [Link to the protocol summary](http://www.salmon-protocol.org/salmon-protocol-summary)
Portable Contacts
---
Portable Contacts is used for friends lists.
* [Link to the specification](https://web.archive.org/web/20160426223008/http://portablecontacts.net/draft-spec.html) (Link to archive.org)
pubsubhubbub
---
pubsubhubbub is used for OStatus.
* [Link to the specification](https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html)

View file

@ -5,7 +5,7 @@ Using SSL with Friendica
Disclaimer
---
**This document has been updated in November 2015.
**This document has been updated in November 2016.
SSL encryption is relevant for security.
This means that recommended settings change fast.
Keep your setup up to date and do not rely on this document being updated as fast as technologies change!**
@ -40,65 +40,26 @@ If your Friendica instance is running on a shared hosting platform, you should f
They have instructions for you on how to do it there.
You can always order a paid certificate with your provider.
They will either install it for you or provide an easy way to upload the certificate and the key via a web interface.
It might be worth asking if your provider would install a certificate you provide yourself, to save money.
If so, read on.
Getting a free StartSSL certificate
---
StartSSL is a certificate authority that issues certificates for free.
They are valid for a year and are sufficient for our purposes.
### Step 1: Create a client certificate
When you initially sign up with StartSSL, you receive a certificate that is installed in your browser.
You need it for the login on startssl.com, also when coming back to the site later.
It has nothing to do with the SSL certificate for your server.
### Step 2: Validate your email address and your domain
To continue you have to prove that you own the email address you specified and the domain that you want a certificate for.
Specify your email address, request a validation link via email from the "validations wizard".
Same procedure for the domain validation.
### Step 3: Request the certificate
Go to the "certificates wizard".
Choose the target web server.
When you are first prompted for a domain to certify, you need to enter your main domain, e.g. example.com.
In the next step, you will be able to specify a subdomain for Friendica, if needed.
Example: If you have friendica.example.com, you first enter example.com, then specify the subdomain friendica later.
If you know how to generate an openssl key and a certificate signing request (csr) yourself, do so.
Paste the csr into your browser to get it signed by StartSSL.
If you do not know how to generate a key and a csr, accept StartSSL's offer to generate it for you.
This means: StartSSL has the key to your encryption but it is better than no certificate at all.
Download your certificate from the website.
(Or in the second case: Download your certificate and your key.)
To install your certificate on a server, you need one or two extra files: sub.class1.server.ca.pem and ca.pem, delivered by startssl.com
Go to the "Tool box" section and download "Class 1 Intermediate Server CA" and "StartCom Root CA (PEM encoded)".
If you want to send your certificate to your hosting provider, they need the certificate, the key and probably at least the intermediate server CA.
To be sure, send those three and the ca.pem file.
With some providers, you have to send them your certificate.
They need the certificate, the key and the CA's intermediate certificate.
To be sure, send those three files.
**You should send them to your provider via an encrypted channel!**
If you run your own server, upload the files and check out the Mozilla wiki link below.
Let's encrypt
Own server
---
If you run your own server, the "Let's encrypt" initiative might become an interesting alternative.
Their offer is in public beta right now.
Check out [their website](https://letsencrypt.org/) for status updates.
If you run your own server, we recommend to check out the ["Let's Encrypt" initiative](https://letsencrypt.org/).
Not only do they offer free SSL certificates, but also a way to automate their renewal.
You need to install a client software on your server to use it.
Instructions for the official client are [here](https://certbot.eff.org/).
Depending on your needs, you might want to look at the [list of alternative letsencrypt clients](https://letsencrypt.org/docs/client-options/).
Web server settings
---
Visit the [Mozilla's wiki](https://wiki.mozilla.org/Security/Server_Side_TLS) for instructions on how to configure a secure webserver.
They provide recommendations for [different web servers](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations).
They provide recommendations for [different web servers](https://mozilla.github.io/server-side-tls/ssl-config-generator/).
Test your SSL settings
---

View file

@ -8,7 +8,11 @@ Getting started
[Vagrant](https://www.vagrantup.com/) is a virtualization solution for developers.
No need to setup up a webserver, database etc. before actually starting.
Vagrant creates a virtual machine (an Ubuntu 14.04) for you that you can just run inside VirtualBox and start to work directly on Friendica.
Vagrant creates a virtual machine for you that you can just run inside VirtualBox and start to work directly on Friendica.
You can choose between two different Ubuntu Linux versions:
1. Ubuntu Trusty (14.04) with PHP 5.5.9 and MySQL 5.5.53
2. Ubuntu Xenial (16.04) with PHP 7.0 and MySQL 5.7.16
What you need to do:
@ -16,21 +20,27 @@ What you need to do:
Please use an up-to-date vagrant version from https://www.vagrantup.com/downloads.html.
2. Git clone your Friendica repository.
Inside, you'll find a "Vagrantfile" and some scripts in the utils folder.
3. Run "vagrant up" from inside the friendica clone.
3. Choose the Ubuntu version you'll need und run "vagrant up <ubuntu-version>" from inside the friendica clone:
$> vagrant up trusty
$> vagrant up xenial
Be patient: When it runs for the first time, it downloads an Ubuntu Server image.
4. Run "vagrant ssh" to log into the virtual machine to log in to the VM.
5. Open 192.168.22.10 in a browser.
4. Run "vagrant ssh <ubuntu-version>" to log into the virtual machine to log in to the VM:
$> vagrant ssh trusty
$> vagrant ssh xenial
5. Open you test installation in a browser.
If you selected an Ubuntu Trusty go to 192.168.22.10.
If you started a Xenial machine go to 192.168.22.11.
The mysql database is called "friendica", the mysql user and password both are "root".
6. Work on Friendica's code in your git clone on your machine (not in the VM).
Your local working directory is set up as a shared directory with the VM (/vagrant).
7. Check the changes in your browser in the VM.
Debug via the "vagrant ssh" login.
Debug via the "vagrant ssh <ubuntu-version>" login.
Find the Friendica log file /vagrant/logfile.out.
8. Commit and push your changes directly back to Github.
If you want to stop vagrant after finishing your work, run the following command
$> vagrant halt
$> vagrant halt <ubuntu-version>
in the development directory.
@ -44,10 +54,3 @@ You will then have the following accounts to login:
* friendica2 and friendica3 are conntected. friendica4 and friendica5 are connected.
For further documentation of vagrant, please see [the vagrant*docs*](https://docs.vagrantup.com/v2/).
**Important notice:**
If you already had an Ubuntu 12.04 Vagrant VM, please run
$> vagrant destroy
before starting the new 14.04 machine.

View file

@ -26,32 +26,31 @@ Friendica - Dokumentation und Ressourcen
* [Bugs und Probleme](help/Bugs-and-Issues)
* [Häufig gestellte Fragen (FAQ)](help/FAQ)
**Technische Dokumentation**
**Dokumentation für Administratoren**
* [Installation](help/Install)
* [Konfigurationen & Admin-Panel](help/Settings)
* [Plugins](help/Plugins)
* [Konnektoren (Connectors) installieren (Twitter/GNU Social)](help/Installing-Connectors)
* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN)
* [Nachrichtenfluss](help/Message-Flow)
* [Betreibe deine Seite mit einem SSL-Zertifikat](help/SSL)
* [Entwickler](help/Developers)
* [Twitter/GNU Social API Functions](help/api) (EN)
* [Translation of Friendica](help/translations) (EN)
* [Konfigurationswerte, die nur in der .htconfig.php gesetzt werden können](help/htconfig) (EN)
**Entwickler Dokumentation**
**Dokumentation für Entwickler**
* [Where to get started?](help/Developers-Intro)
* [Entwickler](help/Developers)
* [Where to get started?](help/Developers-Intro) (EN)
* [Help on Github](help/Github)
* [Help on Vagrant](help/Vagrant)
* [How to translate Friendica](help/translations)
* [How to translate Friendica](help/translations) (EN)
* [Bugs and Issues](help/Bugs-and-Issues)
* [Plugin Development](help/Plugins)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
* [Protokoll Dokumentation](help/Protocol) (EN)
* [Datenbank-Schema](help/database)
* [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/)
* [Twitter/GNU Social API Functions](help/api) (EN)
**Externe Ressourcen**

View file

@ -6,7 +6,7 @@ Friendica Nachrichtenfluss
Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden.
Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen.
Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll (http://dfrn.org/dfrn.pdf) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub).
Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll ([Dokument mit den DFRN Spezifikationen](https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf)) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub).
Der Großteil der Nachrichtenverarbeitung nutzt die Datei include/items.php, welche Funktionen für verschiedene Feed-bezogene Import-/Exportaktivitäten liefert.
@ -24,7 +24,7 @@ PuSh-Feeds (pubsubhubbub) kommen via mod/pubsub.php an.
DFRN-poll Feed-Imports kommen via include/poller.php als geplanter Task an, das implementiert die lokale Bearbeitung (local side) des DFRN-Protokolls.
Szenario #1. Bob schreibt eine öffentliche Statusnachricht
### Szenario #1. Bob schreibt eine öffentliche Statusnachricht
Dies ist eine öffentliche Nachricht ohne begrenzte Nutzerfreigabe, so dass keine private Übertragung notwendig ist.
Es gibt zwei Wege, die genutzt werden können - als bbcode an DFRN-Clients oder als durch den Server konvertierten HTML-Code (mit PuSH; pubsubhubbub).
@ -33,13 +33,13 @@ Sie fallen zurück auf eine tägliche Abfrage, wenn der Hub Übertragungsschwier
Wenn kein spezifizierter Hub oder Hubs ausgewählt sind, werden DFRN-Clients in einer pro Kontakt konfigurierbaren Rate mit bis zu 5-Minuten-Intervallen abfragen.
Feeds, die via DFRN-Poll abgerufen werden, sind bbcode und können auch private Unterhaltungen enthalten, die vom Poller auf ihre Zugriffsrechte hin geprüft werden.
Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk.
### Szenario #2. Jack antwortet auf Bobs öffentliche Nachricht. Jack ist im Friendica/DFRN-Netzwerk.
Jack nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken.
Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist und dfrn-notify nutzt.
Die PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen diese an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können).
Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk.
### Szenario #3. Mary antwortet auf Bobs öffentliche Nachricht. Mary ist im Friendica/DFRN-Netzwerk.
Mary nutzt dfrn-notify, um eine direkte Antwort an Bob zu schicken.
Bob erstellt dann einen Feed der Unterhaltung und sendet diesen an jeden, der an der Unterhaltung beteiligt ist (mit Ausnahme von Bob selbst; die Unterhaltung wird nun an Jack und Mary geschickt).
@ -47,14 +47,14 @@ Die Nachrichten werden mit dfrn-notify übertragen.
PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist.
Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können).
Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk.
### Szenario #4. William antwortet auf Bobs öffentliche Nachricht. William ist in einem OStatus-Netzwerk.
William nutzt salmon, um Bob über seine Antwort zu benachrichtigen.
Der Inhalt ist HTML-Code, der in das Salmon Magic Envelope eingebettet ist.
Bob erstellt dann einen Feed der Unterhaltung und sendet es an alle Friendica-Nutzer, die an der Unterhaltung beteiligt sind und dfrn-notify nutzen (mit Ausnahme von William selbst; die Unterhaltung wird an Jack und Mary weitergeleitet).
PuSH-Hubs werden darüber informiert, dass neuer Inhalt verfügbar ist. Der/die Hub/s erhalten dann die neuesten Feeds und übertragen sie an alle Hub-Teilnehmer (die auch zu verschiedenen Netzwerken gehören können).
Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack.
### Szenario #5. Bob schreibt eine private Nachricht an Mary und Jack.
Die Nachricht wird sofort an Mary und Jack mit Hilfe von dfrn_notify geschickt.
Öffentliche Hubs werden nicht benachrichtigt.

View file

@ -5,7 +5,7 @@ Friendica mit SSL nutzen
Disclaimer
---
**Dieses Dokument wurde im November 2015 aktualisiert.
**Dieses Dokument wurde im November 2016 aktualisiert.
SSL-Verschlüsselung ist sicherheitskritisch.
Das bedeutet, dass sich die empfohlenen Einstellungen schnell verändern.
Halte deine Installation auf dem aktuellen Stand und verlasse dich nicht darauf, dass dieses Dokument genau so schnell aktualisiert wird, wie sich Technologien verändern!**
@ -45,55 +45,15 @@ Sie installieren es für dich oder haben in der Weboberfläche eine einfache Upl
Um Geld zu sparen, kann es sich lohnen, dort auch nachzufragen, ob sie ein anderes Zertifikat, das du selbst beschaffst, für dich installieren würden.
Wenn ja, dann lies weiter.
Ein kostenloses StartSSL-Zertifikat besorgen
---
StartSSL ist eine Zertifizierungsstelle, die kostenlose Zertifikate ausstellt.
Sie sind für ein Jahr gültig und genügen für unsere Zwecke.
### Schritt 1: Client-Zertifikat erstellen
Wenn du dich erstmalig bei StartSSL anmeldest, erhältst du ein Zertifikat, das in deinem Browser installiert wird.
Du brauchst es, um dich bei StartSSL einzuloggen, auch wenn du später wiederkommst.
Dieses Client-Zertifikat hat nichts mit dem SSL-Zertifikat für deinen Server zu tun.
### Schritt 2: Email-Adresse und Domain validieren
Um fortzufahren musst du beweisen, dass du die Email-Adresse, die du angegeben hast, und die Domain, für die du das Zertifikat möchtest, besitzt.
Gehe in den "Validation wizard" und fordere einen Bestätigungslink per Mail an.
Dasselbe machst du auch für die Validierung der Domain.
### Schritt 3: Das Zertifikat bestellen
Gehe in den "Certificate wizard".
Wähle das Target Webserver.
Bei der ersten Abfrage der Domain gibst du deine Hauptdomain an.
Im nächsten Schritt kannst du eine Subdomain hinzufügen.
Ein Beispiel: Wenn die Adresse der Friendica-Instanz friendica.beispiel.net lautet, gibst du zuerst beispiel.net an und danach friendica.
Wenn du weißt, wie man einen openssl-Schlüssel und einen Certificate Signing Request (CSR) erstellt, tu das.
Kopiere den CSR in den Browser, um ihn von StartSSL signiert zu bekommen.
Wenn du nicht weißt, wie man Schlüssel und CSR erzeugt, nimm das Angebot von StartSSL an, beides für dich zu generieren.
Das bedeutet: StartSSL hat den Schlüssel zu deiner SSL-Verschlüsselung, aber das ist immer noch besser als gar kein Zertifikat.
Lade dein Zertifikat von der Website herunter.
(Oder im zweiten Fall: Lade Zertifikat und Schlüssel herunter.)
Um dein Zertifikat auf einem Webserver zu installieren, brauchst du noch ein oder zwei andere Dateien: sub.class1.server.ca.pem und ca.pem, auch von StartSSL.
Gehe in die Rubrik "Tool box" und lade "Class 1 Intermediate Server CA" und "StartCom Root CA (PEM encoded)" herunter.
Wenn du dein Zertifikat zu deinem Hosting-Provider schicken möchtest, brauchen Sie mindestens Zertifikat und Schlüssel.
Schick zur Sicherheit alle vier Dateien hin.
**Du solltest sie auf einem verschlüsselten Weg hinschicken!**
Wenn du deinen eigenen Server betreibst, lade die Dateien hoch und besuche das Mozilla-Wiki (Link unten).
Let's encrypt
---
Wenn du einen eigenen Server betreibst und den Nameserver kontrollierst, könnte auch die Initiative "Let's encrypt" interessant für dich werden.
Momentan ist deren Angebot noch nicht fertig.
Auf der [Website](https://letsencrypt.org/) kannst du dich über den Stand informieren.
Sie bietet nicht nur freie SSL Zertifikate sondern auch einen automatisierten Prozess zum Erneuern der Zertifikate.
Um letsencrypt Zertifikate verwenden zu können, musst du dir einen Client auf deinem Server installieren.
Eine Anleitung zum offiziellen Client findet du [hier](https://certbot.eff.org/).
Falls du dir andere Clients anschauen willst, kannst du einen Blick in diese [Liste von alternativen letsencrypt Clients](https://letsencrypt.org/docs/client-options/).
Webserver-Einstellungen
---

View file

@ -29,6 +29,8 @@ Example: To set the directory value please add this line to your .htconfig.php:
* disable_email_validation (Boolean) - Disables the check if a mail address is in a valid format and can be resolved via DNS.
* disable_url_validation (Boolean) - Disables the DNS lookup of an URL.
* event_input_format - Default value is "ymd".
* frontend_worker (Boolean) - Activates the frontend worker which acts as a replacement for running the poller via the command line.
* frontend_worker_timeout - Value in minutes after we think that a frontend task was killed by the webserver. Default value is 10.
* ignore_cache (Boolean) - For development only. Disables the item cache.
* like_no_comment (Boolean) - Don't update the "commented" value of an item when it is liked.
* local_block (Boolean) - Used in conjunction with "block_public".

View file

@ -22,6 +22,7 @@ function user_remove($uid) {
$r[0]['nickname']
);
/// @todo Should be done in a background job since this likely will run into a time out
// don't delete yet, will be done later when contacts have deleted my stuff
// q("DELETE FROM `contact` WHERE `uid` = %d", intval($uid));
q("DELETE FROM `gcign` WHERE `uid` = %d", intval($uid));
@ -74,25 +75,10 @@ function contact_remove($id) {
return;
}
q("DELETE FROM `contact` WHERE `id` = %d",
intval($id)
);
q("DELETE FROM `item` WHERE `contact-id` = %d ",
intval($id)
);
q("DELETE FROM `photo` WHERE `contact-id` = %d ",
intval($id)
);
q("DELETE FROM `mail` WHERE `contact-id` = %d ",
intval($id)
);
q("DELETE FROM `event` WHERE `cid` = %d ",
intval($id)
);
q("DELETE FROM `queue` WHERE `cid` = %d ",
intval($id)
);
q("DELETE FROM `contact` WHERE `id` = %d", intval($id));
// Delete the rest in the background
proc_run(PRIORITY_LOW, 'include/remove_contact.php', $id);
}
@ -145,7 +131,6 @@ function terminate_friendship($user,$self,$contact) {
// 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.
if(! function_exists('mark_for_death')) {
function mark_for_death($contact) {
if($contact['archive'])
@ -156,14 +141,24 @@ function mark_for_death($contact) {
dbesc(datetime_convert()),
intval($contact['id'])
);
}
else {
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)) {
@ -171,26 +166,45 @@ function mark_for_death($contact) {
// 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",
q("UPDATE `contact` SET `archive` = 1 WHERE `id` = %d",
intval($contact['id'])
);
q("UPDATE `item` SET `private` = 2 WHERE `contact-id` = %d AND `uid` = %d", intval($contact['id']), intval($contact['uid']));
//contact_remove($contact['id']);
if ($contact['url'] != '') {
q("UPDATE `contact` SET `archive` = 1 WHERE `nurl` = '%s'",
dbesc(normalise_link($contact['url']))
);
}
}
}
}}
}
if(! function_exists('unmark_for_death')) {
function unmark_for_death($contact) {
$r = q("SELECT `term-date` FROM `contact` WHERE `id` = %d AND `term-date` > '%s'",
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.
q("UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d",
dbesc('0000-00-00 00:00:00'),
intval($contact['id'])
);
}}
if ($contact['url'] != '') {
q("UPDATE `contact` SET `term-date` = '%s' WHERE `nurl` = '%s'",
dbesc('0000-00-00 00:00:00'),
dbesc(normalise_link($contact['url']))
);
}
}
/**
* @brief Get contact data for a given profile link

552
include/ParseUrl.php Normal file
View file

@ -0,0 +1,552 @@
<?php
/**
* @file include/ParseUrl.php
* @brief Get informations about a given URL
*/
namespace Friendica;
use \Friendica\Core\Config;
require_once("include/network.php");
require_once("include/Photo.php");
require_once("include/oembed.php");
require_once("include/xml.php");
/**
* @brief Class with methods for extracting certain content from an url
*/
class ParseUrl {
/**
* @brief Search for chached embeddable data of an url otherwise fetch it
*
* @param type $url The url of the page which should be scraped
* @param type $no_guessing If true the parse doens't search for
* preview pictures
* @param type $do_oembed The false option is used by the function fetch_oembed()
* to avoid endless loops
*
* @return array which contains needed data for embedding
* string 'url' => The url of the parsed page
* string 'type' => Content type
* string 'title' => The title of the content
* string 'text' => The description for the content
* string 'image' => A preview image of the content (only available
* if $no_geuessing = false
* array'images' = Array of preview pictures
* string 'keywords' => The tags which belong to the content
*
* @see ParseUrl::getSiteinfo() for more information about scraping
* embeddable content
*/
public static function getSiteinfoCached($url, $no_guessing = false, $do_oembed = true) {
if ($url == "") {
return false;
}
$r = q("SELECT * FROM `parsed_url` WHERE `url` = '%s' AND `guessing` = %d AND `oembed` = %d",
dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed));
if ($r) {
$data = $r[0]["content"];
}
if (!is_null($data)) {
$data = unserialize($data);
return $data;
}
$data = self::getSiteinfo($url, $no_guessing, $do_oembed);
q("INSERT INTO `parsed_url` (`url`, `guessing`, `oembed`, `content`, `created`) VALUES ('%s', %d, %d, '%s', '%s')
ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'",
dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed),
dbesc(serialize($data)), dbesc(datetime_convert()),
dbesc(serialize($data)), dbesc(datetime_convert()));
return $data;
}
/**
* @brief Parse a page for embeddable content information
*
* This method parses to url for meta data which can be used to embed
* the content. If available it prioritizes Open Graph meta tags.
* If this is not available it uses the twitter cards meta tags.
* As fallback it uses standard html elements with meta informations
* like \<title\>Awesome Title\</title\> or
* \<meta name="description" content="An awesome description"\>
*
* @param type $url The url of the page which should be scraped
* @param type $no_guessing If true the parse doens't search for
* preview pictures
* @param type $do_oembed The false option is used by the function fetch_oembed()
* to avoid endless loops
* @param type $count Internal counter to avoid endless loops
*
* @return array which contains needed data for embedding
* string 'url' => The url of the parsed page
* string 'type' => Content type
* string 'title' => The title of the content
* string 'text' => The description for the content
* string 'image' => A preview image of the content (only available
* if $no_geuessing = false
* array'images' = Array of preview pictures
* string 'keywords' => The tags which belong to the content
*
* @todo https://developers.google.com/+/plugins/snippet/
* @verbatim
* <meta itemprop="name" content="Awesome title">
* <meta itemprop="description" content="An awesome description">
* <meta itemprop="image" content="http://maple.libertreeproject.org/images/tree-icon.png">
*
* <body itemscope itemtype="http://schema.org/Product">
* <h1 itemprop="name">Shiny Trinket</h1>
* <img itemprop="image" src="{image-url}" />
* <p itemprop="description">Shiny trinkets are shiny.</p>
* </body>
* @endverbatim
*/
public static function getSiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
$a = get_app();
$siteinfo = array();
// Check if the URL does contain a scheme
$scheme = parse_url($url, PHP_URL_SCHEME);
if ($scheme == "") {
$url = "http://".trim($url, "/");
}
if ($count > 10) {
logger("parseurl_getsiteinfo: Endless loop detected for ".$url, LOGGER_DEBUG);
return($siteinfo);
}
$url = trim($url, "'");
$url = trim($url, '"');
$url = original_url($url);
$siteinfo["url"] = $url;
$siteinfo["type"] = "link";
$check_cert = Config::get("system", "verifyssl");
$stamp1 = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
$header = curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info["http_code"];
curl_close($ch);
$a->save_timestamp($stamp1, "network");
if ((($curl_info["http_code"] == "301") || ($curl_info["http_code"] == "302") || ($curl_info["http_code"] == "303") || ($curl_info["http_code"] == "307"))
&& (($curl_info["redirect_url"] != "") || ($curl_info["location"] != ""))) {
if ($curl_info["redirect_url"] != "") {
$siteinfo = self::getSiteinfo($curl_info["redirect_url"], $no_guessing, $do_oembed, ++$count);
} else {
$siteinfo = self::getSiteinfo($curl_info["location"], $no_guessing, $do_oembed, ++$count);
}
return($siteinfo);
}
// If the file is too large then exit
if ($curl_info["download_content_length"] > 1000000) {
return($siteinfo);
}
// If it isn't a HTML file then exit
if (($curl_info["content_type"] != "") && !strstr(strtolower($curl_info["content_type"]), "html")) {
return($siteinfo);
}
if ($do_oembed) {
$oembed_data = oembed_fetch_url($url);
if (!in_array($oembed_data->type, array("error", "rich"))) {
$siteinfo["type"] = $oembed_data->type;
}
if (($oembed_data->type == "link") && ($siteinfo["type"] != "photo")) {
if (isset($oembed_data->title)) {
$siteinfo["title"] = $oembed_data->title;
}
if (isset($oembed_data->description)) {
$siteinfo["text"] = trim($oembed_data->description);
}
if (isset($oembed_data->thumbnail_url)) {
$siteinfo["image"] = $oembed_data->thumbnail_url;
}
}
}
$stamp1 = microtime(true);
// Now fetch the body as well
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
$header = curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info["http_code"];
curl_close($ch);
$a->save_timestamp($stamp1, "network");
// Fetch the first mentioned charset. Can be in body or header
$charset = "";
if (preg_match('/charset=(.*?)['."'".'"\s\n]/', $header, $matches)) {
$charset = trim(trim(trim(array_pop($matches)), ';,'));
}
if ($charset == "") {
$charset = "utf-8";
}
$pos = strpos($header, "\r\n\r\n");
if ($pos) {
$body = trim(substr($header, $pos));
} else {
$body = $header;
}
if (($charset != "") && (strtoupper($charset) != "UTF-8")) {
logger("parseurl_getsiteinfo: detected charset ".$charset, LOGGER_DEBUG);
//$body = mb_convert_encoding($body, "UTF-8", $charset);
$body = iconv($charset, "UTF-8//TRANSLIT", $body);
}
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new \DOMDocument();
@$doc->loadHTML($body);
\xml::deleteNode($doc, "style");
\xml::deleteNode($doc, "script");
\xml::deleteNode($doc, "option");
\xml::deleteNode($doc, "h1");
\xml::deleteNode($doc, "h2");
\xml::deleteNode($doc, "h3");
\xml::deleteNode($doc, "h4");
\xml::deleteNode($doc, "h5");
\xml::deleteNode($doc, "h6");
\xml::deleteNode($doc, "ol");
\xml::deleteNode($doc, "ul");
$xpath = new \DomXPath($doc);
$list = $xpath->query("//meta[@content]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
if (@$attr["http-equiv"] == "refresh") {
$path = $attr["content"];
$pathinfo = explode(";", $path);
$content = "";
foreach ($pathinfo as $value) {
if (substr(strtolower($value), 0, 4) == "url=") {
$content = substr($value, 4);
}
}
if ($content != "") {
$siteinfo = self::getSiteinfo($content, $no_guessing, $do_oembed, ++$count);
return($siteinfo);
}
}
}
$list = $xpath->query("//title");
if ($list->length > 0) {
$siteinfo["title"] = $list->item(0)->nodeValue;
}
//$list = $xpath->query("head/meta[@name]");
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
$attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
if ($attr["content"] != "") {
switch (strtolower($attr["name"])) {
case "fulltitle":
$siteinfo["title"] = $attr["content"];
break;
case "description":
$siteinfo["text"] = $attr["content"];
break;
case "thumbnail":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:image":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:image:src":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:card":
if (($siteinfo["type"] == "") || ($attr["content"] == "photo")) {
$siteinfo["type"] = $attr["content"];
}
break;
case "twitter:description":
$siteinfo["text"] = $attr["content"];
break;
case "twitter:title":
$siteinfo["title"] = $attr["content"];
break;
case "dc.title":
$siteinfo["title"] = $attr["content"];
break;
case "dc.description":
$siteinfo["text"] = $attr["content"];
break;
case "keywords":
$keywords = explode(",", $attr["content"]);
break;
case "news_keywords":
$keywords = explode(",", $attr["content"]);
break;
}
}
if ($siteinfo["type"] == "summary") {
$siteinfo["type"] = "link";
}
}
if (isset($keywords)) {
$siteinfo["keywords"] = array();
foreach ($keywords as $keyword) {
if (!in_array(trim($keyword), $siteinfo["keywords"])) {
$siteinfo["keywords"][] = trim($keyword);
}
}
}
//$list = $xpath->query("head/meta[@property]");
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
$attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
if ($attr["content"] != "") {
switch (strtolower($attr["property"])) {
case "og:image":
$siteinfo["image"] = $attr["content"];
break;
case "og:title":
$siteinfo["title"] = $attr["content"];
break;
case "og:description":
$siteinfo["text"] = $attr["content"];
break;
}
}
}
if ((@$siteinfo["image"] == "") && !$no_guessing) {
$list = $xpath->query("//img[@src]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length) {
foreach ($node->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
$src = self::completeUrl($attr["src"], $url);
$photodata = get_photo_info($src);
if (($photodata) && ($photodata[0] > 150) && ($photodata[1] > 150)) {
if ($photodata[0] > 300) {
$photodata[1] = round($photodata[1] * (300 / $photodata[0]));
$photodata[0] = 300;
}
if ($photodata[1] > 300) {
$photodata[0] = round($photodata[0] * (300 / $photodata[1]));
$photodata[1] = 300;
}
$siteinfo["images"][] = array("src" => $src,
"width" => $photodata[0],
"height" => $photodata[1]);
}
}
} elseif ($siteinfo["image"] != "") {
$src = self::completeUrl($siteinfo["image"], $url);
unset($siteinfo["image"]);
$photodata = get_photo_info($src);
if (($photodata) && ($photodata[0] > 10) && ($photodata[1] > 10)) {
$siteinfo["images"][] = array("src" => $src,
"width" => $photodata[0],
"height" => $photodata[1]);
}
}
if ((@$siteinfo["text"] == "") && (@$siteinfo["title"] != "") && !$no_guessing) {
$text = "";
$list = $xpath->query("//div[@class='article']");
foreach ($list as $node) {
if (strlen($node->nodeValue) > 40) {
$text .= " ".trim($node->nodeValue);
}
}
if ($text == "") {
$list = $xpath->query("//div[@class='content']");
foreach ($list as $node) {
if (strlen($node->nodeValue) > 40) {
$text .= " ".trim($node->nodeValue);
}
}
}
// If none text was found then take the paragraph content
if ($text == "") {
$list = $xpath->query("//p");
foreach ($list as $node) {
if (strlen($node->nodeValue) > 40) {
$text .= " ".trim($node->nodeValue);
}
}
}
if ($text != "") {
$text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
while (strpos($text, " ")) {
$text = trim(str_replace(" ", " ", $text));
}
$siteinfo["text"] = trim(html_entity_decode(substr($text, 0, 350), ENT_QUOTES, "UTF-8").'...');
}
}
logger("parseurl_getsiteinfo: Siteinfo for ".$url." ".print_r($siteinfo, true), LOGGER_DEBUG);
call_hooks("getsiteinfo", $siteinfo);
return($siteinfo);
}
/**
* @brief Convert tags from CSV to an array
*
* @param string $string Tags
* @return array with formatted Hashtags
*/
public static function convertTagsToArray($string) {
$arr_tags = str_getcsv($string);
if (count($arr_tags)) {
// add the # sign to every tag
array_walk($arr_tags, array("self", "arrAddHashes"));
return $arr_tags;
}
}
/**
* @brief Add a hasht sign to a string
*
* This method is used as callback function
*
* @param string $tag The pure tag name
* @param int $k Counter for internal use
*/
private static function arrAddHashes(&$tag, $k) {
$tag = "#" . $tag;
}
/**
* @brief Add a scheme to an url
*
* The src attribute of some html elements (e.g. images)
* can miss the scheme so we need to add the correct
* scheme
*
* @param string $url The url which possibly does have
* a missing scheme (a link to an image)
* @param string $scheme The url with a correct scheme
* (e.g. the url from the webpage which does contain the image)
*
* @return string The url with a scheme
*/
private static function completeUrl($url, $scheme) {
$urlarr = parse_url($url);
// If the url does allready have an scheme
// we can stop the process here
if (isset($urlarr["scheme"])) {
return($url);
}
$schemearr = parse_url($scheme);
$complete = $schemearr["scheme"]."://".$schemearr["host"];
if (@$schemearr["port"] != "") {
$complete .= ":".$schemearr["port"];
}
if (strpos($urlarr["path"],"/") !== 0) {
$complete .= "/";
}
$complete .= $urlarr["path"];
if (@$urlarr["query"] != "") {
$complete .= "?".$urlarr["query"];
}
if (@$urlarr["fragment"] != "") {
$complete .= "#".$urlarr["fragment"];
}
return($complete);
}
}

View file

@ -623,7 +623,7 @@
// count friends
$r = q("SELECT count(*) as `count` FROM `contact`
WHERE `uid` = %d AND `rel` IN ( %d, %d )
AND `self`=0 AND `blocked`=0 AND `pending`=0 AND `hidden`=0",
AND `self`=0 AND NOT `blocked` AND `hidden`=0",
intval($uinfo[0]['uid']),
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND)
@ -632,7 +632,7 @@
$r = q("SELECT count(*) as `count` FROM `contact`
WHERE `uid` = %d AND `rel` IN ( %d, %d )
AND `self`=0 AND `blocked`=0 AND `pending`=0 AND `hidden`=0",
AND `self`=0 AND NOT `blocked` AND `hidden`=0",
intval($uinfo[0]['uid']),
intval(CONTACT_IS_FOLLOWER),
intval(CONTACT_IS_FRIEND)
@ -1399,7 +1399,7 @@
`contact`.`id` AS `cid`
FROM `item`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`uid` = %d AND `verb` = '%s'
AND `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
$sql_extra
@ -1476,7 +1476,7 @@
`user`.`nickname`, `user`.`hidewall`
FROM `item`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
STRAIGHT_JOIN `user` ON `user`.`uid` = `item`.`uid`
AND NOT `user`.`hidewall`
WHERE `verb` = '%s' AND `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
@ -1543,7 +1543,7 @@
`contact`.`id` AS `cid`
FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
AND `item`.`uid` = %d AND `item`.`verb` = '%s'
$sql_extra",
@ -1619,7 +1619,7 @@
`contact`.`id` AS `cid`
FROM `item`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`parent` = %d AND `item`.`visible`
AND NOT `item`.`moderated` AND NOT `item`.`deleted`
AND `item`.`uid` = %d AND `item`.`verb` = '%s'
@ -1673,7 +1673,7 @@
`contact`.`id` AS `cid`
FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
AND NOT `item`.`private` AND `item`.`allow_cid` = '' AND `item`.`allow`.`gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
@ -1792,7 +1792,7 @@
`contact`.`id` AS `cid`
FROM `item` FORCE INDEX (`uid_id`)
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`uid` = %d AND `verb` = '%s'
AND NOT (`item`.`author-link` IN ('https://%s', 'http://%s'))
AND `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
@ -1866,7 +1866,7 @@
`contact`.`id` AS `cid`
FROM `item` FORCE INDEX (`uid_contactid_id`)
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`uid` = %d AND `verb` = '%s'
AND `item`.`contact-id` = %d
AND `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
@ -2002,7 +2002,7 @@
AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
AND `item`.`starred` = 1
AND `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
$sql_extra
AND `item`.`id`>%d
ORDER BY `item`.`id` DESC LIMIT %d ,%d ",
@ -2436,18 +2436,18 @@
'religion' => $profile['religion'],
'public_keywords' => $profile['pub_keywords'],
'private_keywords' => $profile['prv_keywords'],
'likes' => bbcode(api_clean_plain_items($profile['likes']), false, false, 2, true),
'dislikes' => bbcode(api_clean_plain_items($profile['dislikes']), false, false, 2, true),
'about' => bbcode(api_clean_plain_items($profile['about']), false, false, 2, true),
'music' => bbcode(api_clean_plain_items($profile['music']), false, false, 2, true),
'book' => bbcode(api_clean_plain_items($profile['book']), false, false, 2, true),
'tv' => bbcode(api_clean_plain_items($profile['tv']), false, false, 2, true),
'film' => bbcode(api_clean_plain_items($profile['film']), false, false, 2, true),
'interest' => bbcode(api_clean_plain_items($profile['interest']), false, false, 2, true),
'romance' => bbcode(api_clean_plain_items($profile['romance']), false, false, 2, true),
'work' => bbcode(api_clean_plain_items($profile['work']), false, false, 2, true),
'education' => bbcode(api_clean_plain_items($profile['education']), false, false, 2, true),
'social_networks' => bbcode(api_clean_plain_items($profile['contact']), false, false, 2, true),
'likes' => bbcode(api_clean_plain_items($profile['likes']), false, false, 2, false),
'dislikes' => bbcode(api_clean_plain_items($profile['dislikes']), false, false, 2, false),
'about' => bbcode(api_clean_plain_items($profile['about']), false, false, 2, false),
'music' => bbcode(api_clean_plain_items($profile['music']), false, false, 2, false),
'book' => bbcode(api_clean_plain_items($profile['book']), false, false, 2, false),
'tv' => bbcode(api_clean_plain_items($profile['tv']), false, false, 2, false),
'film' => bbcode(api_clean_plain_items($profile['film']), false, false, 2, false),
'interest' => bbcode(api_clean_plain_items($profile['interest']), false, false, 2, false),
'romance' => bbcode(api_clean_plain_items($profile['romance']), false, false, 2, false),
'work' => bbcode(api_clean_plain_items($profile['work']), false, false, 2, false),
'education' => bbcode(api_clean_plain_items($profile['education']), false, false, 2, false),
'social_networks' => bbcode(api_clean_plain_items($profile['contact']), false, false, 2, false),
'homepage' => $profile['homepage'],
'users' => null);
return $profile;
@ -2648,7 +2648,7 @@
if ($user_info['self'] == 0)
$sql_extra = " AND false ";
$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 $sql_extra",
$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND NOT `self` AND (NOT `blocked` OR `pending`) $sql_extra",
intval(api_user())
);

View file

@ -84,9 +84,14 @@ class Cache {
$memcache = self::memcache();
if (is_object($memcache)) {
// We fetch with the hostname as key to avoid problems with other applications
$value = $memcache->get(get_app()->get_hostname().":".$key);
if (!is_bool($value)) {
return unserialize($value);
$cached = $memcache->get(get_app()->get_hostname().":".$key);
$value = @unserialize($cached);
// Only return a value if the serialized value is valid.
// We also check if the db entry is a serialized
// boolean 'false' value (which we want to return).
if ($cached === serialize(false) || $value !== false) {
return $value;
}
return null;
@ -100,7 +105,15 @@ class Cache {
);
if (dbm::is_result($r)) {
return unserialize($r[0]['v']);
$cached = $r[0]['v'];
$value = @unserialize($cached);
// Only return a value if the serialized value is valid.
// We also check if the db entry is a serialized
// boolean 'false' value (which we want to return).
if ($cached === serialize(false) || $value !== false) {
return $value;
}
}
return null;

View file

@ -439,7 +439,7 @@ These Fields are not added below (yet). They are here to for bug search.
function item_joins() {
return "STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND
NOT `contact`.`blocked` AND NOT `contact`.`pending`
(NOT `contact`.`blocked` OR `contact`.`pending`)
LEFT JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
LEFT JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id`";
}
@ -1064,6 +1064,9 @@ function builtin_activity_puller($item, &$conv_responses) {
else
$conv_responses[$mode][$item['thr-parent']] ++;
if((local_user()) && (local_user() == $item['uid']) && ($item['self']))
$conv_responses[$mode][$item['thr-parent'] . '-self'] = 1;
$conv_responses[$mode][$item['thr-parent'] . '-l'][] = $url;
// there can only be one activity verb per item so if we found anything, we can stop looking
@ -1443,6 +1446,7 @@ function get_responses($conv_responses,$response_verbs,$ob,$item) {
$ret[$v] = array();
$ret[$v]['count'] = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri']] : '');
$ret[$v]['list'] = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri'] . '-l'] : '');
$ret[$v]['self'] = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri'] . '-self'] : '0');
if(count($ret[$v]['list']) > MAX_LIKERS) {
$ret[$v]['list_part'] = array_slice($ret[$v]['list'], 0, MAX_LIKERS);
array_push($ret[$v]['list_part'], '<a href="#" data-toggle="modal" data-target="#' . $v . 'Modal-'

View file

@ -325,7 +325,7 @@ function cron_poll_contacts($argc, $argv) {
logger("Polling ".$contact["network"]." ".$contact["id"]." ".$contact["nick"]." ".$contact["name"]);
if ($contact["remote_self"]) {
if (($contact['network'] == NETWORK_FEED) AND ($contact['priority'] <= 3)) {
proc_run(PRIORITY_MEDIUM, 'include/onepoll.php', $contact['id']);
} else {
proc_run(PRIORITY_LOW, 'include/onepoll.php', $contact['id']);

View file

@ -109,6 +109,17 @@ class dba {
return $return;
}
/**
* @brief Returns the selected database name
*
* @return string
*/
public function database_name() {
$r = $this->q("SELECT DATABASE() AS `db`");
return $r[0]['db'];
}
/**
* @brief Returns the number of rows
*

View file

@ -1280,6 +1280,7 @@ function db_definition($charset) {
"uid" => array("type" => "int(11) unsigned", "not null" => "1", "default" => "0"),
"password" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"language" => array("type" => "varchar(16)", "not null" => "1", "default" => ""),
"note" => array("type" => "text"),
),
"indexes" => array(
"PRIMARY" => array("id"),

View file

@ -381,7 +381,14 @@ function delivery_run(&$argv, &$argc){
if ($deliver_status == (-1)) {
logger('notifier: delivery failed: queuing message');
add_to_queue($contact['id'],NETWORK_DFRN,$atom);
// The message could not be delivered. We mark the contact as "dead"
mark_for_death($contact);
} else {
// We successfully delivered a message, the contact is alive
unmark_for_death($contact);
}
break;
case NETWORK_OSTATUS:

View file

@ -3,7 +3,8 @@
* @file include/dfrn.php
* @brief The implementation of the dfrn protocol
*
* https://github.com/friendica/friendica/wiki/Protocol
* @see https://github.com/friendica/friendica/wiki/Protocol and
* https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
*/
require_once("include/Contact.php");
@ -134,7 +135,7 @@ class dfrn {
break; // NOTREACHED
}
$r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `contact`.`uid` = %d $sql_extra LIMIT 1",
$r = q("SELECT * FROM `contact` WHERE NOT `blocked` AND `contact`.`uid` = %d $sql_extra LIMIT 1",
intval($owner_id)
);
@ -193,7 +194,7 @@ class dfrn {
`sign`.`signed_text`, `sign`.`signature`, `sign`.`signer`
FROM `item` USE INDEX (`uid_wall_changed`, `uid_type_changed`) $sql_post_table
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id`
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`moderated` AND `item`.`parent` != 0
AND `item`.`wall` AND `item`.`changed` > '%s'

View file

@ -999,17 +999,21 @@ class diaspora {
*/
private function author_contact_by_url($contact, $person, $uid) {
$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
$r = q("SELECT `id`, `network`, `url` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc(normalise_link($person["url"])), intval($uid));
if ($r) {
$cid = $r[0]["id"];
$network = $r[0]["network"];
// We are receiving content from a user that is about to be terminated
// This means the user is vital, so we remove a possible termination date.
unmark_for_death($contact);
} else {
$cid = $contact["id"];
$network = NETWORK_DIASPORA;
}
return (array("cid" => $cid, "network" => $network));
return array("cid" => $cid, "network" => $network);
}
/**
@ -2633,7 +2637,13 @@ class diaspora {
} else {
// queue message for redelivery
add_to_queue($contact["id"], NETWORK_DIASPORA, $slap, $public_batch);
// The message could not be delivered. We mark the contact as "dead"
mark_for_death($contact);
}
} elseif (($return_code >= 200) AND ($return_code <= 299)) {
// We successfully delivered a message, the contact is alive
unmark_for_death($contact);
}
return(($return_code) ? $return_code : (-1));

View file

@ -7,20 +7,27 @@
/**
* @brief check if feature is enabled
*
*
* @return boolean
*/
function feature_enabled($uid,$feature) {
function feature_enabled($uid, $feature) {
$x = get_config('feature_lock',$feature);
if($x === false) {
$x = get_pconfig($uid,'feature',$feature);
if($x === false) {
$x = get_config('feature',$feature);
if($x === false)
if (($feature == 'richtext') AND !get_app()->theme_richtext_editor) {
return false;
}
$x = get_config('feature_lock', $feature);
if ($x === false) {
$x = get_pconfig($uid, 'feature', $feature);
if ($x === false) {
$x = get_config('feature', $feature);
if ($x === false) {
$x = get_feature_default($feature);
}
}
}
$arr = array('uid' => $uid, 'feature' => $feature, 'enabled' => $x);
call_hooks('feature_enabled',$arr);
return($arr['enabled']);
@ -135,6 +142,11 @@ function get_features($filtered = true) {
}
}
// Remove the richtext editor setting if the theme doesn't support it
if (!get_app()->theme_richtext_editor) {
unset($arr['composition'][1]);
}
call_hooks('get_features',$arr);
return $arr;
}

View file

@ -1,11 +1,14 @@
<?php
/*
html2bbcode.php
Converter for HTML to BBCode
Made by: ike@piratenpartei.de
Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
https://github.com/annando/Syncom
*/
/**
* @file include/html2bbcode.php
* @brief Converter for HTML to BBCode
*
* Made by: ike@piratenpartei.de
* Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
* https://github.com/annando/Syncom
*/
require_once("include/xml.php");
function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
{
@ -76,15 +79,6 @@ function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
return($replace);
}
if(!function_exists('deletenode')) {
function deletenode(&$doc, $node)
{
$xpath = new DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child)
$child->parentNode->removeChild($child);
}}
function _replace_code_cb($m){
return "<code>".str_replace("\n","<br>\n",$m[1]). "</code>";
}
@ -117,12 +111,12 @@ function html2bbcode($message)
@$doc->loadHTML($message);
deletenode($doc, 'style');
deletenode($doc, 'head');
deletenode($doc, 'title');
deletenode($doc, 'meta');
deletenode($doc, 'xml');
deletenode($doc, 'removeme');
xml::deleteNode($doc, 'style');
xml::deleteNode($doc, 'head');
xml::deleteNode($doc, 'title');
xml::deleteNode($doc, 'meta');
xml::deleteNode($doc, 'xml');
xml::deleteNode($doc, 'removeme');
$xpath = new DomXPath($doc);
$list = $xpath->query("//pre");
@ -239,7 +233,7 @@ function html2bbcode($message)
node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), '[iframe]$1', '[/iframe]');
node2bbcode($doc, 'code', array(), '[code]', '[/code]');
node2bbcode($doc, 'key', array(), '[code]', '[/code]');
node2bbcode($doc, 'key', array(), '[code]', '[/code]');
$message = $doc->saveHTML();

View file

@ -371,7 +371,7 @@ function profile_sidebar($profile, $block = 0) {
if(count($r))
$updated = date("c", strtotime($r[0]['updated']));
$r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
$r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s', '')",
intval($profile['uid']),
dbesc(NETWORK_DFRN),

View file

@ -1,5 +1,11 @@
<?php
/**
* @file include/items.php
*/
use \Friendica\ParseUrl;
require_once('include/bbcode.php');
require_once('include/oembed.php');
require_once('include/salmon.php');
@ -216,9 +222,8 @@ function add_page_info_data($data) {
}
function query_page_info($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "") {
require_once("mod/parse_url.php");
$data = parseurl_getsiteinfo_cached($url, true);
$data = ParseUrl::getSiteinfoCached($url, true);
if ($photo != "")
$data["images"][0]["src"] = $photo;
@ -412,6 +417,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
$dsprsig = null;
if (x($arr,'dsprsig')) {
$encoded_signature = $arr['dsprsig'];
$dsprsig = json_decode(base64_decode($arr['dsprsig']));
unset($arr['dsprsig']);
}
@ -840,15 +846,27 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
}
} else {
// This can happen - for example - if there are locking timeouts.
logger("Item wasn't stored - we quit here.");
q("COMMIT");
q("ROLLBACK");
// Store the data into a spool file so that we can try again later.
// At first we restore the Diaspora signature that we removed above.
if (isset($encoded_signature)) {
$arr['dsprsig'] = $encoded_signature;
}
// Now we store the data in the spool directory
$file = 'item-'.round(microtime(true) * 10000).".msg";
$spool = get_spoolpath().'/'.$file;
file_put_contents($spool, json_encode($arr));
logger("Item wasn't stored - Item was spooled into file ".$file, LOGGER_DEBUG);
return 0;
}
if ($current_post == 0) {
// This is one of these error messages that never should occur.
logger("couldn't find created item - we better quit now.");
q("COMMIT");
q("ROLLBACK");
return 0;
}
@ -863,7 +881,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
if (!dbm::is_result($r)) {
// This shouldn't happen, since COUNT always works when the database connection is there.
logger("We couldn't count the stored entries. Very strange ...");
q("COMMIT");
q("ROLLBACK");
return 0;
}
@ -878,7 +896,7 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
} elseif ($r[0]["entries"] == 0) {
// This really should never happen since we quit earlier if there were problems.
logger("Something is terribly wrong. We haven't found our created entry.");
q("COMMIT");
q("ROLLBACK");
return 0;
}

View file

@ -1,8 +1,17 @@
<?php
/**
* @file include/oembed.php
*/
use \Friendica\ParseUrl;
use \Friendica\Core\Config;
function oembed_replacecb($matches){
$embedurl=$matches[1];
$j = oembed_fetch_url($embedurl);
$s = oembed_format_object($j);
return $s;
}
@ -66,7 +75,7 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
}
if ($txt==false || $txt=="") {
$embedly = get_config("system", "embedly");
$embedly = Config::get("system", "embedly");
if ($embedly != "") {
// try embedly service
$ourl = "https://api.embed.ly/1/oembed?key=".$embedly."&url=".urlencode($embedurl);
@ -110,8 +119,7 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
// If fetching information doesn't work, then improve via internal functions
if (($j->type == "error") OR ($no_rich_type AND ($j->type == "rich"))) {
require_once("mod/parse_url.php");
$data = parseurl_getsiteinfo_cached($embedurl, true, false);
$data = ParseUrl::getSiteinfoCached($embedurl, true, false);
$j->type = $data["type"];
if ($j->type == "photo") {
@ -143,12 +151,11 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
function oembed_format_object($j){
require_once("mod/proxy.php");
$a = get_app();
$embedurl = $j->embedurl;
$jhtml = oembed_iframe($j->embedurl,(isset($j->width) ? $j->width : null), (isset($j->height) ? $j->height : null) );
$ret="<span class='oembed ".$j->type."'>";
switch ($j->type) {
case "video": {
case "video":
if (isset($j->thumbnail_url)) {
$tw = (isset($j->thumbnail_width) && intval($j->thumbnail_width)) ? $j->thumbnail_width:200;
$th = (isset($j->thumbnail_height) && intval($j->thumbnail_height)) ? $j->thumbnail_height:180;
@ -158,7 +165,7 @@ function oembed_format_object($j){
$th=120; $tw = $th*$tr;
$tpl=get_markup_template('oembed_video.tpl');
$ret.=replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
'$baseurl' => App::get_baseurl(),
'$embedurl'=>$embedurl,
'$escapedhtml'=>base64_encode($jhtml),
'$tw'=>$tw,
@ -170,43 +177,49 @@ function oembed_format_object($j){
$ret=$jhtml;
}
//$ret.="<br>";
}; break;
case "photo": {
break;
case "photo":
$ret.= "<img width='".$j->width."' src='".proxy_url($j->url)."'>";
}; break;
case "link": {
}; break;
case "rich": {
break;
case "link":
break;
case "rich":
// not so safe..
if (!get_config("system","no_oembed_rich_content"))
if (!Config::get("system","no_oembed_rich_content")) {
$ret.= proxy_parse_html($jhtml);
}; break;
}
break;
}
// add link to source if not present in "rich" type
if ($j->type!='rich' || !strpos($j->html,$embedurl) ){
$ret .= "<h4>";
if (isset($j->title)) {
if (isset($j->provider_name))
if (isset($j->provider_name)) {
$ret .= $j->provider_name.": ";
}
$embedlink = (isset($j->title))?$j->title:$embedurl;
$ret .= "<a href='$embedurl' rel='oembed'>$embedlink</a>";
if (isset($j->author_name))
if (isset($j->author_name)) {
$ret.=" (".$j->author_name.")";
}
} elseif (isset($j->provider_name) OR isset($j->author_name)) {
$embedlink = "";
if (isset($j->provider_name))
if (isset($j->provider_name)) {
$embedlink .= $j->provider_name;
}
if (isset($j->author_name)) {
if ($embedlink != "")
if ($embedlink != "") {
$embedlink .= ": ";
}
$embedlink .= $j->author_name;
}
if (trim($embedlink) == "")
if (trim($embedlink) == "") {
$embedlink = $embedurl;
}
$ret .= "<a href='$embedurl' rel='oembed'>$embedlink</a>";
}
@ -247,15 +260,14 @@ function oembed_iframe($src, $width, $height) {
}
$width = '100%';
$a = get_app();
$s = $a->get_baseurl() . '/oembed/'.base64url_encode($src);
$s = App::get_baseurl() . '/oembed/'.base64url_encode($src);
return '<iframe onload="resizeIframe(this);" class="embed_rich" height="' . $height . '" width="' . $width . '" src="' . $s . '" scrolling="no" frameborder="no">' . t('Embedded content') . '</iframe>';
}
function oembed_bbcode2html($text){
$stopoembed = get_config("system","no_oembed");
$stopoembed = Config::get("system","no_oembed");
if ($stopoembed == true){
return preg_replace("/\[embed\](.+?)\[\/embed\]/is", "<!-- oembed $1 --><i>". t('Embedding disabled') ." : $1</i><!-- /oembed $1 -->" ,$text);
}
@ -268,13 +280,13 @@ function oe_build_xpath($attr, $value){
return "contains( normalize-space( @$attr ), ' $value ' ) or substring( normalize-space( @$attr ), 1, string-length( '$value' ) + 1 ) = '$value ' or substring( normalize-space( @$attr ), string-length( @$attr ) - string-length( '$value' ) ) = ' $value' or @$attr = '$value'";
}
function oe_get_inner_html( $node ) {
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveXML( $child );
}
return $innerHTML;
function oe_get_inner_html($node) {
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveXML($child);
}
return $innerHTML;
}
/**
@ -283,15 +295,16 @@ function oe_get_inner_html( $node ) {
*/
function oembed_html2bbcode($text) {
// start parser only if 'oembed' is in text
if (strpos($text, "oembed")){
if (strpos($text, "oembed")) {
// convert non ascii chars to html entities
$html_text = mb_convert_encoding($text, 'HTML-ENTITIES', mb_detect_encoding($text));
// If it doesn't parse at all, just return the text.
$dom = @DOMDocument::loadHTML($html_text);
if(! $dom)
if (! $dom) {
return $text;
}
$xpath = new DOMXPath($dom);
$attr = "oembed";

View file

@ -1,6 +1,15 @@
<?php
/**
* @file include/plaintext.php
*/
use \Friendica\ParseUrl;
require_once("include/Photo.php");
require_once("include/bbcode.php");
require_once("include/html2plain.php");
require_once("include/network.php");
/**
* @brief Fetches attachment data that were generated the old way
@ -181,20 +190,17 @@ function get_attached_data($body) {
// if nothing is found, it maybe having an image.
if (!isset($post["type"])) {
require_once("mod/parse_url.php");
require_once("include/Photo.php");
$URLSearchString = "^\[\]";
if (preg_match_all("(\[url=([$URLSearchString]*)\]\s*\[img\]([$URLSearchString]*)\[\/img\]\s*\[\/url\])ism", $body, $pictures, PREG_SET_ORDER)) {
if (count($pictures) == 1) {
// Checking, if the link goes to a picture
$data = parseurl_getsiteinfo_cached($pictures[0][1], true);
$data = ParseUrl::getSiteinfoCached($pictures[0][1], true);
// Workaround:
// Sometimes photo posts to the own album are not detected at the start.
// So we seem to cannot use the cache for these cases. That's strange.
if (($data["type"] != "photo") AND strstr($pictures[0][1], "/photos/"))
$data = parseurl_getsiteinfo($pictures[0][1], true);
$data = ParseUrl::getSiteinfo($pictures[0][1], true);
if ($data["type"] == "photo") {
$post["type"] = "photo";
@ -246,8 +252,7 @@ function get_attached_data($body) {
$post["text"] = trim($body);
}
} elseif (isset($post["url"]) AND ($post["type"] == "video")) {
require_once("mod/parse_url.php");
$data = parseurl_getsiteinfo_cached($post["url"], true);
$data = ParseUrl::getSiteinfoCached($post["url"], true);
if (isset($data["images"][0]))
$post["image"] = $data["images"][0]["src"];
@ -288,9 +293,6 @@ function shortenmsg($msg, $limit, $twitter = false) {
* @return string The converted message
*/
function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2, $target_network = "") {
require_once("include/bbcode.php");
require_once("include/html2plain.php");
require_once("include/network.php");
// Remove the hash tags
$URLSearchString = "^\[\]";

View file

@ -15,7 +15,7 @@ use \Friendica\Core\PConfig;
require_once("boot.php");
function poller_run(&$argv, &$argc){
function poller_run($argv, $argc){
global $a, $db;
if(is_null($a)) {
@ -35,16 +35,21 @@ function poller_run(&$argv, &$argc){
$a->start_process();
$mypid = getmypid();
if ($a->max_processes_reached())
if (poller_max_connections_reached()) {
return;
}
if (poller_max_connections_reached())
if (App::maxload_reached()) {
return;
}
if (App::maxload_reached())
if(($argc <= 1) OR ($argv[1] != "no_cron")) {
poller_run_cron();
}
if ($a->max_processes_reached()) {
return;
}
// Checking the number of workers
if (poller_too_much_workers()) {
@ -52,112 +57,18 @@ function poller_run(&$argv, &$argc){
return;
}
if(($argc <= 1) OR ($argv[1] != "no_cron")) {
// Run the cron job that calls all other jobs
proc_run(PRIORITY_MEDIUM, "include/cron.php");
// Run the cronhooks job separately from cron for being able to use a different timing
proc_run(PRIORITY_MEDIUM, "include/cronhooks.php");
// Cleaning dead processes
poller_kill_stale_workers();
} else
// Sleep four seconds before checking for running processes again to avoid having too many workers
sleep(4);
// Checking number of workers
if (poller_too_much_workers())
return;
$cooldown = Config::get("system", "worker_cooldown", 0);
$starttime = time();
while ($r = poller_worker_process()) {
// Quit when in maintenance
if (get_config('system', 'maintenance', true))
return;
// Constantly check the number of parallel database processes
if ($a->max_processes_reached())
return;
// Constantly check the number of available database connections to let the frontend be accessible at any time
if (poller_max_connections_reached())
return;
// Count active workers and compare them with a maximum value that depends on the load
if (poller_too_much_workers())
if (poller_too_much_workers()) {
return;
$upd = q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d AND `pid` = 0",
dbesc(datetime_convert()),
intval($mypid),
intval($r[0]["id"]));
if (!$upd) {
logger("Couldn't update queue entry ".$r[0]["id"]." - skip this execution", LOGGER_DEBUG);
q("COMMIT");
continue;
}
// Assure that there are no tasks executed twice
$id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
if (!$id) {
logger("Queue item ".$r[0]["id"]." vanished - skip this execution", LOGGER_DEBUG);
q("COMMIT");
continue;
} elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
logger("Entry for queue item ".$r[0]["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
q("COMMIT");
continue;
} elseif ($id[0]["pid"] != $mypid) {
logger("Queue item ".$r[0]["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
q("COMMIT");
continue;
if (!poller_execute($r[0])) {
return;
}
q("COMMIT");
$argv = json_decode($r[0]["parameter"]);
$argc = count($argv);
// Check for existance and validity of the include file
$include = $argv[0];
if (!validate_include($include)) {
logger("Include file ".$argv[0]." is not valid!");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
continue;
}
require_once($include);
$funcname = str_replace(".php", "", basename($argv[0]))."_run";
if (function_exists($funcname)) {
logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." ".$r[0]["parameter"]);
// For better logging create a new process id for every worker call
// But preserve the old one for the worker
$old_process_id = $a->process_id;
$a->process_id = uniqid("wrk", true);
$funcname($argv, $argc);
$a->process_id = $old_process_id;
if ($cooldown > 0) {
logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." - in cooldown for ".$cooldown." seconds");
sleep($cooldown);
}
logger("Process ".$mypid." - Prio ".$r[0]["priority"]." - ID ".$r[0]["id"].": ".$funcname." - done");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
} else
logger("Function ".$funcname." does not exist");
// Quit the poller once every hour
if (time() > ($starttime + 3600))
@ -166,6 +77,108 @@ function poller_run(&$argv, &$argc){
}
/**
* @brief Execute a worker entry
*
* @param array $queue Workerqueue entry
*
* @return boolean "true" if further processing should be stopped
*/
function poller_execute($queue) {
$a = get_app();
$mypid = getmypid();
$cooldown = Config::get("system", "worker_cooldown", 0);
// Quit when in maintenance
if (get_config('system', 'maintenance', true)) {
return false;
}
// Constantly check the number of parallel database processes
if ($a->max_processes_reached()) {
return false;
}
// Constantly check the number of available database connections to let the frontend be accessible at any time
if (poller_max_connections_reached()) {
return false;
}
$upd = q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d AND `pid` = 0",
dbesc(datetime_convert()),
intval($mypid),
intval($queue["id"]));
if (!$upd) {
logger("Couldn't update queue entry ".$queue["id"]." - skip this execution", LOGGER_DEBUG);
q("COMMIT");
return true;
}
// Assure that there are no tasks executed twice
$id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
if (!$id) {
logger("Queue item ".$queue["id"]." vanished - skip this execution", LOGGER_DEBUG);
q("COMMIT");
return true;
} elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
logger("Entry for queue item ".$queue["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
q("COMMIT");
return true;
} elseif ($id[0]["pid"] != $mypid) {
logger("Queue item ".$queue["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
q("COMMIT");
return true;
}
q("COMMIT");
$argv = json_decode($queue["parameter"]);
$argc = count($argv);
// Check for existance and validity of the include file
$include = $argv[0];
if (!validate_include($include)) {
logger("Include file ".$argv[0]." is not valid!");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
return true;
}
require_once($include);
$funcname = str_replace(".php", "", basename($argv[0]))."_run";
if (function_exists($funcname)) {
logger("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." ".$queue["parameter"]);
// For better logging create a new process id for every worker call
// But preserve the old one for the worker
$old_process_id = $a->process_id;
$a->process_id = uniqid("wrk", true);
$funcname($argv, $argc);
$a->process_id = $old_process_id;
if ($cooldown > 0) {
logger("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." - in cooldown for ".$cooldown." seconds");
sleep($cooldown);
}
logger("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." - done");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
} else {
logger("Function ".$funcname." does not exist");
}
return true;
}
/**
* @brief Checks if the number of database connections has reached a critical limit.
*
@ -177,9 +190,7 @@ function poller_max_connections_reached() {
$max = get_config("system", "max_connections");
// Fetch the percentage level where the poller will get active
$maxlevel = get_config("system", "max_connections_level");
if ($maxlevel == 0)
$maxlevel = 75;
$maxlevel = Config::get("system", "max_connections_level", 75);
if ($max == 0) {
// the maximum number of possible user connections can be a system variable
@ -295,13 +306,13 @@ function poller_kill_stale_workers() {
}
}
/**
* @brief Checks if the number of active workers exceeds the given limits
*
* @return bool Are there too much workers running?
*/
function poller_too_much_workers() {
$queues = get_config("system", "worker_queues");
if ($queues == 0)
$queues = 4;
$queues = Config::get("system", "worker_queues", 4);
$maxqueues = $queues;
@ -310,9 +321,7 @@ function poller_too_much_workers() {
// Decrease the number of workers at higher load
$load = current_load();
if($load) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
$maxsysload = intval(Config::get("system", "maxloadavg", 50));
$maxworkers = $queues;
@ -373,6 +382,11 @@ function poller_too_much_workers() {
return($active >= $queues);
}
/**
* @brief Returns the number of active poller processes
*
* @return integer Number of active poller processes
*/
function poller_active_workers() {
$workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'poller.php'");
@ -394,8 +408,7 @@ function poller_passing_slow(&$highest_priority) {
$r = q("SELECT `priority`
FROM `process`
INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`
WHERE `process`.`command` = 'poller.php'");
INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid`");
// No active processes at all? Fine
if (!dbm::is_result($r))
@ -435,7 +448,6 @@ function poller_passing_slow(&$highest_priority) {
*
* @return string SQL statement
*/
function poller_worker_process() {
q("START TRANSACTION;");
@ -464,6 +476,99 @@ function poller_worker_process() {
return $r;
}
/**
* @brief Call the front end worker
*/
function call_worker() {
if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
return;
}
$url = get_app()->get_baseurl()."/worker";
fetch_url($url, false, $redirects, 1);
}
/**
* @brief Call the front end worker if there aren't any active
*/
function call_worker_if_idle() {
if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
return;
}
// Do we have "proc_open"? Then we can fork the poller
if (function_exists("proc_open")) {
// When was the last time that we called the worker?
// Less than one minute? Then we quit
if ((time() - get_config("system", "worker_started")) < 60) {
return;
}
set_config("system", "worker_started", time());
// Do we have enough running workers? Then we quit here.
if (poller_too_much_workers()) {
// Cleaning dead processes
poller_kill_stale_workers();
get_app()->remove_inactive_processes();
return;
}
poller_run_cron();
logger('Call poller', LOGGER_DEBUG);
$args = array("php", "include/poller.php", "no_cron");
$a = get_app();
$a->proc_run($args);
return;
}
// We cannot execute background processes.
// We now run the processes from the frontend.
// This won't work with long running processes.
poller_run_cron();
clear_worker_processes();
$workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'worker.php'");
if ($workers[0]["processes"] == 0) {
call_worker();
}
}
/**
* @brief Removes long running worker processes
*/
function clear_worker_processes() {
$timeout = Config::get("system", "frontend_worker_timeout", 10);
/// @todo We should clean up the corresponding workerqueue entries as well
q("DELETE FROM `process` WHERE `created` < '%s' AND `command` = 'worker.php'",
dbesc(datetime_convert('UTC','UTC',"now - ".$timeout." minutes")));
}
/**
* @brief Runs the cron processes
*/
function poller_run_cron() {
logger('Add cron entries', LOGGER_DEBUG);
// Check for spooled items
proc_run(PRIORITY_HIGH, "include/spool_post.php");
// Run the cron job that calls all other jobs
proc_run(PRIORITY_MEDIUM, "include/cron.php");
// Run the cronhooks job separately from cron for being able to use a different timing
proc_run(PRIORITY_MEDIUM, "include/cronhooks.php");
// Cleaning dead processes
poller_kill_stale_workers();
}
if (array_search(__file__,get_included_files())===0){
poller_run($_SERVER["argv"],$_SERVER["argc"]);

View file

@ -15,22 +15,35 @@ function remove_queue_item($id) {
);
}
/**
* @brief Checks if the communication with a given contact had problems recently
*
* @param int $cid Contact id
*
* @return bool The communication with this contact has currently problems
*/
function was_recently_delayed($cid) {
$r = q("SELECT `id` FROM `queue` WHERE `cid` = %d
and last > UTC_TIMESTAMP() - interval 15 minute limit 1",
$was_delayed = false;
// Are there queue entries that were recently added?
$r = q("SELECT `id` FROM `queue` WHERE `cid` = %d
AND `last` > UTC_TIMESTAMP() - interval 15 minute LIMIT 1",
intval($cid)
);
if(count($r))
return true;
$r = q("select `term-date` from contact where id = %d and `term-date` != '' and `term-date` != '0000-00-00 00:00:00' limit 1",
intval($cid)
);
if(count($r))
return true;
$was_delayed = dbm::is_result($r);
return false;
// We set "term-date" to a current date if the communication has problems.
// If the communication works again we reset this value.
if ($was_delayed) {
$r = q("SELECT `term-date` FROM `contact` WHERE `id` = %d AND `term-date` <= '1000-01-01' LIMIT 1",
intval($cid)
);
$was_delayed = !dbm::is_result($r);
}
return $was_delayed;
}

View file

@ -0,0 +1,52 @@
<?php
/**
* @file include/remove_contact.php
* @brief Removes orphaned data from deleted contacts
*/
require_once("boot.php");
function remove_contact_run($argv, $argc) {
global $a, $db;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
load_config('config');
load_config('system');
if ($argc != 2) {
return;
}
$id = intval($argv[1]);
// Only delete if the contact doesn't exist (anymore)
$r = q("SELECT `id` FROM `contact` WHERE `id` = %d", intval($id));
if (dbm::is_result($r)) {
return;
}
q("DELETE FROM `item` WHERE `contact-id` = %d", intval($id));
q("DELETE FROM `photo` WHERE `contact-id` = %d", intval($id));
q("DELETE FROM `mail` WHERE `contact-id` = %d", intval($id));
q("DELETE FROM `event` WHERE `cid` = %d", intval($id));
q("DELETE FROM `queue` WHERE `cid` = %d", intval($id));
}
if (array_search(__file__, get_included_files()) === 0) {
remove_contact_run($_SERVER["argv"], $_SERVER["argc"]);
killme();
}
?>

View file

@ -1079,10 +1079,12 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
return array();
}
$list = Cache::get("suggestion_query:".$uid.":".$start.":".$limit);
if (!is_null($list)) {
return $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.
// $list = Cache::get("suggestion_query:".$uid.":".$start.":".$limit);
// if (!is_null($list)) {
// return $list;
// }
$network = array(NETWORK_DFRN);
@ -1116,7 +1118,10 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
);
if (count($r) && count($r) >= ($limit -1)) {
Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $r, CACHE_FIVE_MINUTES);
// 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;
}
@ -1147,7 +1152,9 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
while (sizeof($list) > ($limit))
array_pop($list);
Cache::set("suggestion_query:".$uid.":".$start.":".$limit, $list, CACHE_FIVE_MINUTES);
// 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;
}

49
include/spool_post.php Normal file
View file

@ -0,0 +1,49 @@
<?php
/**
* @file include/spool_post.php
* @brief Posts items that wer spooled because they couldn't be posted.
*/
require_once("boot.php");
require_once("include/items.php");
function spool_post_run($argv, $argc) {
global $a, $db;
if (is_null($a)) {
$a = new App;
}
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
}
load_config('config');
load_config('system');
$path = get_spoolpath();
if (is_writable($path)){
if ($dh = opendir($path)) {
while (($file = readdir($dh)) !== false) {
$fullfile = $path."/".$file;
if (filetype($fullfile) != "file") {
continue;
}
$arr = json_decode(file_get_contents($fullfile), true);
$result = item_store($arr);
logger("Spool file ".$file." stored: ".$result, LOGGER_DEBUG);
unlink($fullfile);
}
closedir($dh);
}
}
}
if (array_search(__file__, get_included_files()) === 0) {
spool_post_run($_SERVER["argv"], $_SERVER["argc"]);
killme();
}
?>

View file

@ -12,7 +12,7 @@ if(! function_exists('replace_macros')) {
* This is our template processor
*
* @param string|FriendicaSmarty $s the string requiring macro substitution,
* or an instance of FriendicaSmarty
* or an instance of FriendicaSmarty
* @param array $r key value pairs (search => replace)
* @return string substituted string
*/
@ -874,8 +874,8 @@ function contact_block() {
if((! is_array($a->profile)) || ($a->profile['hide-friends']))
return $o;
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0
AND `hidden` = 0 AND `archive` = 0
WHERE `uid` = %d AND NOT `self` AND NOT `blocked`
AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s')",
intval($a->profile['uid']),
dbesc(NETWORK_DFRN),
@ -892,7 +892,7 @@ function contact_block() {
} else {
// Splitting the query in two parts makes it much faster
$r = q("SELECT `id` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked`
AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s') ORDER BY RAND() LIMIT %d",
intval($a->profile['uid']),

View file

@ -378,6 +378,29 @@ function create_user($arr) {
}
/**
* @brief send registration confiŕmation with the intormation that reg is pending
*
* @param string $email
* @param string $sitename
* @param string $username
* @return NULL|boolean from notification() and email() inherited
*/
function send_register_pending_eml($email, $sitename, $username) {
$body = deindent(t('
Dear %1$s,
Thank you for registering at %2$s. Your account is pending for approval by the administrator.
'));
$body = sprintf($body, $username, $sitename);
return notification(array(
'type' => "SYSTEM_EMAIL",
'to_email' => $email,
'subject'=> sprintf( t('Registration at %s'), $sitename),
'body' => $body));
}
/*
* send registration confirmation.
* It's here as a function because the mail is sent

View file

@ -1,11 +1,12 @@
<?php
/**
* @file include/xml.php
*/
/**
* @brief This class contain functions to work with XML data
* @brief This class contain methods to work with XML data
*
*/
class xml {
@ -23,15 +24,17 @@ class xml {
public static function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
if ($root) {
foreach($array as $key => $value) {
foreach ($namespaces AS $nskey => $nsvalue)
foreach ($array as $key => $value) {
foreach ($namespaces AS $nskey => $nsvalue) {
$key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"';
}
if (is_array($value)) {
$root = new SimpleXMLElement("<".$key."/>");
self::from_array($value, $root, $remove_header, $namespaces, false);
} else
} else {
$root = new SimpleXMLElement("<".$key.">".xmlify($value)."</".$key.">");
}
$dom = dom_import_simplexml($root)->ownerDocument;
$dom->formatOutput = true;
@ -39,16 +42,18 @@ class xml {
$xml_text = $dom->saveXML();
if ($remove_header)
if ($remove_header) {
$xml_text = trim(substr($xml_text, 21));
}
return $xml_text;
}
}
foreach($array as $key => $value) {
if (!isset($element) AND isset($xml))
if (!isset($element) AND isset($xml)) {
$element = $xml;
}
if (is_integer($key)) {
if (isset($element)) {
@ -62,27 +67,31 @@ class xml {
}
$element_parts = explode(":", $key);
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]])) {
$namespace = $namespaces[$element_parts[0]];
elseif (isset($namespaces[""])) {
} elseif (isset($namespaces[""])) {
$namespace = $namespaces[""];
} else
} else {
$namespace = NULL;
}
// Remove undefined namespaces from the key
if ((count($element_parts) > 1) AND is_null($namespace))
if ((count($element_parts) > 1) AND is_null($namespace)) {
$key = $element_parts[1];
}
if (substr($key, 0, 11) == "@attributes") {
if (!isset($element) OR !is_array($value))
if (!isset($element) OR !is_array($value)) {
continue;
}
foreach ($value as $attr_key => $attr_value) {
$element_parts = explode(":", $attr_key);
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]])) {
$namespace = $namespaces[$element_parts[0]];
else
} else {
$namespace = NULL;
}
$element->addAttribute($attr_key, $attr_value, $namespace);
}
@ -90,9 +99,9 @@ class xml {
continue;
}
if (!is_array($value))
if (!is_array($value)) {
$element = $xml->addChild($key, xmlify($value), $namespace);
elseif (is_array($value)) {
} elseif (is_array($value)) {
$element = $xml->addChild($key, NULL, $namespace);
self::from_array($value, $element, $remove_header, $namespaces, false);
}
@ -111,8 +120,9 @@ class xml {
$target->addChild($elementname, xmlify($source));
else {
$child = $target->addChild($elementname);
foreach ($source->children() AS $childfield => $childentry)
foreach ($source->children() AS $childfield => $childentry) {
self::copy($childentry, $child, $childfield);
}
}
}
@ -168,11 +178,11 @@ class xml {
return(null);
}
if (!is_string($xml_element) &&
!is_array($xml_element) &&
(get_class($xml_element) == 'SimpleXMLElement')) {
$xml_element_copy = $xml_element;
$xml_element = get_object_vars($xml_element);
if (!is_string($xml_element)
&& !is_array($xml_element)
&& (get_class($xml_element) == 'SimpleXMLElement')) {
$xml_element_copy = $xml_element;
$xml_element = get_object_vars($xml_element);
}
if (is_array($xml_element)) {
@ -181,7 +191,7 @@ class xml {
return (trim(strval($xml_element_copy)));
}
foreach($xml_element as $key=>$value) {
foreach ($xml_element as $key => $value) {
$recursion_depth++;
$result_array[strtolower($key)] =
@ -223,10 +233,12 @@ class xml {
*
* @return array The parsed XML in an array form. Use print_r() to see the resulting array structure.
*/
public static function to_array($contents, $namespaces = true, $get_attributes=1, $priority = 'attribute') {
if(!$contents) return array();
public static function to_array($contents, $namespaces = true, $get_attributes = 1, $priority = 'attribute') {
if (!$contents) {
return array();
}
if(!function_exists('xml_parser_create')) {
if (!function_exists('xml_parser_create')) {
logger('xml::to_array: parser function missing');
return array();
}
@ -235,12 +247,13 @@ class xml {
libxml_use_internal_errors(true);
libxml_clear_errors();
if($namespaces)
if ($namespaces) {
$parser = @xml_parser_create_ns("UTF-8",':');
else
} else {
$parser = @xml_parser_create();
}
if(! $parser) {
if (! $parser) {
logger('xml::to_array: xml_parser_create: no resource');
return array();
}
@ -252,10 +265,11 @@ class xml {
@xml_parse_into_struct($parser, trim($contents), $xml_values);
@xml_parser_free($parser);
if(! $xml_values) {
if (! $xml_values) {
logger('xml::to_array: libxml: parse error: ' . $contents, LOGGER_DATA);
foreach(libxml_get_errors() as $err)
foreach (libxml_get_errors() as $err) {
logger('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message, LOGGER_DATA);
}
libxml_clear_errors();
return;
}
@ -270,8 +284,8 @@ class xml {
// Go through the tags.
$repeated_tag_index = array(); // Multiple tags with same name will be turned into an array
foreach($xml_values as $data) {
unset($attributes,$value); // Remove existing values, or there will be trouble
foreach ($xml_values as $data) {
unset($attributes, $value); // Remove existing values, or there will be trouble
// This command will extract these variables into the foreach scope
// tag(string), type(string), level(int), attributes(array).
@ -280,46 +294,54 @@ class xml {
$result = array();
$attributes_data = array();
if(isset($value)) {
if($priority == 'tag') $result = $value;
else $result['value'] = $value; // Put the value in a assoc array if we are in the 'Attribute' mode
if (isset($value)) {
if ($priority == 'tag') {
$result = $value;
} else {
$result['value'] = $value; // Put the value in a assoc array if we are in the 'Attribute' mode
}
}
//Set the attributes too.
if(isset($attributes) and $get_attributes) {
foreach($attributes as $attr => $val) {
if($priority == 'tag') $attributes_data[$attr] = $val;
else $result['@attributes'][$attr] = $val; // Set all the attributes in a array called 'attr'
if (isset($attributes) and $get_attributes) {
foreach ($attributes as $attr => $val) {
if($priority == 'tag') {
$attributes_data[$attr] = $val;
} else {
$result['@attributes'][$attr] = $val; // Set all the attributes in a array called 'attr'
}
}
}
// See tag status and do the needed.
if($namespaces && strpos($tag,':')) {
$namespc = substr($tag,0,strrpos($tag,':'));
$tag = strtolower(substr($tag,strlen($namespc)+1));
if ($namespaces && strpos($tag, ':')) {
$namespc = substr($tag, 0, strrpos($tag, ':'));
$tag = strtolower(substr($tag, strlen($namespc)+1));
$result['@namespace'] = $namespc;
}
$tag = strtolower($tag);
if($type == "open") { // The starting of the tag '<tag>'
if ($type == "open") { // The starting of the tag '<tag>'
$parent[$level-1] = &$current;
if(!is_array($current) or (!in_array($tag, array_keys($current)))) { // Insert New tag
if (!is_array($current) or (!in_array($tag, array_keys($current)))) { // Insert New tag
$current[$tag] = $result;
if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
if ($attributes_data) {
$current[$tag. '_attr'] = $attributes_data;
}
$repeated_tag_index[$tag.'_'.$level] = 1;
$current = &$current[$tag];
} else { // There was another element with the same tag name
if(isset($current[$tag][0])) { // If there is a 0th element it is already an array
if (isset($current[$tag][0])) { // If there is a 0th element it is already an array
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
$repeated_tag_index[$tag.'_'.$level]++;
} else { // This section will make the value an array if multiple tags with the same name appear together
$current[$tag] = array($current[$tag],$result); // This will combine the existing item and the new item together to make an array
$current[$tag] = array($current[$tag], $result); // This will combine the existing item and the new item together to make an array
$repeated_tag_index[$tag.'_'.$level] = 2;
if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
if (isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
unset($current[$tag.'_attr']);
}
@ -329,35 +351,37 @@ class xml {
$current = &$current[$tag][$last_item_index];
}
} elseif($type == "complete") { // Tags that ends in 1 line '<tag />'
} elseif ($type == "complete") { // Tags that ends in 1 line '<tag />'
//See if the key is already taken.
if(!isset($current[$tag])) { //New Key
if (!isset($current[$tag])) { //New Key
$current[$tag] = $result;
$repeated_tag_index[$tag.'_'.$level] = 1;
if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;
if ($priority == 'tag' and $attributes_data) {
$current[$tag. '_attr'] = $attributes_data;
}
} else { // If taken, put all things inside a list(array)
if(isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array...
if (isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array...
// ...push the new element into that array.
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
if($priority == 'tag' and $get_attributes and $attributes_data) {
if ($priority == 'tag' and $get_attributes and $attributes_data) {
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
}
$repeated_tag_index[$tag.'_'.$level]++;
} else { // If it is not an array...
$current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
$current[$tag] = array($current[$tag], $result); //...Make it an array using using the existing value and the new value
$repeated_tag_index[$tag.'_'.$level] = 1;
if($priority == 'tag' and $get_attributes) {
if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
if ($priority == 'tag' and $get_attributes) {
if (isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
unset($current[$tag.'_attr']);
}
if($attributes_data) {
if ($attributes_data) {
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
}
}
@ -365,12 +389,25 @@ class xml {
}
}
} elseif($type == 'close') { // End of tag '</tag>'
} elseif ($type == 'close') { // End of tag '</tag>'
$current = &$parent[$level-1];
}
}
return($xml_array);
}
/**
* @brief Delete a node in a XML object
*
* @param object $doc XML document
* @param string $node Node name
*/
public static function deleteNode(&$doc, $node) {
$xpath = new DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child) {
$child->parentNode->removeChild($child);
}
}
}
?>

View file

@ -99,6 +99,10 @@ if (!$a->is_backend()) {
$stamp1 = microtime(true);
session_start();
$a->save_timestamp($stamp1, "parser");
} else {
require_once "include/poller.php";
call_worker_if_idle();
}
/**

View file

@ -296,7 +296,7 @@ function string2bb(element) {
$.fn.bbco_autocomplete = function(type) {
if(type=='bbcode') {
var open_close_elements = ['bold', 'italic', 'underline', 'overline', 'strike', 'quote', 'code', 'spoiler', 'map', 'img', 'url', 'audio', 'video', 'youtube', 'vimeo', 'list', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'center', 'color', 'font', 'size', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nobb', 'noparse', 'pre', 'abstract'];
var open_close_elements = ['bold', 'italic', 'underline', 'overline', 'strike', 'quote', 'code', 'spoiler', 'map', 'img', 'url', 'audio', 'video', 'embed', 'youtube', 'vimeo', 'list', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'center', 'color', 'font', 'size', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nobb', 'noparse', 'pre', 'abstract'];
var open_elements = ['*', 'hr'];
var elements = open_close_elements.concat(open_elements);

View file

@ -44,7 +44,7 @@ aStates[20]="|Brestskaya (Brest)|Homyel'skaya (Homyel')|Horad Minsk|Hrodzyenskay
aStates[21]="|Antwerpen|Brabant Wallon|Brussels Capitol Region|Hainaut|Liege|Limburg|Luxembourg|Namur|Oost-Vlaanderen|Vlaams Brabant|West-Vlaanderen";
aStates[22]="|Belize|Cayo|Corozal|Orange Walk|Stann Creek|Toledo";
aStates[23]="|Alibori|Atakora|Atlantique|Borgou|Collines|Couffo|Donga|Littoral|Mono|Oueme|Plateau|Zou";
aStates[24]="|Devonshire|Hamilton|Hamilton|Paget|Pembroke|Saint George|Saint Georges|Sandys|Smiths|Southampton|Warwick";
aStates[24]="|Devonshire|Hamilton (City)|Hamilton|Paget|Pembroke|Saint George|Saint Georges|Sandys|Smiths|Southampton|Warwick";
aStates[25]="|Bumthang|Chhukha|Chirang|Daga|Geylegphug|Ha|Lhuntshi|Mongar|Paro|Pemagatsel|Punakha|Samchi|Samdrup Jongkhar|Shemgang|Tashigang|Thimphu|Tongsa|Wangdi Phodrang";
aStates[26]="|Beni|Chuquisaca|Cochabamba|La Paz|Oruro|Pando|Potosi|Santa Cruz|Tarija";
aStates[27]="|Federation of Bosnia and Herzegovina|Republika Srpska";
@ -125,7 +125,7 @@ aStates[99]="|Holy See (Vatican City)"
aStates[100]="|Atlantida|Choluteca|Colon|Comayagua|Copan|Cortes|El Paraiso|Francisco Morazan|Gracias a Dios|Intibuca|Islas de la Bahia|La Paz|Lempira|Ocotepeque|Olancho|Santa Barbara|Valle|Yoro";
aStates[101]="|Hong Kong";
aStates[102]="|Howland Island";
aStates[103]="|Bacs-Kiskun|Baranya|Bekes|Bekescsaba|Borsod-Abauj-Zemplen|Budapest|Csongrad|Debrecen|Dunaujvaros|Eger|Fejer|Gyor|Gyor-Moson-Sopron|Hajdu-Bihar|Heves|Hodmezovasarhely|Jasz-Nagykun-Szolnok|Kaposvar|Kecskemet|Komarom-Esztergom|Miskolc|Nagykanizsa|Nograd|Nyiregyhaza|Pecs|Pest|Somogy|Sopron|Szabolcs-Szatmar-Bereg|Szeged|Szekesfehervar|Szolnok|Szombathely|Tatabanya|Tolna|Vas|Veszprem|Veszprem|Zala|Zalaegerszeg";
aStates[103]="|Bacs-Kiskun|Baranya|Bekes|Bekescsaba|Borsod-Abauj-Zemplen|Budapest|Csongrad|Debrecen|Dunaujvaros|Eger|Fejer|Gyor|Gyor-Moson-Sopron|Hajdu-Bihar|Heves|Hodmezovasarhely|Jasz-Nagykun-Szolnok|Kaposvar|Kecskemet|Komarom-Esztergom|Miskolc|Nagykanizsa|Nograd|Nyiregyhaza|Pecs|Pest|Somogy|Sopron|Szabolcs-Szatmar-Bereg|Szeged|Szekesfehervar|Szolnok|Szombathely|Tatabanya|Tolna|Vas|Veszprem|Veszprem (City)|Zala|Zalaegerszeg";
aStates[104]="|Akranes|Akureyri|Arnessysla|Austur-Bardhastrandarsysla|Austur-Hunavatnssysla|Austur-Skaftafellssysla|Borgarfjardharsysla|Dalasysla|Eyjafjardharsysla|Gullbringusysla|Hafnarfjordhur|Husavik|Isafjordhur|Keflavik|Kjosarsysla|Kopavogur|Myrasysla|Neskaupstadhur|Nordhur-Isafjardharsysla|Nordhur-Mulasys-la|Nordhur-Thingeyjarsysla|Olafsfjordhur|Rangarvallasysla|Reykjavik|Saudharkrokur|Seydhisfjordhur|Siglufjordhur|Skagafjardharsysla|Snaefellsnes-og Hnappadalssysla|Strandasysla|Sudhur-Mulasysla|Sudhur-Thingeyjarsysla|Vesttmannaeyjar|Vestur-Bardhastrandarsysla|Vestur-Hunavatnssysla|Vestur-Isafjardharsysla|Vestur-Skaftafellssysla";
aStates[105]="|Andaman and Nicobar Islands|Andhra Pradesh|Arunachal Pradesh|Assam|Bihar|Chandigarh|Chhattisgarh|Dadra and Nagar Haveli|Daman and Diu|Delhi|Goa|Gujarat|Haryana|Himachal Pradesh|Jammu and Kashmir|Jharkhand|Karnataka|Kerala|Lakshadweep|Madhya Pradesh|Maharashtra|Manipur|Meghalaya|Mizoram|Nagaland|Orissa|Pondicherry|Punjab|Rajasthan|Sikkim|Tamil Nadu|Tripura|Uttar Pradesh|Uttaranchal|West Bengal";
aStates[106]="|Aceh|Bali|Banten|Bengkulu|East Timor|Gorontalo|Irian Jaya|Jakarta Raya|Jambi|Jawa Barat|Jawa Tengah|Jawa Timur|Kalimantan Barat|Kalimantan Selatan|Kalimantan Tengah|Kalimantan Timur|Kepulauan Bangka Belitung|Lampung|Maluku|Maluku Utara|Nusa Tenggara Barat|Nusa Tenggara Timur|Riau|Sulawesi Selatan|Sulawesi Tengah|Sulawesi Tenggara|Sulawesi Utara|Sumatera Barat|Sumatera Selatan|Sumatera Utara|Yogyakarta";
@ -145,12 +145,12 @@ aStates[119]="|'Amman|Ajlun|Al 'Aqabah|Al Balqa'|Al Karak|Al Mafraq|At Tafilah|A
aStates[120]="|Juan de Nova Island";
aStates[121]="|Almaty|Aqmola|Aqtobe|Astana|Atyrau|Batys Qazaqstan|Bayqongyr|Mangghystau|Ongtustik Qazaqstan|Pavlodar|Qaraghandy|Qostanay|Qyzylorda|Shyghys Qazaqstan|Soltustik Qazaqstan|Zhambyl";
aStates[122]="|Central|Coast|Eastern|Nairobi Area|North Eastern|Nyanza|Rift Valley|Western";
aStates[123]="|Abaiang|Abemama|Aranuka|Arorae|Banaba|Banaba|Beru|Butaritari|Central Gilberts|Gilbert Islands|Kanton|Kiritimati|Kuria|Line Islands|Line Islands|Maiana|Makin|Marakei|Nikunau|Nonouti|Northern Gilberts|Onotoa|Phoenix Islands|Southern Gilberts|Tabiteuea|Tabuaeran|Tamana|Tarawa|Tarawa|Teraina";
aStates[123]="|Abaiang|Abemama|Aranuka|Arorae|Banaba (District)|Banaba|Beru|Butaritari|Central Gilberts (District)|Gilbert Islands (Unit)|Kanton|Kiritimati|Kuria|Line Islands (District)|Line Islands (Unit)|Maiana|Makin|Marakei|Nikunau|Nonouti|Northern Gilberts (District)|Onotoa|Phoenix Islands (Unit)|Southern Gilberts (District)|Tabiteuea|Tabuaeran|Tamana|Tarawa (District)|Tarawa|Teraina";
aStates[124]="|Chagang-do (Chagang Province)|Hamgyong-bukto (North Hamgyong Province)|Hamgyong-namdo (South Hamgyong Province)|Hwanghae-bukto (North Hwanghae Province)|Hwanghae-namdo (South Hwanghae Province)|Kaesong-si (Kaesong City)|Kangwon-do (Kangwon Province)|Namp'o-si (Namp'o City)|P'yongan-bukto (North P'yongan Province)|P'yongan-namdo (South P'yongan Province)|P'yongyang-si (P'yongyang City)|Yanggang-do (Yanggang Province)"
aStates[125]="|Ch'ungch'ong-bukto|Ch'ungch'ong-namdo|Cheju-do|Cholla-bukto|Cholla-namdo|Inch'on-gwangyoksi|Kangwon-do|Kwangju-gwangyoksi|Kyonggi-do|Kyongsang-bukto|Kyongsang-namdo|Pusan-gwangyoksi|Soul-t'ukpyolsi|Taegu-gwangyoksi|Taejon-gwangyoksi|Ulsan-gwangyoksi";
aStates[126]="|Al 'Asimah|Al Ahmadi|Al Farwaniyah|Al Jahra'|Hawalli";
aStates[127]="|Batken Oblasty|Bishkek Shaary|Chuy Oblasty (Bishkek)|Jalal-Abad Oblasty|Naryn Oblasty|Osh Oblasty|Talas Oblasty|Ysyk-Kol Oblasty (Karakol)"
aStates[128]="|Attapu|Bokeo|Bolikhamxai|Champasak|Houaphan|Khammouan|Louangnamtha|Louangphabang|Oudomxai|Phongsali|Salavan|Savannakhet|Viangchan|Viangchan|Xaignabouli|Xaisomboun|Xekong|Xiangkhoang";
aStates[128]="|Attapu|Bokeo|Bolikhamxai|Champasak|Houaphan|Khammouan|Louangnamtha|Louangphabang|Oudomxai|Phongsali|Salavan|Savannakhet|Viangchan City|Viangchan|Xaignabouli|Xaisomboun|Xekong|Xiangkhoang";
aStates[129]="|Aizkraukles Rajons|Aluksnes Rajons|Balvu Rajons|Bauskas Rajons|Cesu Rajons|Daugavpils|Daugavpils Rajons|Dobeles Rajons|Gulbenes Rajons|Jekabpils Rajons|Jelgava|Jelgavas Rajons|Jurmala|Kraslavas Rajons|Kuldigas Rajons|Leipaja|Liepajas Rajons|Limbazu Rajons|Ludzas Rajons|Madonas Rajons|Ogres Rajons|Preilu Rajons|Rezekne|Rezeknes Rajons|Riga|Rigas Rajons|Saldus Rajons|Talsu Rajons|Tukuma Rajons|Valkas Rajons|Valmieras Rajons|Ventspils|Ventspils Rajons";
aStates[130]="|Beyrouth|Ech Chimal|Ej Jnoub|El Bekaa|Jabal Loubnane";
aStates[131]="|Berea|Butha-Buthe|Leribe|Mafeteng|Maseru|Mohales Hoek|Mokhotlong|Qacha's Nek|Quthing|Thaba-Tseka";
@ -176,7 +176,7 @@ aStates[150]="|Mayotte";
aStates[151]="|Aguascalientes|Baja California|Baja California Sur|Campeche|Chiapas|Chihuahua|Coahuila de Zaragoza|Colima|Distrito Federal|Durango|Guanajuato|Guerrero|Hidalgo|Jalisco|Mexico|Michoacan de Ocampo|Morelos|Nayarit|Nuevo Leon|Oaxaca|Puebla|Queretaro de Arteaga|Quintana Roo|San Luis Potosi|Sinaloa|Sonora|Tabasco|Tamaulipas|Tlaxcala|Veracruz-Llave|Yucatan|Zacatecas";
aStates[152]="|Chuuk (Truk)|Kosrae|Pohnpei|Yap";
aStates[153]="|Midway Islands";
aStates[154]="|Balti|Cahul|Chisinau|Chisinau|Dubasari|Edinet|Gagauzia|Lapusna|Orhei|Soroca|Tighina|Ungheni";
aStates[154]="|Balti|Cahul|Chisinau (City)|Chisinau|Dubasari|Edinet|Gagauzia|Lapusna|Orhei|Soroca|Tighina|Ungheni";
aStates[155]="|Fontvieille|La Condamine|Monaco-Ville|Monte-Carlo";
aStates[156]="|Arhangay|Bayan-Olgiy|Bayanhongor|Bulgan|Darhan|Dornod|Dornogovi|Dundgovi|Dzavhan|Erdenet|Govi-Altay|Hentiy|Hovd|Hovsgol|Omnogovi|Ovorhangay|Selenge|Suhbaatar|Tov|Ulaanbaatar|Uvs";
aStates[157]="|Saint Anthony|Saint Georges|Saint Peter's";
@ -243,7 +243,7 @@ aStates[217]="|Hhohho|Lubombo|Manzini|Shiselweni";
aStates[218]="|Blekinge|Dalarnas|Gavleborgs|Gotlands|Hallands|Jamtlands|Jonkopings|Kalmar|Kronobergs|Norrbottens|Orebro|Ostergotlands|Skane|Sodermanlands|Stockholms|Uppsala|Varmlands|Vasterbottens|Vasternorrlands|Vastmanlands|Vastra Gotalands";
aStates[219]="|Aargau|Ausser-Rhoden|Basel-Landschaft|Basel-Stadt|Bern|Fribourg|Geneve|Glarus|Graubunden|Inner-Rhoden|Jura|Luzern|Neuchatel|Nidwalden|Obwalden|Sankt Gallen|Schaffhausen|Schwyz|Solothurn|Thurgau|Ticino|Uri|Valais|Vaud|Zug|Zurich";
aStates[220]="|Al Hasakah|Al Ladhiqiyah|Al Qunaytirah|Ar Raqqah|As Suwayda'|Dar'a|Dayr az Zawr|Dimashq|Halab|Hamah|Hims|Idlib|Rif Dimashq|Tartus";
aStates[221]="|Chang-hua|Chi-lung|Chia-i|Chia-i|Chung-hsing-hsin-ts'un|Hsin-chu|Hsin-chu|Hua-lien|I-lan|Kao-hsiung|Kao-hsiung|Miao-li|Nan-t'ou|P'eng-hu|P'ing-tung|T'ai-chung|T'ai-chung|T'ai-nan|T'ai-nan|T'ai-pei|T'ai-pei|T'ai-tung|T'ao-yuan|Yun-lin";
aStates[221]="|Chang-hua|Chi-lung|Chia-i (City)|Chia-i|Chung-hsing-hsin-ts'un|Hsin-chu (City)|Hsin-chu|Hua-lien|I-lan|Kao-hsiung (City)|Kao-hsiung|Miao-li|Nan-t'ou|P'eng-hu|P'ing-tung|T'ai-chung (City)|T'ai-chung|T'ai-nan (City)|T'ai-nan|T'ai-pei (City)|T'ai-pei|T'ai-tung|T'ao-yuan|Yun-lin";
aStates[222]="|Viloyati Khatlon|Viloyati Leninobod|Viloyati Mukhtori Kuhistoni Badakhshon";
aStates[223]="|Arusha|Dar es Salaam|Dodoma|Iringa|Kagera|Kigoma|Kilimanjaro|Lindi|Mara|Mbeya|Morogoro|Mtwara|Mwanza|Pemba North|Pemba South|Pwani|Rukwa|Ruvuma|Shinyanga|Singida|Tabora|Tanga|Zanzibar Central/South|Zanzibar North|Zanzibar Urban/West";
aStates[224]="|Amnat Charoen|Ang Thong|Buriram|Chachoengsao|Chai Nat|Chaiyaphum|Chanthaburi|Chiang Mai|Chiang Rai|Chon Buri|Chumphon|Kalasin|Kamphaeng Phet|Kanchanaburi|Khon Kaen|Krabi|Krung Thep Mahanakhon (Bangkok)|Lampang|Lamphun|Loei|Lop Buri|Mae Hong Son|Maha Sarakham|Mukdahan|Nakhon Nayok|Nakhon Pathom|Nakhon Phanom|Nakhon Ratchasima|Nakhon Sawan|Nakhon Si Thammarat|Nan|Narathiwat|Nong Bua Lamphu|Nong Khai|Nonthaburi|Pathum Thani|Pattani|Phangnga|Phatthalung|Phayao|Phetchabun|Phetchaburi|Phichit|Phitsanulok|Phra Nakhon Si Ayutthaya|Phrae|Phuket|Prachin Buri|Prachuap Khiri Khan|Ranong|Ratchaburi|Rayong|Roi Et|Sa Kaeo|Sakon Nakhon|Samut Prakan|Samut Sakhon|Samut Songkhram|Sara Buri|Satun|Sing Buri|Sisaket|Songkhla|Sukhothai|Suphan Buri|Surat Thani|Surin|Tak|Trang|Trat|Ubon Ratchathani|Udon Thani|Uthai Thani|Uttaradit|Yala|Yasothon";

View file

@ -92,7 +92,6 @@
/* event from comment textarea button popups */
/* insert returned bbcode at cursor position or replace selected text */
$("body").on("fbrowser.image.comment", function(e, filename, bbcode, id) {
console.log("on", id);
$.colorbox.close();
var textarea = document.getElementById("comment-edit-text-" +id);
var start = textarea.selectionStart;
@ -117,7 +116,6 @@
$("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
$("#"+id+"_onoff ."+ (val==1?"on":"off")).removeClass("hidden");
input.val(val);
//console.log(id);
});
/* setup field_richtext */
@ -179,110 +177,77 @@
$('#nav-notifications-menu, aside').perfectScrollbar();
/* nav update event */
$('nav').bind('nav-update', function(e,data){
var invalid = $(data).find('invalid').text();
$('nav').bind('nav-update', function(e, data){
var invalid = data.invalid || 0;
if(invalid == 1) { window.location.href=window.location.href }
var net = $(data).find('net').text();
if(net == 0) { net = ''; $('#net-update').removeClass('show') } else { $('#net-update').addClass('show') }
$('#net-update').html(net);
['net', 'home', 'intro', 'mail', 'events', 'birthdays', 'notify'].forEach(function(type) {
var number = data[type];
if (number == 0) {
number = '';
$('#' + type + '-update').removeClass('show');
} else {
$('#' + type + '-update').addClass('show');
}
$('#' + type + '-update').text(number);
});
var home = $(data).find('home').text();
if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
$('#home-update').html(home);
var intro = $(data).find('intro').text();
if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
$('#intro-update').html(intro);
var mail = $(data).find('mail').text();
if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
$('#mail-update').html(mail);
var intro = $(data).find('intro').text();
if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
var intro = data['intro'];
if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
$('#intro-update-li').html(intro);
var mail = $(data).find('mail').text();
if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
var mail = data['mail'];
if(mail == 0) { mail = ''; $('#mail-update-li').removeClass('show') } else { $('#mail-update-li').addClass('show') }
$('#mail-update-li').html(mail);
var allevents = $(data).find('all-events').text();
if(allevents == 0) { allevents = ''; $('#allevents-update').removeClass('show') } else { $('#allevents-update').addClass('show') }
$('#allevents-update').html(allevents);
var alleventstoday = $(data).find('all-events-today').text();
if(alleventstoday == 0) { $('#allevents-update').removeClass('notif-allevents-today') } else { $('#allevents-update').addClass('notif-allevents-today') }
var events = $(data).find('events').text();
if(events == 0) { events = ''; $('#events-update').removeClass('show') } else { $('#events-update').addClass('show') }
$('#events-update').html(events);
var eventstoday = $(data).find('events-today').text();
if(eventstoday == 0) { $('#events-update').removeClass('notif-events-today') } else { $('#events-update').addClass('notif-events-today') }
var birthdays = $(data).find('birthdays').text();
if(birthdays == 0) {birthdays = ''; $('#birthdays-update').removeClass('show') } else { $('#birthdays-update').addClass('show') }
$('#birthdays-update').html(birthdays);
var birthdaystoday = $(data).find('birthdays-today').text();
if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
$(".sidebar-group-li .notify").removeClass("show");
$(data).find("group").each(function() {
var gid = this.id;
var gcount = this.innerHTML;
$(data.groups).each(function(key, group) {
var gid = group.id;
var gcount = group.count;
$(".group-"+gid+" .notify").addClass("show").text(gcount);
});
$(".forum-widget-entry .notify").removeClass("show");
$(data).find("forum").each(function() {
var fid = this.id;
var fcount = this.innerHTML;
$(data.forums).each(function(key, forum) {
var fid = forum.id;
var fcount = forum.count;
$(".forum-"+fid+" .notify").addClass("show").text(fcount);
});
var eNotif = $(data).find('notif')
if (eNotif.children("note").length==0){
if (data.notifications.length == 0) {
$("#nav-notifications-menu").html(notifications_empty);
} else {
nnm = $("#nav-notifications-menu");
var nnm = $("#nav-notifications-menu");
nnm.html(notifications_all + notifications_mark);
//nnm.attr('popup','true');
var notification_lastitem = parseInt(localStorage.getItem("notification-lastitem"));
var notification_id = 0;
eNotif.children("note").each(function(){
e = $(this);
var text = e.text().format("<span class='contactname'>"+e.attr('name')+"</span>");
var contact = ("<a href="+e.attr('url')+"><span class='contactname'>"+e.attr('name')+"</span></a>");
var seenclass = (e.attr('seen')==1)?"notify-seen":"notify-unseen";
$(data.notifications).each(function(key, notif){
var text = notif.message.format('<span class="contactname">' + notif.name + '</span>');
var contact = ('<a href="' + notif.url + '"><span class="contactname">' + notif.name + '</span></a>');
var seenclass = (notif.seen == 1) ? "notify-seen" : "notify-unseen";
var html = notifications_tpl.format(
e.attr('href'), // {0} // link to the source
e.attr('photo'), // {1} // photo of the contact
text, // {2} // preformatted text (autor + text)
e.attr('date'), // {3} // date of notification (time ago)
seenclass, // {4} // visited status of the notification
new Date(e.attr('timestamp')*1000), // {5} // date of notification
e.attr('url'), // {6} // profile url of the contact
e.text().format(contact), // {7} // preformatted html (text including author profile url)
'' // {8} // Deprecated
notif.href, // {0} // link to the source
notif.photo, // {1} // photo of the contact
text, // {2} // preformatted text (autor + text)
notif.date, // {3} // date of notification (time ago)
seenclass, // {4} // visited status of the notification
new Date(notif.timestamp*1000), // {5} // date of notification
notif.url, // {6} // profile url of the contact
notif.message.format(contact), // {7} // preformatted html (text including author profile url)
'' // {8} // Deprecated
);
nnm.append(html);
});
$(eNotif.children("note").get().reverse()).each(function(){
e = $(this);
notification_id = parseInt(e.attr('timestamp'));
if (notification_lastitem!== null && notification_id > notification_lastitem) {
if (getNotificationPermission()==="granted") {
$(data.notifications.reverse()).each(function(key, e){
notification_id = parseInt(e.timestamp);
if (notification_lastitem !== null && notification_id > notification_lastitem) {
if (getNotificationPermission() === "granted") {
var notification = new Notification(document.title, {
body: decodeHtml(e.text().replace('&rarr; ','').format(e.attr('name'))),
icon: e.attr('photo'),
body: decodeHtml(e.message.replace('&rarr; ', '').format(e.name)),
icon: e.photo,
});
notification['url'] = e.attr('href');
notification['url'] = e.href;
notification.addEventListener("click", function(ev){
window.location = ev.target.url;
});
@ -303,23 +268,18 @@
});
}
notif = eNotif.attr('count');
if (notif>0){
var notif = data['notify'];
if (notif > 0){
$("#nav-notifications-linkmenu").addClass("on");
} else {
$("#nav-notifications-linkmenu").removeClass("on");
}
if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
$('#notify-update').html(notif);
var eSysmsg = $(data).find('sysmsgs');
eSysmsg.children("notice").each(function(){
text = $(this).text();
$.jGrowl(text, { sticky: true, theme: 'notice' });
$(data.sysmsgs.notice).each(function(key, message){
$.jGrowl(message, {sticky: true, theme: 'notice'});
});
eSysmsg.children("info").each(function(){
text = $(this).text();
$.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
$(data.sysmsgs.info).each(function(key, message){
$.jGrowl(message, {sticky: false, theme: 'info', life: 5000});
});
/* update the js scrollbars */
@ -374,50 +334,38 @@
function NavUpdate() {
if(! stopped) {
var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
$.get(pingCmd,function(data) {
$(data).find('result').each(function() {
if (!stopped) {
var pingCmd = 'ping?format=json' + ((localUser != 0) ? '&f=&uid=' + localUser : '');
$.get(pingCmd, function(data) {
if (data.result) {
// send nav-update event
$('nav').trigger('nav-update', this);
$('nav').trigger('nav-update', data.result);
// start live update
if($('#live-network').length) { src = 'network'; liveUpdate(); }
if($('#live-profile').length) { src = 'profile'; liveUpdate(); }
if($('#live-community').length) { src = 'community'; liveUpdate(); }
if($('#live-notes').length) { src = 'notes'; liveUpdate(); }
if($('#live-display').length) { src = 'display'; liveUpdate(); }
/* if($('#live-display').length) {
if(liking) {
liking = 0;
window.location.href=window.location.href
['network', 'profile', 'community', 'notes', 'display'].forEach(function (src) {
if ($('#live-' + src).length) {
liveUpdate(src);
}
}*/
if($('#live-photos').length) {
if(liking) {
});
if ($('#live-photos').length) {
if (liking) {
liking = 0;
window.location.href=window.location.href
window.location.href = window.location.href;
}
}
});
}
}) ;
}
timer = setTimeout(NavUpdate,updateInterval);
timer = setTimeout(NavUpdate, updateInterval);
}
function liveUpdate() {
function liveUpdate(src) {
if((src == null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; }
if(($('.comment-edit-text-full').length) || (in_progress)) {
if(livetime) {
clearTimeout(livetime);
}
livetime = setTimeout(liveUpdate, 5000);
livetime = setTimeout(function() {liveUpdate(src)}, 5000);
return;
}
if(livetime != null)
@ -740,8 +688,6 @@
// page number
infinite_scroll.pageno+=1;
console.log('Loading page ' + infinite_scroll.pageno);
// get the raw content from the next page and insert this content
// right before "#conversation-end"
$.get('network?mode=raw' + infinite_scroll.reload_uri + '&page=' + infinite_scroll.pageno, function(data) {

View file

@ -428,6 +428,21 @@ function admin_page_queue(&$a) {
* @return string
*/
function admin_page_summary(&$a) {
global $db;
// are there MyISAM tables in the DB? If so, trigger a warning message
$r = q("SELECT `engine` FROM `information_schema`.`tables` WHERE `engine` = 'myisam' AND `table_schema` = '%s' LIMIT 1",
dbesc($db->database_name()));
$showwarning = false;
$warningtext = array();
if (dbm::is_result($r)) {
$showwarning = true;
$warningtext[] = sprintf(t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the <tt>convert_innodb.sql</tt> in the <tt>/util</tt> directory of your Friendica installation.<br />'), 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
}
// MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements
if ((version_compare($db->server_info(), '5.7.4') >= 0) AND
!(strpos($db->server_info(), 'MariaDB') !== false)) {
$warningtext[] = t('You are using a MySQL version which does not support all features that Friendica uses. You should consider switching to MariaDB.');
}
$r = q("SELECT `page-flags`, COUNT(`uid`) AS `count` FROM `user` GROUP BY `page-flags`");
$accounts = array(
array(t('Normal Account'), 0),
@ -478,7 +493,9 @@ function admin_page_summary(&$a) {
'$platform' => FRIENDICA_PLATFORM,
'$codename' => FRIENDICA_CODENAME,
'$build' => get_config('system','build'),
'$plugins' => array(t('Active plugins'), $a->plugins)
'$plugins' => array(t('Active plugins'), $a->plugins),
'$showwarning' => $showwarning,
'$warningtext' => $warningtext
));
}
@ -1388,6 +1405,7 @@ function admin_page_users(&$a){
'$h_deleted' => t('User waiting for permanent deletion'),
'$th_pending' => array(t('Request date'), t('Name'), t('Email')),
'$no_pending' => t('No registrations.'),
'$pendingnotetext' => t('Note from the user'),
'$approve' => t('Approve'),
'$deny' => t('Deny'),
'$delete' => t('Delete'),

View file

@ -1,17 +1,21 @@
<?php
/*
* Module: dfrn_confirm
/**
* @file mod/dfrn_confirm.php
* @brief Module: dfrn_confirm
* Purpose: Friendship acceptance for DFRN contacts
*
*.
* There are two possible entry points and three scenarios.
*
*.
* 1. A form was submitted by our user approving a friendship that originated elsewhere.
* This may also be called from dfrn_request to automatically approve a friendship.
*
* 2. We may be the target or other side of the conversation to scenario 1, and will
* interact with that process on our own user's behalf.
*
*.
* @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
* You also find a graphic which describes the confirmation process at
* https://github.com/friendica/friendica/blob/master/spec/dfrn2_contact_confirmation.png
*/
require_once('include/enotify.php');
@ -22,7 +26,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
if(is_array($handsfree)) {
/**
/*
* We were called directly from dfrn_request due to automatic friend acceptance.
* Any $_POST parameters we may require are supplied in the $handsfree array.
*
@ -37,7 +41,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
$node = $a->argv[1];
}
/**
/*
*
* Main entry point. Scenario 1. Our user received a friend request notification (perhaps
* from another site) and clicked 'Approve'.
@ -87,7 +91,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
$activity = ((x($_POST,'activity')) ? intval($_POST['activity']) : 0 );
}
/**
/*
*
* Ensure that dfrn_id has precedence when we go to find the contact record.
* We only want to search based on contact id if there is no dfrn_id,
@ -103,7 +107,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
logger('Confirming follower with contact_id: ' . $cid);
/**
/*
*
* The other person will have been issued an ID when they first requested friendship.
* Locate their record. At this time, their record will have both pending and blocked set to 1.
@ -139,7 +143,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
if($network === NETWORK_DFRN) {
/**
/*
*
* Generate a key pair for all further communications with this person.
* We have a keypair for every contact, and a site key for unknown people.
@ -166,7 +170,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
$params = array();
/**
/*
*
* Per the DFRN protocol, we will verify both ends by encrypting the dfrn_id with our
* site private key (person on the other end can decrypt it with our site public key).
@ -212,7 +216,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
logger('Confirm: posting data to ' . $dfrn_confirm . ': ' . print_r($params,true), LOGGER_DATA);
/**
/*
*
* POST all this stuff to the other site.
* Temporarily raise the network timeout to 120 seconds because the default 60
@ -506,7 +510,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
//NOTREACHED
}
/**
/*
*
*
* End of Scenario 1. [Local confirmation of remote friend request].

View file

@ -1,5 +1,10 @@
<?php
/**
* @file mod/dfrn_notify.php
* @brief The dfrn notify endpoint
* @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
*/
require_once('include/items.php');
require_once('include/dfrn.php');
require_once('include/event.php');
@ -7,7 +12,7 @@ require_once('include/event.php');
require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
function dfrn_notify_post(&$a) {
logger(__function__, LOGGER_TRACE);
logger(__function__, LOGGER_TRACE);
$dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : '');
$dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version'] : 2.0);
$challenge = ((x($_POST,'challenge')) ? notags(trim($_POST['challenge'])) : '');
@ -117,7 +122,7 @@ function dfrn_notify_post(&$a) {
if($dissolve == 1) {
/**
/*
* Relationship is dissolved permanently
*/

View file

@ -1,12 +1,15 @@
<?php
/**
*
* Module: dfrn_request
* @file mod/dfrn_request.php
* @brief Module: dfrn_request
*
* Purpose: Handles communication associated with the issuance of
* friend requests.
*
* @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
* You also find a graphic which describes the confirmation process at
* https://github.com/friendica/friendica/blob/master/spec/dfrn2_contact_request.png
*/
require_once('include/enotify.php');
@ -14,7 +17,6 @@ require_once('include/Scrape.php');
require_once('include/Probe.php');
require_once('include/group.php');
if(! function_exists('dfrn_request_init')) {
function dfrn_request_init(&$a) {
if($a->argc > 1)
@ -22,7 +24,7 @@ function dfrn_request_init(&$a) {
profile_load($a,$which);
return;
}}
}
/**
@ -40,8 +42,6 @@ function dfrn_request_init(&$a) {
* After logging in, we click 'submit' to approve the linkage.
*
*/
if(! function_exists('dfrn_request_post')) {
function dfrn_request_post(&$a) {
if(($a->argc != 2) || (! count($a->profile))) {
@ -55,7 +55,7 @@ function dfrn_request_post(&$a) {
}
/**
/*
*
* Scenario 2: We've introduced ourself to another cell, then have been returned to our own cell
* to confirm the request, and then we've clicked submit (perhaps after logging in).
@ -65,7 +65,7 @@ function dfrn_request_post(&$a) {
if((x($_POST,'localconfirm')) && ($_POST['localconfirm'] == 1)) {
/**
/*
* Ensure this is a valid request
*/
@ -77,23 +77,24 @@ function dfrn_request_post(&$a) {
$confirm_key = ((x($_POST,'confirm_key')) ? $_POST['confirm_key'] : "");
$hidden = ((x($_POST,'hidden-contact')) ? intval($_POST['hidden-contact']) : 0);
$contact_record = null;
$blocked = 1;
$pending = 1;
if(x($dfrn_url)) {
/**
/*
* Lookup the contact based on their URL (which is the only unique thing we have at the moment)
*/
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND (`url` = '%s' OR `nurl` = '%s') AND `self` = 0 LIMIT 1",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND NOT `self` LIMIT 1",
intval(local_user()),
dbesc($dfrn_url),
dbesc(normalise_link($dfrn_url))
);
if(count($r)) {
if(strlen($r[0]['dfrn-id'])) {
/**
/*
* We don't need to be here. It has already happened.
*/
@ -113,7 +114,7 @@ function dfrn_request_post(&$a) {
}
else {
/**
/*
* Scrape the other site's profile page to pick up the dfrn links, key, fn, and photo
*/
@ -141,19 +142,18 @@ function dfrn_request_post(&$a) {
$photo = $parms["photo"];
/********* Escape the entire array ********/
// Escape the entire array
dbesc_array($parms);
/******************************************/
/**
/*
* Create a contact record on our site for the other person
*/
$r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `nurl`, `addr`, `name`, `nick`, `photo`, `site-pubkey`,
`request`, `confirm`, `notify`, `poll`, `poco`, `network`, `aes_allow`, `hidden`)
VALUES ( %d, '%s', '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
`request`, `confirm`, `notify`, `poll`, `poco`, `network`, `aes_allow`, `hidden`, `blocked`, `pending`)
VALUES ( %d, '%s', '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d)",
intval(local_user()),
datetime_convert(),
dbesc($dfrn_url),
@ -170,7 +170,9 @@ function dfrn_request_post(&$a) {
$parms['dfrn-poco'],
dbesc(NETWORK_DFRN),
intval($aes_allow),
intval($hidden)
intval($hidden),
intval($blocked),
intval($pending)
);
}
@ -195,7 +197,7 @@ function dfrn_request_post(&$a) {
} else
$forwardurl = $a->get_baseurl()."/contacts";
/**
/*
* Allow the blocked remote notification to complete
*/
@ -222,7 +224,7 @@ function dfrn_request_post(&$a) {
return; // NOTREACHED
}
/**
/*
* Otherwise:
*
* Scenario 1:
@ -256,11 +258,13 @@ function dfrn_request_post(&$a) {
$contact_record = null;
$failed = false;
$parms = null;
$blocked = 1;
$pending = 1;
if( x($_POST,'dfrn_url')) {
/**
/*
* Block friend request spam
*/
@ -277,7 +281,7 @@ function dfrn_request_post(&$a) {
}
}
/**
/*
*
* Cleanup old introductions that remain blocked.
* Also remove the contact record, but only if there is no existing relationship
@ -304,7 +308,7 @@ function dfrn_request_post(&$a) {
}
}
/**
/*
*
* Cleanup any old email intros - which will have a greater lifetime
*/
@ -354,8 +358,6 @@ function dfrn_request_post(&$a) {
$nurl = normalise_url($host);
$poll = 'email ' . random_string();
$notify = 'smtp ' . random_string();
$blocked = 1;
$pending = 1;
$network = NETWORK_MAIL2;
$rel = CONTACT_IS_FOLLOWER;
@ -540,8 +542,8 @@ function dfrn_request_post(&$a) {
dbesc_array($parms);
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `name`, `nick`, `issued-id`, `photo`, `site-pubkey`,
`request`, `confirm`, `notify`, `poll`, `poco`, `network` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
`request`, `confirm`, `notify`, `poll`, `poco`, `network`, `blocked`, `pending` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
intval($uid),
dbesc(datetime_convert()),
$parms['url'],
@ -557,7 +559,9 @@ function dfrn_request_post(&$a) {
$parms['dfrn-notify'],
$parms['dfrn-poll'],
$parms['dfrn-poco'],
dbesc(NETWORK_DFRN)
dbesc(NETWORK_DFRN),
intval($blocked),
intval($pending)
);
// find the contact record we just created
@ -613,7 +617,7 @@ function dfrn_request_post(&$a) {
// END $network === NETWORK_DFRN
} elseif (($network != NETWORK_PHANTOM) AND ($url != "")) {
/**
/*
*
* Substitute our user's feed URL into $url template
* Send the subscriber home to subscribe
@ -642,12 +646,9 @@ function dfrn_request_post(&$a) {
}
} return;
}}
}
if(! function_exists('dfrn_request_content')) {
function dfrn_request_content(&$a) {
if(($a->argc != 2) || (! count($a->profile)))
@ -781,7 +782,7 @@ function dfrn_request_content(&$a) {
}
else {
/**
/*
* Normal web request. Display our user's introduction form.
*/
@ -793,7 +794,7 @@ function dfrn_request_content(&$a) {
}
/**
/*
* Try to auto-fill the profile address
*/
@ -816,7 +817,7 @@ function dfrn_request_content(&$a) {
$target_addr = $a->profile['nickname'] . '@' . substr(z_root(), strpos(z_root(),'://') + 3 );
/**
/*
*
* The auto_request form only has the profile address
* because nobody is going to read the comments and
@ -881,4 +882,4 @@ function dfrn_request_content(&$a) {
}
return; // Somebody is fishing.
}}
}

View file

@ -744,6 +744,9 @@ function item_post(&$a) {
if($preview) {
require_once('include/conversation.php');
// We set the datarray ID to -1 because in preview mode the dataray
// doesn't have an ID.
$datarray["id"] = -1;
$o = conversation($a,array(array_merge($contact_record,$datarray)),'search', false, true);
logger('preview: ' . $o);
echo json_encode(array('preview' => $o));

View file

@ -395,10 +395,10 @@ function network_content(&$a, $update = 0) {
if($group) {
if(($t = group_public_members($group)) && (! get_pconfig(local_user(),'system','nowarn_insecure'))) {
notice( sprintf( tt('Warning: This group contains %s member from an insecure network.',
'Warning: This group contains %s members from an insecure network.',
$t), $t ) . EOL);
notice( t('Private messages to this group are at risk of public disclosure.') . EOL);
notice(sprintf(tt("Warning: This group contains %s member from a network that doesn't allow non public messages.",
"Warning: This group contains %s members from a network that doesn't allow non public messages.",
$t), $t).EOL);
notice(t("Messages in this group won't be send to these receivers.").EOL);
}
}
@ -453,6 +453,7 @@ function network_content(&$a, $update = 0) {
if ($nouveau OR strlen($file) OR $update) {
$sql_table = "`item`";
$sql_parent = "`parent`";
$sql_post_table = " INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`";
}
$sql_nets = (($nets) ? sprintf(" and $sql_table.`network` = '%s' ", dbesc($nets)) : '');
@ -487,9 +488,9 @@ function network_content(&$a, $update = 0) {
$gcontact_str_self = $self[0]["gid"];
}
$sql_post_table = " INNER JOIN `item` AS `temp1` ON `temp1`.`id` = ".$sql_table.".".$sql_parent;
$sql_extra3 .= " AND ($sql_table.`contact-id` IN ($contact_str) ";
$sql_extra3 .= " OR ($sql_table.`contact-id` = '$contact_str_self' AND `temp1`.`allow_gid` LIKE '".protect_sprintf('%<'.intval($group).'>%')."' AND `temp1`.`private`))";
$sql_post_table .= " INNER JOIN `item` AS `temp1` ON `temp1`.`id` = ".$sql_table.".".$sql_parent;
$sql_extra3 .= " AND (`thread`.`contact-id` IN ($contact_str) ";
$sql_extra3 .= " OR (`thread`.`contact-id` = '$contact_str_self' AND `temp1`.`allow_gid` LIKE '".protect_sprintf('%<'.intval($group).'>%')."' AND `temp1`.`private`))";
} else {
$sql_extra3 .= " AND false ";
info( t('Group is empty'));
@ -503,7 +504,7 @@ function network_content(&$a, $update = 0) {
elseif($cid) {
$r = qu("SELECT `id`,`name`,`network`,`writable`,`nurl`, `forum`, `prv`, `contact-type`, `addr`, `thumb`, `location` FROM `contact` WHERE `id` = %d
AND `blocked` = 0 AND `pending` = 0 LIMIT 1",
AND (NOT `blocked` OR `pending`) LIMIT 1",
intval($cid)
);
if(count($r)) {
@ -569,7 +570,7 @@ function network_content(&$a, $update = 0) {
if($tag) {
$sql_extra = "";
$sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
$sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
dbesc(protect_sprintf($search)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), intval(local_user()));
$sql_order = "`item`.`id`";
$order_mode = "id";
@ -583,7 +584,7 @@ function network_content(&$a, $update = 0) {
}
}
if(strlen($file)) {
$sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
$sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
dbesc(protect_sprintf($file)), intval(TERM_OBJ_POST), intval(TERM_FILE), intval(local_user()));
$sql_order = "`item`.`id`";
$order_mode = "id";
@ -602,7 +603,7 @@ function network_content(&$a, $update = 0) {
if(get_config('system', 'old_pager')) {
$r = qu("SELECT COUNT(*) AS `total`
FROM $sql_table $sql_post_table INNER JOIN `contact` ON `contact`.`id` = $sql_table.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE $sql_table.`uid` = %d AND $sql_table.`visible` AND NOT $sql_table.`deleted`
$sql_extra2 $sql_extra3
$sql_extra $sql_nets ",
@ -680,7 +681,7 @@ function network_content(&$a, $update = 0) {
$r = qu("SELECT `item`.`parent` AS `item_id`, `item`.`network` AS `item_network`, `contact`.`uid` AS `contact_uid`
FROM $sql_table $sql_post_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` $sql_extra4
AND NOT `item`.`moderated` AND `item`.`unseen`
$sql_extra3 $sql_extra $sql_nets
@ -690,7 +691,7 @@ function network_content(&$a, $update = 0) {
} else {
$r = qu("SELECT `thread`.`iid` AS `item_id`, `thread`.`network` AS `item_network`, `contact`.`uid` AS `contact_uid`
FROM $sql_table $sql_post_table STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated`
$sql_extra2 $sql_extra3 $sql_extra $sql_nets

View file

@ -1,516 +1,176 @@
<?php
/**
* @file mod/parse_url.php
* @brief The parse_url module
*
* @todo https://developers.google.com/+/plugins/snippet/
* This module does parse an url for embedable content (audio, video, image files or link)
* information and does format this information to BBCode or html (this depends
* on the user settings - default is BBCode output).
* If the user has enabled the richtext editor setting the output will be in html
* (Note: This is not always possible and in some case not useful because
* the richtext editor doesn't support all kind of html).
* Otherwise the output will be constructed BBCode.
*
* @verbatim
* <meta itemprop="name" content="Toller Titel">
* <meta itemprop="description" content="Eine tolle Beschreibung">
* <meta itemprop="image" content="http://maple.libertreeproject.org/images/tree-icon.png">
*
* <body itemscope itemtype="http://schema.org/Product">
* <h1 itemprop="name">Shiny Trinket</h1>
* <img itemprop="image" src="{image-url}" />
* <p itemprop="description">Shiny trinkets are shiny.</p>
* </body>
* @endverbatim
* @see ParseUrl::getSiteinfo() for more information about scraping embeddable content
*/
if(!function_exists('deletenode')) {
function deletenode(&$doc, $node)
{
$xpath = new DomXPath($doc);
$list = $xpath->query("//".$node);
foreach ($list as $child)
$child->parentNode->removeChild($child);
}
}
use \Friendica\ParseUrl;
function completeurl($url, $scheme) {
$urlarr = parse_url($url);
if (isset($urlarr["scheme"]))
return($url);
$schemearr = parse_url($scheme);
$complete = $schemearr["scheme"]."://".$schemearr["host"];
if (@$schemearr["port"] != "")
$complete .= ":".$schemearr["port"];
if(strpos($urlarr['path'],'/') !== 0)
$complete .= '/';
$complete .= $urlarr["path"];
if (@$urlarr["query"] != "")
$complete .= "?".$urlarr["query"];
if (@$urlarr["fragment"] != "")
$complete .= "#".$urlarr["fragment"];
return($complete);
}
function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
if ($url == "")
return false;
$r = q("SELECT * FROM `parsed_url` WHERE `url` = '%s' AND `guessing` = %d AND `oembed` = %d",
dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed));
if ($r)
$data = $r[0]["content"];
if (!is_null($data)) {
$data = unserialize($data);
return $data;
}
$data = parseurl_getsiteinfo($url, $no_guessing, $do_oembed);
q("INSERT INTO `parsed_url` (`url`, `guessing`, `oembed`, `content`, `created`) VALUES ('%s', %d, %d, '%s', '%s')
ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'",
dbesc(normalise_link($url)), intval(!$no_guessing), intval($do_oembed),
dbesc(serialize($data)), dbesc(datetime_convert()),
dbesc(serialize($data)), dbesc(datetime_convert()));
return $data;
}
function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
require_once("include/network.php");
require_once("include/Photo.php");
$a = get_app();
$siteinfo = array();
// Check if the URL does contain a scheme
$scheme = parse_url($url, PHP_URL_SCHEME);
if ($scheme == "") {
$url = "http://".trim($url, "/");
}
if ($count > 10) {
logger("parseurl_getsiteinfo: Endless loop detected for ".$url, LOGGER_DEBUG);
return($siteinfo);
}
$url = trim($url, "'");
$url = trim($url, '"');
$url = original_url($url);
$siteinfo["url"] = $url;
$siteinfo["type"] = "link";
$check_cert = get_config('system','verifyssl');
$stamp1 = microtime(true);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
$header = curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
curl_close($ch);
$a->save_timestamp($stamp1, "network");
if ((($curl_info['http_code'] == "301") OR ($curl_info['http_code'] == "302") OR ($curl_info['http_code'] == "303") OR ($curl_info['http_code'] == "307"))
AND (($curl_info['redirect_url'] != "") OR ($curl_info['location'] != ""))) {
if ($curl_info['redirect_url'] != "")
$siteinfo = parseurl_getsiteinfo($curl_info['redirect_url'], $no_guessing, $do_oembed, ++$count);
else
$siteinfo = parseurl_getsiteinfo($curl_info['location'], $no_guessing, $do_oembed, ++$count);
return($siteinfo);
}
// if the file is too large then exit
if ($curl_info["download_content_length"] > 1000000)
return($siteinfo);
// if it isn't a HTML file then exit
if (($curl_info["content_type"] != "") AND !strstr(strtolower($curl_info["content_type"]),"html"))
return($siteinfo);
if ($do_oembed) {
require_once("include/oembed.php");
$oembed_data = oembed_fetch_url($url);
if (!in_array($oembed_data->type, array("error", "rich"))) {
$siteinfo["type"] = $oembed_data->type;
}
if (($oembed_data->type == "link") AND ($siteinfo["type"] != "photo")) {
if (isset($oembed_data->title))
$siteinfo["title"] = $oembed_data->title;
if (isset($oembed_data->description))
$siteinfo["text"] = trim($oembed_data->description);
if (isset($oembed_data->thumbnail_url))
$siteinfo["image"] = $oembed_data->thumbnail_url;
}
}
$stamp1 = microtime(true);
// Now fetch the body as well
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $a->get_useragent());
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, (($check_cert) ? 2 : false));
$header = curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$http_code = $curl_info['http_code'];
curl_close($ch);
$a->save_timestamp($stamp1, "network");
// Fetch the first mentioned charset. Can be in body or header
$charset = "";
if (preg_match('/charset=(.*?)['."'".'"\s\n]/', $header, $matches))
$charset = trim(trim(trim(array_pop($matches)), ';,'));
if ($charset == "")
$charset = "utf-8";
$pos = strpos($header, "\r\n\r\n");
if ($pos)
$body = trim(substr($header, $pos));
else
$body = $header;
if (($charset != '') AND (strtoupper($charset) != "UTF-8")) {
logger("parseurl_getsiteinfo: detected charset ".$charset, LOGGER_DEBUG);
//$body = mb_convert_encoding($body, "UTF-8", $charset);
$body = iconv($charset, "UTF-8//TRANSLIT", $body);
}
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new DOMDocument();
@$doc->loadHTML($body);
deletenode($doc, 'style');
deletenode($doc, 'script');
deletenode($doc, 'option');
deletenode($doc, 'h1');
deletenode($doc, 'h2');
deletenode($doc, 'h3');
deletenode($doc, 'h4');
deletenode($doc, 'h5');
deletenode($doc, 'h6');
deletenode($doc, 'ol');
deletenode($doc, 'ul');
$xpath = new DomXPath($doc);
$list = $xpath->query("//meta[@content]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
if (@$attr["http-equiv"] == 'refresh') {
$path = $attr["content"];
$pathinfo = explode(";", $path);
$content = "";
foreach ($pathinfo AS $value) {
if (substr(strtolower($value), 0, 4) == "url=")
$content = substr($value, 4);
}
if ($content != "") {
$siteinfo = parseurl_getsiteinfo($content, $no_guessing, $do_oembed, ++$count);
return($siteinfo);
}
}
}
$list = $xpath->query("//title");
if ($list->length > 0)
$siteinfo["title"] = $list->item(0)->nodeValue;
//$list = $xpath->query("head/meta[@name]");
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
if ($attr["content"] != "")
switch (strtolower($attr["name"])) {
case "fulltitle":
$siteinfo["title"] = $attr["content"];
break;
case "description":
$siteinfo["text"] = $attr["content"];
break;
case "thumbnail":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:image":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:image:src":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:card":
if (($siteinfo["type"] == "") OR ($attr["content"] == "photo"))
$siteinfo["type"] = $attr["content"];
break;
case "twitter:description":
$siteinfo["text"] = $attr["content"];
break;
case "twitter:title":
$siteinfo["title"] = $attr["content"];
break;
case "dc.title":
$siteinfo["title"] = $attr["content"];
break;
case "dc.description":
$siteinfo["text"] = $attr["content"];
break;
case "keywords":
$keywords = explode(",", $attr["content"]);
break;
case "news_keywords":
$keywords = explode(",", $attr["content"]);
break;
}
if ($siteinfo["type"] == "summary")
$siteinfo["type"] = "link";
}
if (isset($keywords)) {
$siteinfo["keywords"] = array();
foreach ($keywords as $keyword)
if (!in_array(trim($keyword), $siteinfo["keywords"]))
$siteinfo["keywords"][] = trim($keyword);
}
//$list = $xpath->query("head/meta[@property]");
$list = $xpath->query("//meta[@property]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8"));
if ($attr["content"] != "")
switch (strtolower($attr["property"])) {
case "og:image":
$siteinfo["image"] = $attr["content"];
break;
case "og:title":
$siteinfo["title"] = $attr["content"];
break;
case "og:description":
$siteinfo["text"] = $attr["content"];
break;
}
}
if ((@$siteinfo["image"] == "") AND !$no_guessing) {
$list = $xpath->query("//img[@src]");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
$src = completeurl($attr["src"], $url);
$photodata = get_photo_info($src);
if (($photodata) && ($photodata[0] > 150) and ($photodata[1] > 150)) {
if ($photodata[0] > 300) {
$photodata[1] = round($photodata[1] * (300 / $photodata[0]));
$photodata[0] = 300;
}
if ($photodata[1] > 300) {
$photodata[0] = round($photodata[0] * (300 / $photodata[1]));
$photodata[1] = 300;
}
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
}
} elseif ($siteinfo["image"] != "") {
$src = completeurl($siteinfo["image"], $url);
unset($siteinfo["image"]);
$photodata = get_photo_info($src);
if (($photodata) && ($photodata[0] > 10) and ($photodata[1] > 10))
$siteinfo["images"][] = array("src"=>$src,
"width"=>$photodata[0],
"height"=>$photodata[1]);
}
if ((@$siteinfo["text"] == "") AND (@$siteinfo["title"] != "") AND !$no_guessing) {
$text = "";
$list = $xpath->query("//div[@class='article']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
if ($text == "") {
$list = $xpath->query("//div[@class='content']");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
// If none text was found then take the paragraph content
if ($text == "") {
$list = $xpath->query("//p");
foreach ($list as $node)
if (strlen($node->nodeValue) > 40)
$text .= " ".trim($node->nodeValue);
}
if ($text != "") {
$text = trim(str_replace(array("\n", "\r"), array(" ", " "), $text));
while (strpos($text, " "))
$text = trim(str_replace(" ", " ", $text));
$siteinfo["text"] = trim(html_entity_decode(substr($text,0,350), ENT_QUOTES, "UTF-8").'...');
}
}
logger("parseurl_getsiteinfo: Siteinfo for ".$url." ".print_r($siteinfo, true), LOGGER_DEBUG);
call_hooks('getsiteinfo', $siteinfo);
return($siteinfo);
}
function arr_add_hashes(&$item,$k) {
$item = '#' . $item;
}
require_once("include/items.php");
function parse_url_content(&$a) {
require_once("include/items.php");
$text = null;
$str_tags = '';
$str_tags = "";
$textmode = false;
if(local_user() && (! feature_enabled(local_user(),'richtext')))
if (local_user() && (!feature_enabled(local_user(), "richtext"))) {
$textmode = true;
}
//if($textmode)
$br = (($textmode) ? "\n" : '<br />');
$br = (($textmode) ? "\n" : "<br />");
if(x($_GET,'binurl'))
$url = trim(hex2bin($_GET['binurl']));
else
$url = trim($_GET['url']);
if (x($_GET,"binurl")) {
$url = trim(hex2bin($_GET["binurl"]));
} else {
$url = trim($_GET["url"]);
}
if($_GET['title'])
$title = strip_tags(trim($_GET['title']));
if ($_GET["title"]) {
$title = strip_tags(trim($_GET["title"]));
}
if($_GET['description'])
$text = strip_tags(trim($_GET['description']));
if ($_GET["description"]) {
$text = strip_tags(trim($_GET["description"]));
}
if($_GET['tags']) {
$arr_tags = str_getcsv($_GET['tags']);
if(count($arr_tags)) {
array_walk($arr_tags,'arr_add_hashes');
$str_tags = $br . implode(' ',$arr_tags) . $br;
if ($_GET["tags"]) {
$arr_tags = ParseUrl::convertTagsToArray($_GET["tags"]);
if (count($arr_tags)) {
$str_tags = $br . implode(" ", $arr_tags) . $br;
}
}
// add url scheme if missing
// Add url scheme if it is missing
$arrurl = parse_url($url);
if (!x($arrurl, 'scheme')) {
if (x($arrurl, 'host'))
if (!x($arrurl, "scheme")) {
if (x($arrurl, "host")) {
$url = "http:".$url;
else
} else {
$url = "http://".$url;
}
}
logger('parse_url: ' . $url);
logger("prse_url: " . $url);
if($textmode)
$template = '[bookmark=%s]%s[/bookmark]%s';
else
// Check if the URL is an image, video or audio file. If so format
// the URL with the corresponding BBCode media tag
$redirects = 0;
// Fetch the header of the URL
$result = z_fetch_url($url, false, $redirects, array("novalidate" => true, "nobody" => true));
if($result["success"]) {
// Convert the header fields into an array
$hdrs = array();
$h = explode("\n", $result["header"]);
foreach ($h as $l) {
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
$hdrs[$k] = $v;
}
if (array_key_exists("Content-Type", $hdrs)) {
$type = $hdrs["Content-Type"];
}
if ($type) {
if(stripos($type, "image/") !== false) {
echo $br . "[img]" . $url . "[/img]" . $br;
killme();
}
if (stripos($type, "video/") !== false) {
echo $br . "[video]" . $url . "[/video]" . $br;
killme();
}
if (stripos($type, "audio/") !== false) {
echo $br . "[audio]" . $url . "[/audio]" . $br;
killme();
}
}
}
if ($textmode) {
$template = "[bookmark=%s]%s[/bookmark]%s";
} else {
$template = "<a class=\"bookmark\" href=\"%s\" >%s</a>%s";
}
$arr = array('url' => $url, 'text' => '');
$arr = array("url" => $url, "text" => "");
call_hooks('parse_link', $arr);
call_hooks("parse_link", $arr);
if(strlen($arr['text'])) {
echo $arr['text'];
if (strlen($arr["text"])) {
echo $arr["text"];
killme();
}
// If there is allready some content information submitted we don't
// need to parse the url for content.
if ($url && $title && $text) {
if($url && $title && $text) {
$title = str_replace(array("\r","\n"),array("",""),$title);
$title = str_replace(array("\r","\n"),array('',''),$title);
if($textmode)
$text = '[quote]' . trim($text) . '[/quote]' . $br;
else {
$text = '<blockquote>' . htmlspecialchars(trim($text)) . '</blockquote><br />';
if ($textmode) {
$text = "[quote]" . trim($text) . "[/quote]" . $br;
} else {
$text = "<blockquote>" . htmlspecialchars(trim($text)) . "</blockquote><br />";
$title = htmlspecialchars($title);
}
$result = sprintf($template,$url,($title) ? $title : $url,$text) . $str_tags;
$result = sprintf($template, $url, ($title) ? $title : $url, $text) . $str_tags;
logger('parse_url (unparsed): returns: ' . $result);
logger("parse_url (unparsed): returns: " . $result);
echo $result;
killme();
}
$siteinfo = parseurl_getsiteinfo($url);
// Fetch the information directly from the webpage
$siteinfo = ParseUrl::getSiteinfo($url);
unset($siteinfo["keywords"]);
// Format it as BBCode attachment
$info = add_page_info_data($siteinfo);
if (!$textmode)
if (!$textmode) {
// Replace ' with - not perfect - but the richtext editor has problems otherwise
$info = str_replace(array("&#039;"), array("&#8217;"), $info);
}
echo $info;
killme();
}
?>
/**
* @brief Legacy function to call ParseUrl::getSiteinfoCached
*
* Note: We have moved the function to ParseUrl.php. This function is only for
* legacy support and will be remove in the future
*
* @param type $url The url of the page which should be scraped
* @param type $no_guessing If true the parse doens't search for
* preview pictures
* @param type $do_oembed The false option is used by the function fetch_oembed()
* to avoid endless loops
*
* @return array which contains needed data for embedding
*
* @see ParseUrl::getSiteinfoCached()
*
* @todo Remove this function after all Addons has been changed to use
* ParseUrl::getSiteinfoCached
*/
function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
$siteinfo = ParseUrl::getSiteinfoCached($url, $no_guessing, $do_oembed);
return $siteinfo;
}

View file

@ -3,43 +3,119 @@ require_once("include/datetime.php");
require_once('include/bbcode.php');
require_once('include/ForumManager.php');
require_once('include/group.php');
require_once("mod/proxy.php");
require_once('mod/proxy.php');
require_once('include/xml.php');
function ping_init(&$a) {
/**
* @brief Outputs the counts and the lists of various notifications
*
* The output format can be controlled via the GET parameter 'format'. It can be
* - xml (deprecated legacy default)
* - json (outputs JSONP with the 'callback' GET parameter)
*
* Expected JSON structure:
* {
* "result": {
* "intro": 0,
* "mail": 0,
* "net": 0,
* "home": 0,
* "register": 0,
* "all-events": 0,
* "all-events-today": 0,
* "events": 0,
* "events-today": 0,
* "birthdays": 0,
* "birthdays-today": 0,
* "groups": [ ],
* "forums": [ ],
* "notify": 0,
* "notifications": [ ],
* "sysmsgs": {
* "notice": [ ],
* "info": [ ]
* }
* }
* }
*
* @param App $a The Friendica App instance
*/
function ping_init(App $a)
{
$format = 'xml';
$xmlhead = "<"."?xml version='1.0' encoding='UTF-8' ?".">";
if (isset($_GET['format']) && $_GET['format'] == 'json') {
$format = 'json';
}
$tags = array();
$comments = array();
$likes = array();
$dislikes = array();
$friends = array();
$posts = array();
$regs = array();
$mails = array();
$notifications = array();
$intro_count = 0;
$mail_count = 0;
$home_count = 0;
$network_count = 0;
$register_count = 0;
$sysnotify_count = 0;
$groups_unseen = array();
$forums_unseen = array();
$all_events = 0;
$all_events_today = 0;
$events = 0;
$events_today = 0;
$birthdays = 0;
$birthdays_today = 0;
$data = array();
$data['intro'] = $intro_count;
$data['mail'] = $mail_count;
$data['net'] = $network_count;
$data['home'] = $home_count;
$data['register'] = $register_count;
$data['all-events'] = $all_events;
$data['all-events-today'] = $all_events_today;
$data['events'] = $events;
$data['events-today'] = $events_today;
$data['birthdays'] = $birthdays;
$data['birthdays-today'] = $birthdays_today;
if (local_user()){
// Different login session than the page that is calling us.
if (intval($_GET['uid']) && intval($_GET['uid']) != local_user()) {
$data = array("invalid" => 1);
header("Content-type: text/xml");
echo xml::from_array(array("result" => $data), $xml);
$data = array('result' => array('invalid' => 1));
if ($format == 'json') {
if (isset($_GET['callback'])) {
// JSONP support
header("Content-type: application/javascript");
echo $_GET['callback'] . '(' . json_encode($data) . ')';
} else {
header("Content-type: application/json");
echo json_encode($data);
}
} else {
header("Content-type: text/xml");
echo xml::from_array($data, $xml);
}
killme();
}
$notifs = ping_get_notifications(local_user());
$sysnotify = 0; // we will update this in a moment
$tags = array();
$comments = array();
$likes = array();
$dislikes = array();
$friends = array();
$posts = array();
$regs = array();
$mails = array();
$home = 0;
$network = 0;
$groups_unseen = array();
$forums_unseen = array();
$r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`wall`, `item`.`author-name`,
$items_unseen = qu("SELECT `item`.`id`, `item`.`parent`, `item`.`verb`, `item`.`wall`, `item`.`author-name`,
`item`.`contact-id`, `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object`,
`pitem`.`author-name` as `pname`, `pitem`.`author-link` as `plink`
FROM `item` INNER JOIN `item` as `pitem` ON `pitem`.`id`=`item`.`parent`
`pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`
FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id` = `item`.`parent`
WHERE `item`.`unseen` = 1 AND `item`.`visible` = 1 AND
`item`.`deleted` = 0 AND `item`.`uid` = %d AND `pitem`.`parent` != 0
AND `item`.`contact-id` != %d
@ -47,110 +123,90 @@ function ping_init(&$a) {
intval(local_user()), intval(local_user())
);
if (dbm::is_result($r)) {
$arr = array('items' => $r);
if (dbm::is_result($items_unseen)) {
$arr = array('items' => $items_unseen);
call_hooks('network_ping', $arr);
foreach ($r as $it) {
if ($it['wall'])
$home ++;
else
$network ++;
switch($it['verb']){
case ACTIVITY_TAG:
$obj = parse_xml_string($xmlhead.$it['object']);
$it['tname'] = $obj->content;
$tags[] = $it;
break;
case ACTIVITY_LIKE:
$likes[] = $it;
break;
case ACTIVITY_DISLIKE:
$dislikes[] = $it;
break;
case ACTIVITY_FRIEND:
$obj = parse_xml_string($xmlhead.$it['object']);
$it['fname'] = $obj->title;
$friends[] = $it;
break;
default:
if ($it['parent']!=$it['id']) {
$comments[] = $it;
} else {
if (!$it['wall'])
$posts[] = $it;
}
foreach ($items_unseen as $item) {
if ($item['wall']) {
$home_count++;
} else {
$network_count++;
}
}
}
if ($network) {
if (intval(feature_enabled(local_user(),'groups'))) {
if ($network_count) {
if (intval(feature_enabled(local_user(), 'groups'))) {
// Find out how unseen network posts are spread across groups
$groups_unseen = groups_count_unseen();
$group_counts = groups_count_unseen();
if (dbm::is_result($group_counts)) {
foreach ($group_counts as $group_count) {
if ($group_count['count'] > 0) {
$groups_unseen[] = $group_count;
}
}
}
}
if (intval(feature_enabled(local_user(),'forumlist_widget'))) {
$forums_unseen = ForumManager::count_unseen_items();
if (intval(feature_enabled(local_user(), 'forumlist_widget'))) {
$forum_counts = ForumManager::count_unseen_items();
if (dbm::is_result($forums_counts)) {
foreach ($forums_counts as $forum_count) {
if ($forum_count['count'] > 0) {
$forums_unseen[] = $forum_count;
}
}
}
}
}
$intros1 = q("SELECT `intro`.`id`, `intro`.`datetime`,
$intros1 = qu("SELECT `intro`.`id`, `intro`.`datetime`,
`fcontact`.`name`, `fcontact`.`url`, `fcontact`.`photo`
FROM `intro` LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
WHERE `intro`.`uid` = %d AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`fid`!=0",
WHERE `intro`.`uid` = %d AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`fid` != 0",
intval(local_user())
);
$intros2 = q("SELECT `intro`.`id`, `intro`.`datetime`,
$intros2 = qu("SELECT `intro`.`id`, `intro`.`datetime`,
`contact`.`name`, `contact`.`url`, `contact`.`photo`
FROM `intro` LEFT JOIN `contact` ON `intro`.`contact-id` = `contact`.`id`
WHERE `intro`.`uid` = %d AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`contact-id`!=0",
WHERE `intro`.`uid` = %d AND `intro`.`blocked` = 0 AND `intro`.`ignore` = 0 AND `intro`.`contact-id` != 0",
intval(local_user())
);
$intro = count($intros1) + count($intros2);
$intro_count = count($intros1) + count($intros2);
$intros = $intros1+$intros2;
$myurl = $a->get_baseurl() . '/profile/' . $a->user['nickname'] ;
$mails = q("SELECT * FROM `mail`
$mails = qu("SELECT `id`, `from-name`, `from-url`, `from-photo`, `created` FROM `mail`
WHERE `uid` = %d AND `seen` = 0 AND `from-url` != '%s' ",
intval(local_user()),
dbesc($myurl)
);
$mail = count($mails);
$mail_count = count($mails);
if ($a->config['register_policy'] == REGISTER_APPROVE && is_site_admin()){
$regs = q("SELECT `contact`.`name`, `contact`.`url`, `contact`.`micro`, `register`.`created`, COUNT(*) as `total` FROM `contact` RIGHT JOIN `register` ON `register`.`uid`=`contact`.`uid` WHERE `contact`.`self`=1");
if ($regs)
$register = $regs[0]['total'];
} else {
$register = "0";
$regs = qu("SELECT `contact`.`name`, `contact`.`url`, `contact`.`micro`, `register`.`created`, COUNT(*) AS `total`
FROM `contact` RIGHT JOIN `register` ON `register`.`uid` = `contact`.`uid`
WHERE `contact`.`self` = 1");
if ($regs) {
$register_count = $regs[0]['total'];
}
}
$all_events = 0;
$all_events_today = 0;
$events = 0;
$events_today = 0;
$birthdays = 0;
$birthdays_today = 0;
$ev = q("SELECT count(`event`.`id`) as total, type, start, adjust FROM `event`
$ev = qu("SELECT count(`event`.`id`) AS total, type, start, adjust FROM `event`
WHERE `event`.`uid` = %d AND `start` < '%s' AND `finish` > '%s' and `ignore` = 0
ORDER BY `start` ASC ",
intval(local_user()),
dbesc(datetime_convert('UTC','UTC','now + 7 days')),
dbesc(datetime_convert('UTC','UTC','now'))
dbesc(datetime_convert('UTC', 'UTC', 'now + 7 days')),
dbesc(datetime_convert('UTC', 'UTC', 'now'))
);
if (dbm::is_result($ev)) {
$all_events = intval($ev[0]['total']);
if ($all_events) {
$str_now = datetime_convert('UTC',$a->timezone,'now','Y-m-d');
$str_now = datetime_convert('UTC', $a->timezone, 'now', 'Y-m-d');
foreach($ev as $x) {
$bd = false;
if ($x['type'] === 'birthday') {
@ -160,7 +216,7 @@ function ping_init(&$a) {
else {
$events ++;
}
if (datetime_convert('UTC',((intval($x['adjust'])) ? $a->timezone : 'UTC'), $x['start'],'Y-m-d') === $str_now) {
if (datetime_convert('UTC', ((intval($x['adjust'])) ? $a->timezone : 'UTC'), $x['start'], 'Y-m-d') === $str_now) {
$all_events_today ++;
if ($bd)
$birthdays_today ++;
@ -171,99 +227,70 @@ function ping_init(&$a) {
}
}
$data = array();
$data["intro"] = $intro;
$data["mail"] = $mail;
$data["net"] = $network;
$data["home"] = $home;
$data['intro'] = $intro_count;
$data['mail'] = $mail_count;
$data['net'] = $network_count;
$data['home'] = $home_count;
$data['register'] = $register_count;
if ($register!=0)
$data["register"] = $register;
$data['all-events'] = $all_events;
$data['all-events-today'] = $all_events_today;
$data['events'] = $events;
$data['events-today'] = $events_today;
$data['birthdays'] = $birthdays;
$data['birthdays-today'] = $birthdays_today;
$groups = array();
if (dbm::is_result($groups_unseen)) {
$count = 0;
foreach ($groups_unseen as $it)
if ($it['count'] > 0) {
$count++;
$groups[$count.":group"] = $it['count'];
$groups[$count.":@attributes"] = array("id" => $it['id']);
if (dbm::is_result($notifs)) {
foreach ($notifs as $notif) {
if ($notif['seen'] == 0) {
$sysnotify_count ++;
}
$data["groups"] = $groups;
}
$forums = array();
if (dbm::is_result($forums_unseen)) {
$count = 0;
foreach ($forums_unseen as $it)
if ($it['count'] > 0) {
$count++;
$forums[$count.":forum"] = $it['count'];
$forums[$count.":@attributes"] = array("id" => $it['id']);
}
$data["forums"] = $forums;
}
$data["all-events"] = $all_events;
$data["all-events-today"] = $all_events_today;
$data["events"] = $events;
$data["events-today"] = $events_today;
$data["birthdays"] = $birthdays;
$data["birthdays-today"] = $birthdays_today;
if (dbm::is_result($notifs) && !$sysnotify) {
foreach ($notifs as $zz) {
if ($zz['seen'] == 0)
$sysnotify ++;
}
}
// merge all notification types in one array
if (dbm::is_result($intros)) {
foreach ($intros as $i) {
$n = array(
'href' => $a->get_baseurl().'/notifications/intros/'.$i['id'],
'name' => $i['name'],
'url' => $i['url'],
'photo' => $i['photo'],
'date' => $i['datetime'],
'seen' => false,
'message' => t("{0} wants to be your friend"),
foreach ($intros as $intro) {
$notif = array(
'href' => $a->get_baseurl() . '/notifications/intros/' . $intro['id'],
'name' => $intro['name'],
'url' => $intro['url'],
'photo' => $intro['photo'],
'date' => $intro['datetime'],
'seen' => false,
'message' => t('{0} wants to be your friend'),
);
$notifs[] = $n;
$notifs[] = $notif;
}
}
if (dbm::is_result($mails)) {
foreach ($mails as $i) {
$n = array(
'href' => $a->get_baseurl().'/message/'.$i['id'],
'name' => $i['from-name'],
'url' => $i['from-url'],
'photo' => $i['from-photo'],
'date' => $i['created'],
'seen' => false,
'message' => t("{0} sent you a message"),
foreach ($mails as $mail) {
$notif = array(
'href' => $a->get_baseurl() . '/message/' . $mail['id'],
'name' => $mail['from-name'],
'url' => $mail['from-url'],
'photo' => $mail['from-photo'],
'date' => $mail['created'],
'seen' => false,
'message' => t('{0} sent you a message'),
);
$notifs[] = $n;
$notifs[] = $notif;
}
}
if (dbm::is_result($regs)) {
foreach ($regs as $i) {
$n = array(
'href' => $a->get_baseurl().'/admin/users/',
'name' => $i['name'],
'url' => $i['url'],
'photo' => $i['micro'],
'date' => $i['created'],
'seen' => false,
'message' => t("{0} requested registration"),
foreach ($regs as $reg) {
$notif = array(
'href' => $a->get_baseurl() . '/admin/users/',
'name' => $reg['name'],
'url' => $reg['url'],
'photo' => $reg['micro'],
'date' => $reg['created'],
'seen' => false,
'message' => t('{0} requested registration'),
);
$notifs[] = $n;
$notifs[] = $notif;
}
}
@ -279,68 +306,79 @@ function ping_init(&$a) {
usort($notifs, $sort_function);
if (dbm::is_result($notifs)) {
// Are the nofications calles from the regular process or via the friendica app?
// Are the nofications called from the regular process or via the friendica app?
$regularnotifications = (intval($_GET['uid']) AND intval($_GET['_']));
$count = 0;
foreach($notifs as $n) {
$count++;
if ($a->is_friendica_app() OR !$regularnotifications)
$n['message'] = str_replace("{0}", $n['name'], $n['message']);
foreach ($notifs as $notif) {
if ($a->is_friendica_app() OR !$regularnotifications) {
$notif['message'] = str_replace("{0}", $notif['name'], $notif['message']);
}
$notifications[$count.":note"] = $n['message'];
$contact = get_contact_details_by_url($notif['url']);
if (isset($contact['micro'])) {
$notif['photo'] = proxy_url($contact['micro'], false, PROXY_SIZE_MICRO);
} else {
$notif['photo'] = proxy_url($notif['photo'], false, PROXY_SIZE_MICRO);
}
$contact = get_contact_details_by_url($n['url']);
if (isset($contact["micro"]))
$n['photo'] = proxy_url($contact["micro"], false, PROXY_SIZE_MICRO);
else
$n['photo'] = proxy_url($n['photo'], false, PROXY_SIZE_MICRO);
$local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']);
call_hooks('ping_xmlize', $n);
$notifications[$count.":@attributes"] = array("id" => $n["id"],
"href" => $n['href'],
"name" => $n['name'],
"url" => $n['url'],
"photo" => $n['photo'],
"date" => relative_date($n['date']),
"seen" => $n['seen'],
"timestamp" => strtotime($local_time));
$local_time = datetime_convert('UTC', date_default_timezone_get(), $notif['date']);
$notifications[] = array(
'id' => $notif['id'],
'href' => $notif['href'],
'name' => $notif['name'],
'url' => $notif['url'],
'photo' => $notif['photo'],
'date' => relative_date($notif['date']),
'message' => $notif['message'],
'seen' => $notif['seen'],
'timestamp' => strtotime($local_time)
);
}
}
$data["notif"] = $notifications;
$data["@attributes"] = array("count" => $sysnotify + $intro + $mail + $register);
}
$sysmsg = array();
$sysmsgs = array();
$sysmsgs_info = array();
if (x($_SESSION,'sysmsg')){
$count = 0;
foreach ($_SESSION['sysmsg'] as $m){
$count++;
$sysmsg[$count.":notice"] = $m;
}
if (x($_SESSION, 'sysmsg')) {
$sysmsgs = $_SESSION['sysmsg'];
unset($_SESSION['sysmsg']);
}
if (x($_SESSION,'sysmsg_info')){
$count = 0;
foreach ($_SESSION['sysmsg_info'] as $m){
$count++;
$sysmsg[$count.":info"] = $m;
}
if (x($_SESSION, 'sysmsg_info')) {
$sysmsgs_info = $_SESSION['sysmsg_info'];
unset($_SESSION['sysmsg_info']);
}
$data["sysmsgs"] = $sysmsg;
if ($format == 'json') {
$data['groups'] = $groups_unseen;
$data['forums'] = $forums_unseen;
$data['notify'] = $sysnotify_count + $intro_count + $mail_count + $register_count;
$data['notifications'] = $notifications;
$data['sysmsgs'] = array(
'notice' => $sysmsgs,
'info' => $sysmsgs_info
);
$json_payload = json_encode(array("result" => $data));
if (isset($_GET['callback'])) {
// JSONP support
header("Content-type: application/javascript");
echo $_GET['callback'] . '(' . $json_payload . ')';
} else {
header("Content-type: application/json");
echo $json_payload;
}
} else {
// Legacy slower XML format output
$data = ping_format_xml_data($data, $sysnotify_count, $notifications, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen);
header("Content-type: text/xml");
echo xml::from_array(array("result" => $data), $xml);
}
header("Content-type: text/xml");
echo xml::from_array(array("result" => $data), $xml);
killme();
}
@ -350,19 +388,19 @@ function ping_init(&$a) {
* @param int $uid User id
* @return array Associative array of notifications
*/
function ping_get_notifications($uid) {
$result = array();
$offset = 0;
$seen = false;
function ping_get_notifications($uid)
{
$result = array();
$offset = 0;
$seen = false;
$seensql = "NOT";
$order = "DESC";
$quit = false;
$order = "DESC";
$quit = false;
$a = get_app();
do {
$r = q("SELECT `notify`.*, `item`.`visible`, `item`.`spam`, `item`.`deleted`
$r = qu("SELECT `notify`.*, `item`.`visible`, `item`.`spam`, `item`.`deleted`
FROM `notify` LEFT JOIN `item` ON `item`.`id` = `notify`.`iid`
WHERE `notify`.`uid` = %d AND `notify`.`msg` != ''
AND NOT (`notify`.`type` IN (%d, %d))
@ -422,3 +460,71 @@ function ping_get_notifications($uid) {
return($result);
}
/**
* @brief Backward-compatible XML formatting for ping.php output
* @deprecated
*
* @param array $data The initial ping data array
* @param int $sysnotify_count Number of unseen system notifications
* @param array $notifs Complete list of notification
* @param array $sysmsgs List of system notice messages
* @param array $sysmsgs_info List of system info messages
* @param int $groups_unseen Number of unseen group items
* @param int $forums_unseen Number of unseen forum items
* @return array XML-transform ready data array
*/
function ping_format_xml_data($data, $sysnotify, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen)
{
$notifications = array();
foreach($notifs as $key => $notif) {
$notifications[$key . ':note'] = $notif['message'];
$notifications[$key . ':@attributes'] = array(
'id' => $notif['id'],
'href' => $notif['href'],
'name' => $notif['name'],
'url' => $notif['url'],
'photo' => $notif['photo'],
'date' => $notif['date'],
'seen' => $notif['seen'],
'timestamp' => $notif['timestamp']
);
}
$sysmsg = array();
foreach ($sysmsgs as $key => $m){
$sysmsg[$key . ':notice'] = $m;
}
foreach ($sysmsgs_info as $key => $m){
$sysmsg[$key . ':info'] = $m;
}
$data['notif'] = $notifications;
$data['@attributes'] = array('count' => $sysnotify_count + $data['intro'] + $data['mail'] + $data['register']);
$data['sysmsgs'] = $sysmsg;
if ($data['register'] == 0) {
unset($data['register']);
}
$groups = array();
if (count($groups_unseen)) {
foreach ($groups_unseen as $key => $item) {
$groups[$key . ':group'] = $item['count'];
$groups[$key . ':@attributes'] = array('id' => $item['id']);
}
$data['groups'] = $groups;
}
$forums = array();
if (count($forums_unseen)) {
foreach ($forums_unseen as $key => $item) {
$forums[$count . ':forum'] = $item['count'];
$forums[$count . ':@attributes'] = array('id' => $item['id']);
}
$data['forums'] = $forums;
}
return $data;
}

View file

@ -233,66 +233,87 @@ function proxy_init() {
killme();
}
function proxy_url($url, $writemode = false, $size = "") {
global $_SERVER;
/**
* @brief Transform a remote URL into a local one
*
* This function only performs the URL replacement on http URL and if the
* provided URL isn't local, "the isn't deactivated" (sic) and if the config
* system.proxy_disabled is set to false.
*
* @param string $url The URL to proxyfy
* @param bool $writemode Returns a local path the remote URL should be saved to
* @param string $size One of the PROXY_SIZE_* constants
*
* @return string The proxyfied URL or relative path
*/
function proxy_url($url, $writemode = false, $size = '') {
$a = get_app();
if (substr($url, 0, strlen('http')) !== 'http') {
return($url);
return $url;
}
// Only continue if it isn't a local image and the isn't deactivated
if (proxy_is_local_image($url)) {
$url = str_replace(normalise_link($a->get_baseurl())."/", $a->get_baseurl()."/", $url);
return($url);
$url = str_replace(normalise_link($a->get_baseurl()) . '/', $a->get_baseurl() . '/', $url);
return $url;
}
if (get_config("system", "proxy_disabled"))
return($url);
if (get_config('system', 'proxy_disabled')) {
return $url;
}
// Image URL may have encoded ampersands for display which aren't desirable for proxy
$url = html_entity_decode($url, ENT_NOQUOTES, 'utf-8');
// Creating a sub directory to reduce the amount of files in the cache directory
$basepath = $a->get_basepath()."/proxy";
$basepath = $a->get_basepath() . '/proxy';
$path = substr(hash("md5", $url), 0, 2);
$shortpath = hash('md5', $url);
$longpath = substr($shortpath, 0, 2);
if (is_dir($basepath) and $writemode)
if (!is_dir($basepath."/".$path)) {
mkdir($basepath."/".$path);
chmod($basepath."/".$path, 0777);
if (is_dir($basepath) and $writemode) {
if (!is_dir($basepath . '/' . $longpath)) {
mkdir($basepath . '/' . $longpath);
chmod($basepath . '/' . $longpath, 0777);
}
$path .= "/".strtr(base64_encode($url), '+/', '-_');
// Checking for valid extensions. Only add them if they are safe
$pos = strrpos($url, ".");
if ($pos) {
$extension = strtolower(substr($url, $pos+1));
$pos = strpos($extension, "?");
if ($pos)
$extension = substr($extension, 0, $pos);
}
$extensions = array("jpg", "jpeg", "gif", "png");
$longpath .= '/' . strtr(base64_encode($url), '+/', '-_');
if (in_array($extension, $extensions))
$path .= ".".$extension;
// Checking for valid extensions. Only add them if they are safe
$pos = strrpos($url, '.');
if ($pos) {
$extension = strtolower(substr($url, $pos + 1));
$pos = strpos($extension, '?');
if ($pos) {
$extension = substr($extension, 0, $pos);
}
}
$proxypath = $a->get_baseurl()."/proxy/".$path;
$extensions = array('jpg', 'jpeg', 'gif', 'png');
if (in_array($extension, $extensions)) {
$shortpath .= '.' . $extension;
$longpath .= '.' . $extension;
}
if ($size != "")
$size = ":".$size;
$proxypath = $a->get_baseurl() . '/proxy/' . $longpath;
if ($size != '') {
$size = ':' . $size;
}
// Too long files aren't supported by Apache
// Writemode in combination with long files shouldn't be possible
if ((strlen($proxypath) > 250) AND $writemode)
return (hash("md5", $url));
elseif (strlen($proxypath) > 250)
return ($a->get_baseurl()."/proxy/".hash("md5", $url)."?url=".urlencode($url));
elseif ($writemode)
return ($path);
else
return ($proxypath.$size);
if ((strlen($proxypath) > 250) AND $writemode) {
return $shortpath;
} elseif (strlen($proxypath) > 250) {
return $a->get_baseurl() . '/proxy/' . $shortpath . '?url=' . urlencode($url);
} elseif ($writemode) {
return $longpath;
} else {
return $proxypath . $size;
}
}
/**

View file

@ -113,12 +113,13 @@ function register_post(&$a) {
}
$hash = random_string();
$r = q("INSERT INTO `register` ( `hash`, `created`, `uid`, `password`, `language` ) VALUES ( '%s', '%s', %d, '%s', '%s' ) ",
$r = q("INSERT INTO `register` ( `hash`, `created`, `uid`, `password`, `language`, `note` ) VALUES ( '%s', '%s', %d, '%s', '%s', '%s' ) ",
dbesc($hash),
dbesc(datetime_convert()),
intval($user['uid']),
dbesc($result['password']),
dbesc($lang)
dbesc($lang),
dbesc($_POST['permonlybox'])
);
// invite system
@ -133,6 +134,7 @@ function register_post(&$a) {
$admin_mail_list
);
// send notification to admins
foreach ($adminlist as $admin) {
notification(array(
'type' => NOTIFY_SYSTEM,
@ -149,6 +151,11 @@ function register_post(&$a) {
'show_in_notification_page' => false
));
}
// send notification to the user, that the registration is pending
send_register_pending_eml(
$user['email'],
$a->config['sitename'],
$user['username']);
info( t('Your registration is pending approval by the site owner.') . EOL ) ;
goaway(z_root());
@ -256,6 +263,8 @@ function register_content(&$a) {
$o = replace_macros($o, array(
'$oidhtml' => $oidhtml,
'$invitations' => get_config('system','invitation_only'),
'$permonly' => $a->config['register_policy'] == REGISTER_APPROVE,
'$permonlybox' => array('permonlybox', t('Note for the admin'), '', t('Leave a message for the admin, why you want to join this node')),
'$invite_desc' => t('Membership on this site is by invitation only.'),
'$invite_label' => t('Your invitation ID: '),
'$invite_id' => $invite_id,

View file

@ -301,6 +301,7 @@ function settings_post(&$a) {
$infinite_scroll = x($_POST, 'infinite_scroll') ? intval($_POST['infinite_scroll']) : 0;
$no_auto_update = x($_POST, 'no_auto_update') ? intval($_POST['no_auto_update']) : 0;
$bandwidth_saver = x($_POST, 'bandwidth_saver') ? intval($_POST['bandwidth_saver']) : 0;
$nowarn_insecure = x($_POST, 'nowarn_insecure') ? intval($_POST['nowarn_insecure']) : 0;
$browser_update = x($_POST, 'browser_update') ? intval($_POST['browser_update']) : 0;
if ($browser_update != -1) {
$browser_update = $browser_update * 1000;
@ -321,6 +322,7 @@ function settings_post(&$a) {
set_pconfig(local_user(),'system','mobile_theme',$mobile_theme);
}
set_pconfig(local_user(), 'system', 'nowarn_insecure' , $nowarn_insecure);
set_pconfig(local_user(), 'system', 'update_interval' , $browser_update);
set_pconfig(local_user(), 'system', 'itemspage_network' , $itemspage_network);
set_pconfig(local_user(), 'system', 'itemspage_mobile_network', $itemspage_mobile_network);
@ -951,6 +953,8 @@ function settings_content(&$a) {
$theme_selected = (!x($_SESSION,'theme')? $default_theme : $_SESSION['theme']);
$mobile_theme_selected = (!x($_SESSION,'mobile-theme')? $default_mobile_theme : $_SESSION['mobile-theme']);
$nowarn_insecure = intval(get_pconfig(local_user(), 'system', 'nowarn_insecure'));
$browser_update = intval(get_pconfig(local_user(), 'system','update_interval'));
if (intval($browser_update) != -1)
$browser_update = (($browser_update == 0) ? 40 : $browser_update / 1000); // default if not set: 40 seconds
@ -995,6 +999,7 @@ function settings_content(&$a) {
'$theme' => array('theme', t('Display Theme:'), $theme_selected, '', $themes, true),
'$mobile_theme' => array('mobile_theme', t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, false),
'$nowarn_insecure' => array('nowarn_insecure', t('Suppress warning of insecure networks'), $nowarn_insecure, t("Should the system suppress the warning that the current group contains members of networks that can't receive non public postings.")),
'$ajaxint' => array('browser_update', t("Update browser every xx seconds"), $browser_update, t('Minimum of 10 seconds. Enter -1 to disable it.')),
'$itemspage_network' => array('itemspage_network', t("Number of items to display per page:"), $itemspage_network, t('Maximum of 100 items')),
'$itemspage_mobile_network' => array('itemspage_mobile_network', t("Number of items to display per page when viewed from mobile device:"), $itemspage_mobile_network, t('Maximum of 100 items')),

View file

@ -47,7 +47,7 @@ function viewcontacts_content(&$a) {
}
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
WHERE `uid` = %d AND (NOT `blocked` OR `pending`) AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s')",
intval($a->profile['uid']),
dbesc(NETWORK_DFRN),
@ -58,7 +58,7 @@ function viewcontacts_content(&$a) {
$a->set_pager_total($r[0]['total']);
$r = q("SELECT * FROM `contact`
WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
WHERE `uid` = %d AND (NOT `blocked` OR `pending`) AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s')
ORDER BY `name` ASC LIMIT %d, %d",
intval($a->profile['uid']),

54
mod/worker.php Normal file
View file

@ -0,0 +1,54 @@
<?php
/**
* @file mod/worker.php
* @brief Module for running the poller as frontend process
*/
require_once("include/poller.php");
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
function worker_init($a){
if (!Config::get("system", "frontend_worker") OR !Config::get("system", "worker")) {
return;
}
// We don't need the following lines if we can execute background jobs.
// So we just wake up the worker if it sleeps.
if (function_exists("proc_open")) {
call_worker_if_idle();
return;
}
clear_worker_processes();
$workers = q("SELECT COUNT(*) AS `processes` FROM `process` WHERE `command` = 'worker.php'");
if ($workers[0]["processes"] > Config::get("system", "worker_queues", 4)) {
return;
}
$a->start_process();
logger("Front end worker started: ".getmypid());
call_worker();
if ($r = poller_worker_process()) {
// On most configurations this parameter wouldn't have any effect.
// But since it doesn't destroy anything, we just try to get more execution time in any way.
set_time_limit(0);
poller_execute($r[0]);
}
call_worker();
$a->end_process();
logger("Front end worker ended: ".getmypid());
killme();
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

View file

@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="1633" height="2173" viewBox="0 0 1633 2173">
<style type="text/css"><![CDATA[
text { font:12px Dialog; }
]]></style>
<rect x="-485" y="-485" width="2603" height="3143" style="fill:rgb(255,255,255);stroke:none" />
<clipPath id="clip1"><path d="M614,37 L1056,37 L1056,106 L614,106 L614,37 Z" /></clipPath>
<path d="M616,39 L616,103 L1053,103 L1053,39 Z" style="fill:rgb(202,221,254);stroke:none" clip-path="url(#clip1)" />
<clipPath id="clip2"><path d="M614,37 L1056,37 L1056,106 L614,106 L614,37 Z" /></clipPath>
<path d="M616,39 L616,103 L1053,103 L1053,39 Z" style="fill:none;stroke:rgb(61,83,127)" clip-path="url(#clip2)" />
<text x="649" y="76" style="font:18px Open Sans">Friendica - Contact confirmation</text>
<clipPath id="clip3"><path d="M1198,202 L1388,202 L1388,244 L1198,244 L1198,202 Z" /></clipPath>
<path d="M1208,204 C1203.5820313,204 1200,207.5820313 1200,212 L1200,233 C1200,237.4179688 1203.5820313,241 1208,241 L1377,241 C1381.4179688,241 1385,237.4179688 1385,233 L1385,212 C1385,207.5820313 1381.4179688,204 1377,204 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip3)" />
<clipPath id="clip4"><path d="M1198,202 L1388,202 L1388,244 L1198,244 L1198,202 Z" /></clipPath>
<path d="M1208,204 C1203.5820313,204 1200,207.5820313 1200,212 L1200,233 C1200,237.4179688 1203.5820313,241 1208,241 L1377,241 C1381.4179688,241 1385,237.4179688 1385,233 L1385,212 C1385,207.5820313 1381.4179688,204 1377,204 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip4)" />
<text x="1213" y="225" style="font:13px Tahoma">bob@example.com</text>
<image x="0" y="0" width="1374" height="231" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABV4AAADnCAYAAADmQE2RAAAIU0lEQVR42u3dTW+UZRSA4SYSfoACIi4EhERCJAhWpXZKUT4UEaGlRVuMgNQQlKCoGEBIGbUCEgsUkK+2YFsUUSIxhoVGkUBLCkIRypcSoOUPqCy6sceZUQyZoC5cel3JWUzeOZtneefN8+bkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPB/EBH/aQAAAAAAyJIdUgt3ne+V2NVeld905ofUdGVm19m2RNOZZPqZ8AoAAAAA8C9ujKiPNp18elTdyWu9R1bEvaU7Y8r6szG5+kwULtsfwxdui/yG9p8Tje3ThFcAAAAAgH9wPaCO2dFWmmg43X1fxd64Y9KxGDm/PUq3dETp5o4oSU3xxssxevlXUdB4untMw6lS4RUAAAAA4G+k42mi7njvRP0Pv+S9vj8mV1+KCVUXY/rWjnh6W0eU1XZGYeWFGDijLYbNbY+B4+pjTGP7r3kfnuwjvAIAAAAA3EQmvG5rSw57cVPkLToXRTVX4pntnanpiLK6zijaeDnyl52PQbNORt+px+K28a0xpHxlJLaeqBJeAQAAAABuIh1P8zcfbxswuiYefPVM5mqBstqOKK/vjBk7OmP86osx+q0LUZg8F3eXH4i+4/dE/7ylkVv15dnUek8nCAAAAACQJRNeNxzryn2pLaasv/zH9QJ1nfHszs54ruFq5K+4EE+u/SkeWHgwRr36USxqORyLj7ZE0ZZPfkut93OCAAAAAABZMuF1XWvX4yvP/3Wva3kmvF6Nok2Xo8/M76P39ANx/8t7YnFrSxStaYyH5qzKxNfBBQUFThAAAAAAIEsmvL5/pC3x2r4o2nglSrdcyXxQK/3Ga8mWizFg1rdxz+zGmPBOU0xYXh8F8+viieSGeKPlcHevQYNGOEEAAAAAgCyZj2utak4On7M+xiZ/jKEVp+KpdZeivPZSFFe3RtGaT2Npa3PM2b0vXtj9eUxdvSMWp34/9s7G5tR6bycIAAAAAJAlHV7z3jvcJ//dQz+Pmrcvbh1/NAbPbIvitSeipHpvvNnaHGOXbouy2s9i7t4vMtF13Nt1XXfmThmeWu/hBAEAAAAAsqTDa+at17cOTns4+V13//xN8cAr7TEx+XUsOXIoSqobY+CkDZG/YHsUV9dHwZLa7qGz11akVnuk9wAAAAAAyHI9vGbuel1xoGTUsm+u3fd8TeTN+yDePNoc4xZVx6TKmljaejjGrtjZNXzu1pmptVuu7wAAAAAAkOXG8JqewspveyUqv6nKXfDx2eJ1Tb+l4+uSI4e6JyZrDt0+cuK9OX++6Sq8AgAAAAD8jezwekNQ7ZmafkMeeaSg1113jcj540NaPbL/9ztNv3iKQ/ZEAwAAAABJRU5ErkJggg==" /><clipPath id="clip5"><path d="M181,198 L432,198 L432,240 L181,240 L181,198 Z" /></clipPath>
<path d="M191,200 C186.5820313,200 183,203.5820313 183,208 L183,229 C183,233.4179688 186.5820313,237 191,237 L421,237 C425.4179688,237 429,233.4179688 429,229 L429,208 C429,203.5820313 425.4179688,200 421,200 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip5)" />
<clipPath id="clip6"><path d="M181,198 L432,198 L432,240 L181,240 L181,198 Z" /></clipPath>
<path d="M191,200 C186.5820313,200 183,203.5820313 183,208 L183,229 C183,233.4179688 186.5820313,237 191,237 L421,237 C425.4179688,237 429,233.4179688 429,229 L429,208 C429,203.5820313 425.4179688,200 421,200 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip6)" />
<text x="197" y="221" style="font:13px Tahoma">karen@karenhompage.com</text>
<image x="0" y="0" width="418" height="227" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaIAAADjCAYAAADHeBASAAAE2klEQVR42u3cS29VVRiAYRKNP0ApIg64CImEQEAEbe0pF6EookKhBSlGQGoISlBQDNeUg1RAI5cCcm3BtiiiRGIMAw0goYUUhHIpNyVAyx9AGXRCP3eP0RinLXHyPMkanazJmrz59l5nd+oEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+PiGjXAoAODdHwvVc7p/Y2luXWXDqfrJbM2nu5IVVzKd32mxABcN9C9HzNuSnZFefuZg0uif5Fe2L8xsvxyrpLMXzZoRg4f0fkVjXeSVU3ThIiADo8RCN2NxSlqi62Dio5EI+NOx2D5zZG0bamKNraFIXJmrj5Zgxb/mPkVV9sHVF1oUiIAOiwEKUqzmSlKs//nvPBoWQCuhFjyq7H5O1NMWVHU0zd1RzDS69Fr2kNMWB2Y/QaXRkjqhv/yPniXBchAqBjQrSjIT3g7S2Rs/BKFJTfitd2NicriVBFcxQkk1DusqvRe8a56DrhdDySXx99i1dHavvZMiECoENClLv1TEPPYeXxzIJLmUdxU3c1RXFlc0zb3Rz5a6/HsJXXYnj6SjxRfDS65u+PHjlLYkjZD5eT7Q85QQDaH6JNp1uGvNMQ4zfe/OtxXDIJvb6nOd6ouh25K67Fy+t/i6Hzj0X2gi9j4YnaWHTqRBRs+/pesr2bEwSg/SHaUN/y4uqr/7wXKs6E6HYUbLkZXab/ElmTj8bT7+6PRfVJgD6tjmdnrcnEqE9eXp4TBKD9IfrsZEPq/YNRsPlWFG27lbmg0DYRFW67Hj1nHIknZ1bHmFU1MWZ5ZeTNrYiX0pviwxO1rZ17937KCQLQ7hCl1tSlB87aGKPSv0a/kgvx6oYbUbzrRkxcV59MQN/Ekvq6mLXvYLy177uYsHZ3MhnVxQurNtcl27OcIADtDlHOJ7Vdcj8+fid7zsF4OP9U9JneEBPXn43CdQdiaRKdUUt2JFPStzH7wPeZCI3+qKLl8SHjBybbH3SCALQ7RJmpaOWxSc+lf27tkbslhr7XGGPTP8Xik8eTGFVHr3GbInfezmRCqoy8xbta+81cX9IWIde3AeiwEGXeFa04Wpi97PDdQW+WR86cz2PpqWT6WbguxpWWx5L62hi1Yk/LwNnbpyfbHvBlBQA6PESZj56WHumcKj1cNmTeV5cnbqi51xajZDJqHZsuP/7o4LH9/56EhAiA+xKifwWm7c+q3fqOHJnXuXv3tttxWf+NUNv6E/vueIp8e9bqAAAAAElFTkSuQmCC" /><clipPath id="clip7"><path d="M215,325 L390,325 L390,367 L215,367 L215,325 Z" /></clipPath>
<path d="M224,326 C219.5820313,326 216,329.5820313 216,334 L216,357 C216,361.4179688 219.5820313,365 224,365 L380,365 C384.4179688,365 388,361.4179688 388,357 L388,334 C388,329.5820313 384.4179688,326 380,326 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip7)" />
<text x="230" y="348" style="font:13px Open Sans">notifications.php</text>
<clipPath id="clip8"><path d="M30,409 L580,409 L580,566 L30,566 L30,409 Z" /></clipPath>
<path d="M39,410 C34.5820313,410 31,413.5820313 31,418 L31,556 C31,560.4179688 34.5820313,564 39,564 L570,564 C574.4179688,564 578,560.4179688 578,556 L578,418 C578,413.5820313 574.4179688,410 570,410 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip8)" />
<text x="45" y="432" style="font:13px Open Sans">notifications_content()</text>
<text x="45" y="455" style="font:13px Open Sans">-----------------------------------------</text>
<text x="45" y="501" style="font:13px Open Sans">- This is the page where Karen see Bobs friendship request</text>
<text x="45" y="524" style="font:13px Open Sans">- the submit form redirects to Karens local dfrn_confirm page </text>
<text x="45" y="547" style="font:13px Open Sans">($dfrn_id, $contact_id, $intro_id are submitted)</text>
<clipPath id="clip9"><path d="M219,640 L399,640 L399,682 L219,682 L219,640 Z" /></clipPath>
<path d="M228,641 C223.5820313,641 220,644.5820313 220,649 L220,672 C220,676.4179688 223.5820313,680 228,680 L389,680 C393.4179688,680 397,676.4179688 397,672 L397,649 C397,644.5820313 393.4179688,641 389,641 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip9)" />
<text x="234" y="663" style="font:13px Open Sans">dfrn_confirm.php</text>
<clipPath id="clip10"><path d="M14,698 L594,698 L594,1798 L14,1798 L14,698 Z" /></clipPath>
<path d="M23,699 C18.5820313,699 15,702.5820313 15,707 L15,1788 C15,1792.4179688 18.5820313,1796 23,1796 L584,1796 C588.4179688,1796 592,1792.4179688 592,1788 L592,707 C592,702.5820313 588.4179688,699 584,699 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip10)" />
<text x="29" y="721" style="font:13px Open Sans">dfrn_confirm_post()</text>
<text x="29" y="744" style="font:13px Open Sans">SCENARIO 1 ( no $_POST['source_url'] available)</text>
<text x="29" y="767" style="font:13px Open Sans">--------------------------------------------------------------------------------</text>
<text x="29" y="813" style="font:13px Open Sans">- contact data come either form $handsfree (if autoconfirm) or </text>
<text x="29" y="836" style="font:13px Open Sans">from $_POST</text>
<text x="29" y="882" style="font:13px Open Sans">- get all data about Karen form the user table</text>
<text x="29" y="928" style="font:13px Open Sans">[Note: Bob have been issued an ID (contact issue-id) when he first </text>
<text x="29" y="951" style="font:13px Open Sans">requested the friendship. Locate Bobs contact record. At this </text>
<text x="29" y="974" style="font:13px Open Sans">time, his record will have both pending and blocked set to 1. </text>
<text x="29" y="997" style="font:13px Open Sans">There won't be any dfrn_id if this is a network follower, so use </text>
<text x="29" y="1020" style="font:13px Open Sans">the contact_id instead]</text>
<text x="29" y="1066" style="font:13px Open Sans">- search for Bob in the contact table by contact_id, dfrn_id and </text>
<text x="29" y="1089" style="font:13px Open Sans">issued-id not empty (for the uid -&gt; Karens user id)</text>
<text x="29" y="1135" style="font:13px Open Sans">- if network = dfrn </text>
<text x="29" y="1158" style="font:13px Open Sans"> -&gt; create a new keypair (prvkey &amp; pubkey) and update the </text>
<text x="29" y="1181" style="font:13px Open Sans">contact</text>
<text x="29" y="1227" style="font:13px Open Sans">[Note: Generate a key pair for all further communications with </text>
<text x="29" y="1250" style="font:13px Open Sans">this person. We have a keypair for every contact, and a site key </text>
<text x="29" y="1273" style="font:13px Open Sans">for unknown people. This provides a means to carry on </text>
<text x="29" y="1296" style="font:13px Open Sans">relationships with other people any single key is compromised. It </text>
<text x="29" y="1319" style="font:13px Open Sans">is a robust key. We're much more worried about key leakage </text>
<text x="29" y="1342" style="font:13px Open Sans">than anybody cracking it.]</text>
<text x="29" y="1388" style="font:13px Open Sans"> -&gt; update Bobs contact record (in the contact table) with the </text>
<text x="29" y="1411" style="font:13px Open Sans">generated prvkey</text>
<text x="29" y="1457" style="font:13px Open Sans"> -&gt; encrypting the dfrn_id with Karens prvkey (Bob can decrypt it </text>
<text x="29" y="1480" style="font:13px Open Sans">on the other and with Karens site-pubkey) and add it to the </text>
<text x="29" y="1503" style="font:13px Open Sans">transmit params.</text>
<text x="29" y="1549" style="font:13px Open Sans"> -&gt; encrypting Karens profile url with Bobs site-pubkey (Bob </text>
<text x="29" y="1572" style="font:13px Open Sans">can decrypt it with his own private key) and add it to the </text>
<text x="29" y="1595" style="font:13px Open Sans">transmit params.</text>
<text x="29" y="1641" style="font:13px Open Sans"> -&gt; add the above generated public key to params which </text>
<text x="29" y="1664" style="font:13px Open Sans">getting transmitted (if $aes_allow -&gt; encrypt the the public key)</text>
<text x="29" y="1710" style="font:13px Open Sans"> -&gt; add duplex state and page-flags to the params</text>
<text x="29" y="1756" style="font:13px Open Sans"> -&gt; send params to Bobs dfrn_confirm page ($res = </text>
<text x="29" y="1779" style="font:13px Open Sans">post_url($dfrn_confirm,$params);</text>
<clipPath id="clip11"><path d="M1041,1319 L1619,1319 L1619,1913 L1041,1913 L1041,1319 Z" /></clipPath>
<path d="M1050,1320 C1045.5820313,1320 1042,1323.5820313 1042,1328 L1042,1903 C1042,1907.4179688 1045.5820313,1911 1050,1911 L1609,1911 C1613.4179688,1911 1617,1907.4179688 1617,1903 L1617,1328 C1617,1323.5820313 1613.4179688,1320 1609,1320 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip11)" />
<text x="1055" y="1342" style="font:13px Open Sans">dfrn_confirm_post()</text>
<text x="1055" y="1365" style="font:13px Open Sans">SCENARIO 2 ( $_POST['source_url'] is available)</text>
<text x="1055" y="1388" style="font:13px Open Sans">------------------------------------------------------------------------</text>
<text x="1055" y="1434" style="font:13px Open Sans">- get all data about Bob from the user table (prvkey and uid form </text>
<text x="1055" y="1457" style="font:13px Open Sans">Bob )</text>
<text x="1055" y="1503" style="font:13px Open Sans">- decrypt the transmitted source_url (profile url) with Bobs </text>
<text x="1055" y="1526" style="font:13px Open Sans">prvkey</text>
<text x="1055" y="1572" style="font:13px Open Sans">- get data of Karen from contact table by her source_url (and by </text>
<text x="1055" y="1595" style="font:13px Open Sans">her user id)</text>
<text x="1055" y="1641" style="font:13px Open Sans">- decrypt the dfrn_id sent by Karen with Karens site-pubkey </text>
<text x="1055" y="1664" style="font:13px Open Sans">(taken from contact table)</text>
<text x="1055" y="1710" style="font:13px Open Sans">- if possible decrpyt the pubkey sent by Karen with the prvkey of </text>
<text x="1055" y="1733" style="font:13px Open Sans">Bob (taken from user table) -&gt; if this is not possible use the raw </text>
<text x="1055" y="1756" style="font:13px Open Sans">pubkey</text>
<text x="1055" y="1802" style="font:13px Open Sans">- search if the dfrn_id is already present in the contact table (if it </text>
<text x="1055" y="1825" style="font:13px Open Sans">is prensent it is a duplicate)</text>
<text x="1055" y="1871" style="font:13px Open Sans">- update dfrn-id and pubkey for Karens contact entry in the </text>
<text x="1055" y="1894" style="font:13px Open Sans">contact table</text>
<clipPath id="clip12"><path d="M42,1841 L559,1841 L559,1906 L42,1906 L42,1841 Z" /></clipPath>
<path d="M51,1842 C46.5820313,1842 43,1845.5820313 43,1850 L43,1896 C43,1900.4179688 46.5820313,1904 51,1904 L549,1904 C553.4179688,1904 557,1900.4179688 557,1896 L557,1850 C557,1845.5820313 553.4179688,1842 549,1842 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip12)" />
<text x="57" y="1864" style="font:13px Open Sans"> -&gt; set the relation for the contact and set pending = 0 and </text>
<text x="57" y="1887" style="font:13px Open Sans">blocked = 0</text>
<clipPath id="clip13"><path d="M1128,1950 L1541,1950 L1541,2061 L1128,2061 L1128,1950 Z" /></clipPath>
<path d="M1137,1951 C1132.5820313,1951 1129,1954.5820313 1129,1959 L1129,2051 C1129,2055.4179688 1132.5820313,2059 1137,2059 L1531,2059 C1535.4179688,2059 1539,2055.4179688 1539,2051 L1539,1959 C1539,1954.5820313 1535.4179688,1951 1531,1951 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip13)" />
<text x="1142" y="1973" style="font:13px Open Sans">- update the relationship of the contact Karen</text>
<text x="1142" y="2019" style="font:13px Open Sans">-&gt; if duplex delete the issued-id</text>
<text x="1142" y="2042" style="font:13px Open Sans">-&gt; set blocked = 0 and pending = 0</text>
<clipPath id="clip14"><path d="M1241,2117 L1428,2117 L1428,2159 L1241,2159 L1241,2117 Z" /></clipPath>
<path d="M1250,2118 C1245.5820313,2118 1242,2121.5820313 1242,2126 L1242,2149 C1242,2153.4179688 1245.5820313,2157 1250,2157 L1418,2157 C1422.4179688,2157 1426,2153.4179688 1426,2149 L1426,2126 C1426,2121.5820313 1422.4179688,2118 1418,2118 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip14)" />
<text x="1255" y="2140" style="font:13px Open Sans">send a notification</text>
<clipPath id="clip15"><path d="M190,1937 L410,1937 L410,1979 L190,1979 L190,1937 Z" /></clipPath>
<path d="M199,1938 C194.5820313,1938 191,1941.5820313 191,1946 L191,1969 C191,1973.4179688 194.5820313,1977 199,1977 L400,1977 C404.4179688,1977 408,1973.4179688 408,1969 L408,1946 C408,1941.5820313 404.4179688,1938 400,1938 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip15)" />
<text x="205" y="1960" style="font:13px Open Sans">delete the intro of Bob</text>
<clipPath id="clip16"><path d="M156,14 L512,14 L512,125 L156,125 L156,14 Z" /></clipPath>
<path d="M165,15 C160.5820313,15 157,18.5820313 157,23 L157,115 C157,119.4179688 160.5820313,123 165,123 L502,123 C506.4179688,123 510,119.4179688 510,115 L510,23 C510,18.5820313 506.4179688,15 502,15 Z" style="fill:rgb(255,255,255);stroke:none" clip-path="url(#clip16)" />
<text x="171" y="38" style="font:13px Open Sans">Note: this chart respects only dfrn </text>
<text x="171" y="61" style="font:13px Open Sans">contacts and focuses on key exchange </text>
<text x="171" y="84" style="font:13px Open Sans">(for other areas it might be very </text>
<text x="171" y="106" style="font:13px Open Sans">incomplete)</text>
<clipPath id="clip17"><path d="M266,361 L341,361 L341,414 L266,414 L266,361 Z" /></clipPath>
<path d="M302.4140625,365 L303.1328125,410" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip17)" />
<clipPath id="clip18"><path d="M266,361 L341,361 L341,414 L266,414 L266,361 Z" /></clipPath>
<path d="M297.9960938,401.421875 L303.1328125,410 L307.9960938,401.2617188 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip18)" />
<clipPath id="clip19"><path d="M266,361 L341,361 L341,414 L266,414 L266,361 Z" /></clipPath>
<path d="M297.9960938,401.421875 L303.1328125,410 L307.9960938,401.2617188 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip19)" />
<clipPath id="clip20"><path d="M271,676 L346,676 L346,703 L271,703 L271,676 Z" /></clipPath>
<path d="M308.3515625,680 L308.6445313,699" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip20)" />
<clipPath id="clip21"><path d="M271,676 L346,676 L346,703 L271,703 L271,676 Z" /></clipPath>
<path d="M303.5117188,690.4179688 L308.6445313,699 L313.5078125,690.265625 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip21)" />
<clipPath id="clip22"><path d="M271,676 L346,676 L346,703 L271,703 L271,676 Z" /></clipPath>
<path d="M303.5117188,690.4179688 L308.6445313,699 L313.5078125,690.265625 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip22)" />
<clipPath id="clip23"><path d="M270,560 L345,560 L345,645 L270,645 L270,560 Z" /></clipPath>
<path d="M306.4921875,564 L308.1054688,641" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip23)" />
<clipPath id="clip24"><path d="M270,560 L345,560 L345,645 L270,645 L270,560 Z" /></clipPath>
<path d="M302.9257813,632.4453125 L308.1054688,641 L312.9257813,632.2382813 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip24)" />
<clipPath id="clip25"><path d="M270,560 L345,560 L345,645 L270,645 L270,560 Z" /></clipPath>
<path d="M302.9257813,632.4453125 L308.1054688,641 L312.9257813,632.2382813 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip25)" />
<clipPath id="clip26"><path d="M588,1338 L1046,1338 L1046,1770 L588,1770 L588,1338 Z" /></clipPath>
<path d="M592,1766.2265625 L1042,1342.65625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip26)" />
<clipPath id="clip27"><path d="M588,1338 L1046,1338 L1046,1770 L588,1770 L588,1338 Z" /></clipPath>
<path d="M1039.1210938,1352.2304688 L1042,1342.65625 L1032.265625,1344.9492188 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip27)" />
<clipPath id="clip28"><path d="M588,1338 L1046,1338 L1046,1770 L588,1770 L588,1338 Z" /></clipPath>
<path d="M1039.1210938,1352.2304688 L1042,1342.65625 L1032.265625,1344.9492188 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip28)" />
<clipPath id="clip29"><path d="M263,1792 L338,1792 L338,1846 L263,1846 L263,1792 Z" /></clipPath>
<path d="M300.4296875,1796 L300.1992188,1842" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip29)" />
<clipPath id="clip30"><path d="M263,1792 L338,1792 L338,1846 L263,1846 L263,1792 Z" /></clipPath>
<path d="M295.2421875,1833.3164063 L300.1992188,1842 L305.2421875,1833.3632813 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip30)" />
<clipPath id="clip31"><path d="M263,1792 L338,1792 L338,1846 L263,1846 L263,1792 Z" /></clipPath>
<path d="M295.2421875,1833.3164063 L300.1992188,1842 L305.2421875,1833.3632813 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip31)" />
<clipPath id="clip32"><path d="M1295,1907 L1370,1907 L1370,1955 L1295,1955 L1295,1907 Z" /></clipPath>
<path d="M1332.9140625,1911 L1333.4453125,1951" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip32)" />
<clipPath id="clip33"><path d="M1295,1907 L1370,1907 L1370,1955 L1295,1955 L1295,1907 Z" /></clipPath>
<path d="M1328.3320313,1942.40625 L1333.4453125,1951 L1338.328125,1942.2734375 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip33)" />
<clipPath id="clip34"><path d="M1295,1907 L1370,1907 L1370,1955 L1295,1955 L1295,1907 Z" /></clipPath>
<path d="M1328.3320313,1942.40625 L1333.4453125,1951 L1338.328125,1942.2734375 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip34)" />
<clipPath id="clip35"><path d="M1296,2055 L1371,2055 L1371,2122 L1296,2122 L1296,2055 Z" /></clipPath>
<path d="M1334,2059 L1334,2118" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip35)" />
<clipPath id="clip36"><path d="M1296,2055 L1371,2055 L1371,2122 L1296,2122 L1296,2055 Z" /></clipPath>
<path d="M1329,2109.3398438 L1334,2118 L1339,2109.3398438 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip36)" />
<clipPath id="clip37"><path d="M1296,2055 L1371,2055 L1371,2122 L1296,2122 L1296,2055 Z" /></clipPath>
<path d="M1329,2109.3398438 L1334,2118 L1339,2109.3398438 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip37)" />
<clipPath id="clip38"><path d="M263,1900 L338,1900 L338,1942 L263,1942 L263,1900 Z" /></clipPath>
<path d="M300,1904 L299.6171875,1938" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip38)" />
<clipPath id="clip39"><path d="M263,1900 L338,1900 L338,1942 L263,1942 L263,1900 Z" /></clipPath>
<path d="M294.7148438,1929.2851563 L299.6171875,1938 L304.7148438,1929.3984375 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip39)" />
<clipPath id="clip40"><path d="M263,1900 L338,1900 L338,1942 L263,1942 L263,1900 Z" /></clipPath>
<path d="M294.7148438,1929.2851563 L299.6171875,1938 L304.7148438,1929.3984375 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip40)" />
</svg>

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

View file

@ -0,0 +1,218 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="1458" height="2526" viewBox="0 0 1458 2526">
<style type="text/css"><![CDATA[
text { font:12px Dialog; }
]]></style>
<rect x="-485" y="-485" width="2428" height="3496" style="fill:rgb(255,255,255);stroke:none" />
<clipPath id="clip1"><path d="M468,32 L867,32 L867,101 L468,101 L468,32 Z" /></clipPath>
<path d="M470,34 L470,98 L864,98 L864,34 Z" style="fill:rgb(202,221,254);stroke:none" clip-path="url(#clip1)" />
<clipPath id="clip2"><path d="M468,32 L867,32 L867,101 L468,101 L468,32 Z" /></clipPath>
<path d="M470,34 L470,98 L864,98 L864,34 Z" style="fill:none;stroke:rgb(61,83,127)" clip-path="url(#clip2)" />
<text x="503" y="71" style="font:18px Open Sans">Friendica - Contact request</text>
<image x="0" y="0" width="834" height="74" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA0IAAABKCAYAAACW5eSEAAAEYElEQVR42u3dyW+VVRjAYRKNf4BSRFwwCImEQEAs2tpbCjIoIkJLC1KMgGAISlBQDGPgKhWQWKCATG3BtiiiRGIMCw0gaQspCGUokxJKyz+AsuiGvt7WIcatq9s8T/Iubr6czdn9cr7v3G7dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKBLi4j/NQAAAGkfQnkHrndPHGgqyam5cjE1bZ1z4GpjouZKsuOZEAIAALpUCD1fc2F6VsWFexnD58Xgov0xeevVmFR6JfJWHY2hi/dETlXT3UR101QhBAAAdIkQGrWvsShRdbl92LzD8djEszF8YVMU7WqJop0tUZiagu3NMXL1D5Fbfbl9VNWlIiEEAACkdQglKs5lJCov/pb9/tGYVHorxpfcjGm7W2L6npaYUd4aeWtuRL+ZjTFkflP0G1sZo6qbfs/+/EIPIQQAAKRvCO1pTA55a0dkL70W+WW349W9ralJRVBFa+Rvb46cVdej/+wL0XPK2XhkXEMMLF4fid3nS4QQAACQtiGUs/NcY9+RZfHMkiudr8LNKG+J4srWmLmvNcZtvBkjP7wReclr8UTxieg57lD0yV4RmSXfX00tf8gOAgAA6RlC2862Zb7dGJO3Nv/5OlxFa7y2vzVer7oTOWtvxMubf40Ri09G1pIvYumpulh25lTk7/rqfmp5LzsIAACkZwhtaWh7cf31f74LKu4MoTuRv6M5esz6OTKmnYin3zkUyxpSAbSpOp6du6Ezhgbk5ubaQQAAID1D6NPTjYn3jkT+9ttRtOt25wUJHSdChbtuRt/Zx+PJOdUxfl1NjF9dGbkLK+Kl5Lb44FRde/f+/Z+ygwAAQFqGUGJDfXLo3K0xJvlLDJp3KV7ZciuKy29FQWlD5G/6OlY01Mfcg0fizYPfxpSN+2JZ6vcL67bXp5Zn2EEAACAtQyj7k7oeOR/X3s1acCQeHncmBsxqjILN56Ow9HCsTEXPmBV7Ykb5NzH/8HedETT2o4q2xzMnD00tf9AOAgAAaRlCnadCH56c+lzyp/Y+OTtixLtNMSH5Yyw/XZuKoeroN3Fb5CzaGwWllZG7vLx90JzN8zoiyPXZAABAWodQ57dCa08UZq06dm/YG2WRveCzWHmmPsYuLY2Ja8piRUNdjFm7v23o/N2zUsse+HsNAABAWodQx+StOd49seZYSeaiL68WbKm53xFDy0/Xtk9IltU+OnzC4G5/nQQJIQAAoMuE0L8Cp+PPUnsNHD06t3vv3h23w2X8N4I65g/3mXiK17zpCgAAAABJRU5ErkJggg==" /><clipPath id="clip3"><path d="M1006,236 L1266,236 L1266,278 L1006,278 L1006,236 Z" /></clipPath>
<path d="M1016,238 C1011.5820313,238 1008,241.5820313 1008,246 L1008,267 C1008,271.4179688 1011.5820313,275 1016,275 L1255,275 C1259.4179688,275 1263,271.4179688 1263,267 L1263,246 C1263,241.5820313 1259.4179688,238 1255,238 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip3)" />
<clipPath id="clip4"><path d="M1006,236 L1266,236 L1266,278 L1006,278 L1006,236 Z" /></clipPath>
<path d="M1016,238 C1011.5820313,238 1008,241.5820313 1008,246 L1008,267 C1008,271.4179688 1011.5820313,275 1016,275 L1255,275 C1259.4179688,275 1263,271.4179688 1263,267 L1263,246 C1263,241.5820313 1259.4179688,238 1255,238 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip4)" />
<text x="1021" y="259" style="font:13px Tahoma">karenn@karenhompage.com</text>
<image x="0" y="0" width="1252" height="265" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABOQAAAEJCAYAAAA0I/jnAAAIjElEQVR42u3d3ZPNdRzAcTMZf0Ah6cJDzGQMQ6Jse9aSh5LErl2ymhCNUUZRGo/DkQ2ZFos87S7ZVVIm0zQuapBhmSXWw3oqg13/gHKxN/bTOac0xt1hpqvXa+Zzceacz8338j2/3/m2agUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/ysiHmkAAAAAgCw8GNjyd19pm9jdUJpbc/Fcapozs/tSfaLmYjL9nSAHAAAAAI/g/rj2cs3ZCQMrz95p12969CreGWPWX4rRZRcjf/GB6DNnW+TuaridqG4YJ8gBAAAAwEO6F9YG76gvTuy60NJ3+r54atSp6DerIYq3NEbx5sYoSk3hxhsxaMnPkVd9oWXwrvPFghwAAAAAPIR0VEtUnm6XqDr3Z87HB2J02fUYUXotxm9tjAnbGmNiRVPkL70aXSfVR+8ZDdF1WFUMrm74K+ers+0FOQAAAADIUibIbatP9n5vU+TMuxwF5Tfjze1NqWmMiZVNUbDxRuQuvhLdppyNDmNPxRPD66JHycpIbD1TKsgBAAAAQJbSUS138+n6LoPK44W5FzOvqE6saIySqqaYtKMphq++FoOWX4385OV4puRwdBi+NzrnLIz+pT9dSq23cYIAAAAAkIVMkNtwqrn/+/UxZv2Nf15TrWyKt3Y2xdu7bkXusqvx+to/YsCcIzFw7tcx7/ixmH/yeBRs+fZuar2jEwQAAACALGSC3Lq65ldXXvnvf+NKMkHuVhRsuhHtJ/8W7cYfjuc/2Bvz645HwZrqeHHaqkyU656Xl+cEAQAAACALmSD3xYn6xEf7o2DjzSjecjNzkUP6CbmiLdeiy5RD8ezU6hixoiZGLKmKvFmV8VpyQ3xy/FhL227dnnOCAAAAAJCFzKUOq2qTfaatj6HJ36Pn9PPxxrrrUVJxPQrL6qJgzXexsK42pu3ZH+/u+SHGrt4R81OfX1mxsTa13s4JAgAAAEAW0kEu5/Nj7XM/O3p74Mz98fjwk9F9cn0Urj0TRWX7YlFdbQxduC0mVnwfM/b9mIlxwz6tbH66/5g+qfXWThAAAAAAspAOcpmn5JYfGfdS8teWzrmbYsCHDTEy+UssOHE0isqqo+uoDZE7e3sUllVF3oKKlp5T105PrbZO7wEAAAAAWbgX5DL/JbfscNHAxQfv9H2nPHJmfhmLTtbGsHllMWppeSysOxZDl+1s7jNj6+TU2mP3dgAAAACALNwf5NKTv/RQ28TSg6X9Z39zqXBdzd10lFtw4mjLyGT50Sf7jezV6t8n4wQ5AAAAAHgIDwa5+0Jbm9R07DFkSF7bTp3St6mmL3Bo/eDv/gYwZniKtpg81wAAAABJRU5ErkJggg==" /><clipPath id="clip5"><path d="M235,234 L425,234 L425,276 L235,276 L235,234 Z" /></clipPath>
<path d="M245,236 C240.5820313,236 237,239.5820313 237,244 L237,265 C237,269.4179688 240.5820313,273 245,273 L414,273 C418.4179688,273 422,269.4179688 422,265 L422,244 C422,239.5820313 418.4179688,236 414,236 Z" style="fill:rgb(0,131,191);stroke:none" clip-path="url(#clip5)" />
<clipPath id="clip6"><path d="M235,234 L425,234 L425,276 L235,276 L235,234 Z" /></clipPath>
<path d="M245,236 C240.5820313,236 237,239.5820313 237,244 L237,265 C237,269.4179688 240.5820313,273 245,273 L414,273 C418.4179688,273 422,269.4179688 422,265 L422,244 C422,239.5820313 418.4179688,236 414,236 Z" style="fill:none;stroke:rgb(0,131,191)" clip-path="url(#clip6)" />
<text x="251" y="257" style="font:13px Tahoma">bob@example.com</text>
<image x="0" y="0" width="411" height="263" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZsAAAEHCAYAAAB4POvAAAAFDElEQVR42u3c3ZOOZRzAcTM1/QG1K+nAS8xkDEOibPusl1glFYslqwnRGGUUpWExPLKhpsUir7tkV0mZTNM4qEHGLrPELtaiDHb9A8rBnthf9z5NTdPR4rDPZ+Y6euY6uU6+87vv67k7dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+H+LiPtaAHDXsRm693JWam9DSW7VxXPJasmsvY11qaqL6bbfxAaA+4rN81X1kweX19/OHjAr+hTujrEbGuOV0osxdOmh6Dd/e+TuabiVqmyYIDYA3FNshu2qK0ztudDaf9aBeGzM6RgwtyEKtzZF4ZammJis8Zuux5BlP0Ze5YXWYXvOF4oNAHcVm1T5mexUxbnfcz44lEwy12JUydWYtK0pJm9viik7m2Po8ivRfWpd9J3dEN1HVsSwyoY/cr6o7yg2ALQ/Ntvr0n3f3hw5Cy9FQdmNeG1Hc7KS0JQ3R0Ey0eQuvRw9ptdHp3Gn45H82uhVtDpS286WiA0A7Y5N7pYzdd2GlMUzCy5mHptN2dkURRXNMXVXc+SvvRpDVl6JoelL8UTR0eiUvz+65hTHwJIfGpPtDzlBANoXm42nWwa+UxdjN1z/69FZMtG8vrs53thzM3JXXImX1/0Wg+Yfi8ELvoyFJ6pj0akTUbD16zvJ9s5OEID2xWZ9bcuLqy//856mKBObm1Gw+Xp0nPZLZE86Gk+/uz8W1SaR+bQynp25JhOcnnl5eU4QgPbF5rOTdan3D0bBphtRuPVG5lJA22QzcevV6Db9SDw5ozJGraqKUcsqIm9uebyU3hgfnqhuzerR4yknCEC7YpNaU5PuN3NDjEj/Gr1nnY9X11+Lop3XYnxpbTLJfBPFtTUxc9/BeGvfdzFu7a5kwqmJF1Ztqkm2ZztBANoVm5xPqjvmfnz81uA5B+Ph/FPRc1pdjF93NiaWHoglSVhGFG9Ppp1vY/aB7zOhGflRecvjA8f2S7Y/6AQBaFdsMtPNymMTnkv/3No1d3MMeq8hRqd/isUnjyfBqYzuYzZG7rwdyaRTEXmLd7b2nrFuVltoXH0G4K5ik3l3s+LoxMFLD9/u/2ZZ5Mz5PJacSqaYhaUxZnlZFNdWx4gVu1v6zd42Ldn2gC8IAHBPscl8iHP5kazU8sMlA+d91Th+fdWdtuAkE07r6HTZ8UcHjO7z90QjNgDcc2z+FZG2P2x27jV8eF5Wly5tt86y/xuatvUnRFJ4iu/wPU8AAAAASUVORK5CYII=" /><clipPath id="clip7"><path d="M953,363 L1344,363 L1344,451 L953,451 L953,363 Z" /></clipPath>
<path d="M962,364 C957.5820313,364 954,367.5820313 954,372 L954,441 C954,445.4179688 957.5820313,449 962,449 L1334,449 C1338.4179688,449 1342,445.4179688 1342,441 L1342,372 C1342,367.5820313 1338.4179688,364 1334,364 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip7)" />
<text x="1073" y="386" style="font:13px Open Sans"> dfrn_request.php</text>
<text x="1146" y="409" style="font:13px Open Sans">-</text>
<text x="968" y="432" style="font:13px Open Sans">https://karenhompage/dfrn_request/karin</text>
<clipPath id="clip8"><path d="M890,808 L1416,808 L1416,1448 L890,1448 L890,808 Z" /></clipPath>
<path d="M899,809 C894.5820313,809 891,812.5820313 891,817 L891,1438 C891,1442.4179688 894.5820313,1446 899,1446 L1406,1446 C1410.4179688,1446 1414,1442.4179688 1414,1438 L1414,817 C1414,812.5820313 1410.4179688,809 1406,809 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip8)" />
<text x="904" y="831" style="font:13px Open Sans">dfrn_request_post - SCENARIO 1</text>
<text x="904" y="854" style="font:13px Open Sans">----------------------------------------------</text>
<text x="904" y="900" style="font:13px Open Sans">- Cleanup old introductions that remain blocked + Cleanup </text>
<text x="904" y="923" style="font:13px Open Sans">any old email intros - which will have a greater lifetime</text>
<text x="904" y="969" style="font:13px Open Sans">- probe_url Bobs posted dfrn_url and get the network with </text>
<text x="904" y="992" style="font:13px Open Sans">webfinger_dfrn</text>
<text x="904" y="1038" style="font:13px Open Sans">- try to select all contact data of Bob (contact table) by the </text>
<text x="904" y="1061" style="font:13px Open Sans">url ($_POST['dfrn_url] and profile uid ($a-&gt;profile['uid']) </text>
<text x="904" y="1084" style="font:13px Open Sans">where self = 0 to look if this contact is already there (if </text>
<text x="904" y="1107" style="font:13px Open Sans">issued-id or rel is already available return here because it </text>
<text x="904" y="1130" style="font:13px Open Sans">seems that we are already connected)</text>
<text x="904" y="1176" style="font:13px Open Sans">- create a issued-id with $issued_id = random_string();</text>
<text x="904" y="1222" style="font:13px Open Sans">- if we already found a contact record above update the </text>
<text x="904" y="1245" style="font:13px Open Sans">issued-id with the one we have created</text>
<text x="904" y="1291" style="font:13px Open Sans">- otherwise if Bob is not already in the contact table scrape </text>
<text x="904" y="1314" style="font:13px Open Sans">Bobs profile and create a new contact with this data (e.g. </text>
<text x="904" y="1337" style="font:13px Open Sans">the scraped issued-id / profiles pubkey becomes contacts </text>
<text x="904" y="1360" style="font:13px Open Sans">site-pubkey) in the contact table (blocked = 1, pending = 1)</text>
<text x="904" y="1406" style="font:13px Open Sans">- select this created contact from contact table and create </text>
<text x="904" y="1429" style="font:13px Open Sans">an intro in the intro table (blocked = 1)</text>
<clipPath id="clip9"><path d="M925,693 L1374,693 L1374,735 L925,735 L925,693 Z" /></clipPath>
<path d="M934,694 C929.5820313,694 926,697.5820313 926,702 L926,725 C926,729.4179688 929.5820313,733 934,733 L1364,733 C1368.4179688,733 1372,729.4179688 1372,725 L1372,702 C1372,697.5820313 1368.4179688,694 1364,694 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip9)" />
<text x="939" y="716" style="font:13px Open Sans">$_POST['dfrn_url'] is transmited and is Bobs profile url</text>
<clipPath id="clip10"><path d="M888,1557 L1418,1557 L1418,1852 L888,1852 L888,1557 Z" /></clipPath>
<path d="M897,1558 C892.5820313,1558 889,1561.5820313 889,1566 L889,1842 C889,1846.4179688 892.5820313,1850 897,1850 L1408,1850 C1412.4179688,1850 1416,1846.4179688 1416,1842 L1416,1566 C1416,1561.5820313 1412.4179688,1558 1408,1558 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip10)" />
<text x="902" y="1580" style="font:13px Open Sans">redirect to Bobs request page</text>
<text x="902" y="1626" style="font:13px Open Sans">goaway($parms['dfrn-request'] . "?dfrn_url=$dfrn_url"</text>
<text x="902" y="1649" style="font:13px Open Sans"> . '&amp;dfrn_version=' . </text>
<text x="902" y="1672" style="font:13px Open Sans">DFRN_PROTOCOL_VERSION</text>
<text x="902" y="1695" style="font:13px Open Sans"> . '&amp;confirm_key=' . $hash</text>
<text x="902" y="1718" style="font:13px Open Sans"> . (($aes_allow) ? "&amp;aes_allow=1" : "")</text>
<text x="902" y="1741" style="font:13px Open Sans"> );</text>
<text x="902" y="1787" style="font:13px Open Sans">http://example.com/dfrn_request/bob?dfrn_url=6874747</text>
<text x="902" y="1810" style="font:13px Open Sans">03a2f2f6b6172656e686f6d65706167652e636f6d2f70726f66</text>
<text x="902" y="1833" style="font:13px Open Sans">696c652f6b6172656e&amp;aes_allow=1&amp;confirm_key=”ABC123”</text>
<clipPath id="clip11"><path d="M287,1180 L464,1180 L464,1222 L287,1222 L287,1180 Z" /></clipPath>
<path d="M296,1181 C291.5820313,1181 288,1184.5820313 288,1189 L288,1212 C288,1216.4179688 291.5820313,1220 296,1220 L454,1220 C458.4179688,1220 462,1216.4179688 462,1212 L462,1189 C462,1184.5820313 458.4179688,1181 454,1181 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip11)" />
<text x="302" y="1203" style="font:13px Open Sans">dfrn_request.php</text>
<clipPath id="clip12"><path d="M134,1399 L624,1399 L624,2315 L134,2315 L134,1399 Z" /></clipPath>
<path d="M143,1400 C138.5820313,1400 135,1403.5820313 135,1408 L135,2305 C135,2309.4179688 138.5820313,2313 143,2313 L614,2313 C618.4179688,2313 622,2309.4179688 622,2305 L622,1408 C622,1403.5820313 618.4179688,1400 614,1400 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip12)" />
<text x="149" y="1422" style="font:13px Open Sans">http://example.com/dfrn_request/bob?</text>
<text x="149" y="1445" style="font:13px Open Sans">dfrn_url=</text>
<text x="149" y="1468" style="font:13px Open Sans">687474703a2f2f6b6172656e686f6d65706167652e</text>
<text x="149" y="1491" style="font:13px Open Sans">636f6d2f70726f66696c652f6b6172656e&amp;aes_allow=1&amp;</text>
<text x="149" y="1514" style="font:13px Open Sans">confirm_key=”ABC123”</text>
<text x="149" y="1560" style="font:13px Open Sans">dfrn_request_content()</text>
<text x="149" y="1583" style="font:13px Open Sans">------------------------------------------</text>
<text x="149" y="1606" style="font:13px Open Sans">- copy the posted parameters (dfrn_url, key and so on) </text>
<text x="149" y="1629" style="font:13px Open Sans">to $_POST</text>
<text x="149" y="1698" style="font:13px Open Sans"> dfrn_request_post() - SCENARIO 2 </text>
<text x="149" y="1721" style="font:13px Open Sans">($_POST['localconfirm'] == 1)</text>
<text x="149" y="1744" style="font:13px Open Sans">-----------------------------------------------------------------------</text>
<text x="149" y="1767" style="font:13px Open Sans">- if(local_user() &amp;&amp; ($a-&gt;user['nickname'] == $a-</text>
<text x="149" y="1790" style="font:13px Open Sans">&gt;argv[1]) &amp;&amp; (x($_POST,'dfrn_url')))</text>
<text x="149" y="1813" style="font:13px Open Sans">-&gt;</text>
<text x="149" y="1859" style="font:13px Open Sans">- $confirm_key comes from $_POST</text>
<text x="149" y="1905" style="font:13px Open Sans">- get data for contact Karen (contact table) by </text>
<text x="149" y="1928" style="font:13px Open Sans">$dfrn_url (contacts url and nurl) -&gt; if contact Karen </text>
<text x="149" y="1951" style="font:13px Open Sans">does already have a dfrn-id Bob seems already </text>
<text x="149" y="1974" style="font:13px Open Sans">connected with Karen (abort here)</text>
<text x="149" y="2020" style="font:13px Open Sans">- if this contact (Karen) isn't available in the contact </text>
<text x="149" y="2043" style="font:13px Open Sans">tabel, scrape Karens profile page to pick up the dfrn </text>
<text x="149" y="2066" style="font:13px Open Sans">links, key, fn, and photo</text>
<text x="149" y="2112" style="font:13px Open Sans">- create a contact for Karen in the contact table with </text>
<text x="149" y="2135" style="font:13px Open Sans">the scraped data with blocked = 1 and pending = 1 </text>
<text x="149" y="2158" style="font:13px Open Sans">(Karens pubkey becomes the contact site-pubkey)</text>
<text x="149" y="2204" style="font:13px Open Sans">- fetch_url($dfrn_request . '?confirm_key=' . </text>
<text x="149" y="2227" style="font:13px Open Sans">$confirm_key);</text>
<text x="149" y="2273" style="font:13px Open Sans">- fetch_url(http://karenhomepage.com/dfrn_request?</text>
<text x="149" y="2296" style="font:13px Open Sans">confirm_key=”ABC123”)</text>
<clipPath id="clip13"><path d="M1061,2027 L1238,2027 L1238,2069 L1061,2069 L1061,2027 Z" /></clipPath>
<path d="M1070,2028 C1065.5820313,2028 1062,2031.5820313 1062,2036 L1062,2059 C1062,2063.4179688 1065.5820313,2067 1070,2067 L1228,2067 C1232.4179688,2067 1236,2063.4179688 1236,2059 L1236,2036 C1236,2031.5820313 1232.4179688,2028 1228,2028 Z" style="fill:rgb(127,127,127);stroke:none" clip-path="url(#clip13)" />
<text x="1075" y="2050" style="font:13px Open Sans">dfrn_request.php</text>
<clipPath id="clip14"><path d="M857,2205 L1444,2205 L1444,2454 L857,2454 L857,2205 Z" /></clipPath>
<path d="M866,2206 C861.5820313,2206 858,2209.5820313 858,2214 L858,2444 C858,2448.4179688 861.5820313,2452 866,2452 L1434,2452 C1438.4179688,2452 1442,2448.4179688 1442,2444 L1442,2214 C1442,2209.5820313 1438.4179688,2206 1434,2206 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip14)" />
<text x="871" y="2228" style="font:13px Open Sans">http://karenhomepage.com/dfrn_request?confirm_key=”ABC123”</text>
<text x="871" y="2274" style="font:13px Open Sans">dfrn_request_content() -</text>
<text x="871" y="2297" style="font:13px Open Sans">(elseif((x($_GET,'confirm_key')) &amp;&amp; strlen($_GET['confirm_key'])) )</text>
<text x="871" y="2320" style="font:13px Open Sans">----------------------------------------------------------------------------------------------</text>
<text x="871" y="2366" style="font:13px Open Sans">- select the intro by confirm_key (intro table) -&gt; get contact id</text>
<text x="871" y="2389" style="font:13px Open Sans">- use the intro contact id to get the contact in the contact table</text>
<text x="871" y="2412" style="font:13px Open Sans">- build a notification package ( notification(array.....) )</text>
<text x="871" y="2435" style="font:13px Open Sans">- update intro in intro table (blocked = 0)</text>
<clipPath id="clip15"><path d="M227,2424 L531,2424 L531,2512 L227,2512 L227,2424 Z" /></clipPath>
<path d="M236,2425 C231.5820313,2425 228,2428.5820313 228,2433 L228,2502 C228,2506.4179688 231.5820313,2510 236,2510 L521,2510 C525.4179688,2510 529,2506.4179688 529,2502 L529,2433 C529,2428.5820313 525.4179688,2425 521,2425 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip15)" />
<text x="242" y="2447" style="font:13px Open Sans">Bob stays on his Friendica server</text>
<text x="242" y="2493" style="font:13px Open Sans">- goaway($forwardurl);</text>
<clipPath id="clip16"><path d="M14,14 L370,14 L370,125 L14,125 L14,14 Z" /></clipPath>
<path d="M23,15 C18.5820313,15 15,18.5820313 15,23 L15,115 C15,119.4179688 18.5820313,123 23,123 L360,123 C364.4179688,123 368,119.4179688 368,115 L368,23 C368,18.5820313 364.4179688,15 360,15 Z" style="fill:rgb(255,255,255);stroke:none" clip-path="url(#clip16)" />
<text x="29" y="38" style="font:13px Open Sans">Note: this chart respects only dfrn </text>
<text x="29" y="61" style="font:13px Open Sans">contacts and focuses on key exchange </text>
<text x="29" y="83" style="font:13px Open Sans">(for other areas it might be very </text>
<text x="29" y="106" style="font:13px Open Sans">incomplete)</text>
<clipPath id="clip17"><path d="M871,491 L1431,491 L1431,648 L871,648 L871,491 Z" /></clipPath>
<path d="M880,492 C875.5820313,492 872,495.5820313 872,500 L872,638 C872,642.4179688 875.5820313,646 880,646 L1421,646 C1425.4179688,646 1429,642.4179688 1429,638 L1429,500 C1429,495.5820313 1425.4179688,492 1421,492 Z" style="fill:rgb(255,255,3);stroke:none" clip-path="url(#clip17)" />
<text x="885" y="514" style="font:13px Open Sans">dfrn_request_content()</text>
<text x="885" y="537" style="font:13px Open Sans">------------------------------------</text>
<text x="885" y="583" style="font:13px Open Sans">- the page for the on Katrins server where Bob do a connection </text>
<text x="885" y="606" style="font:13px Open Sans">request</text>
<text x="885" y="629" style="font:13px Open Sans">- the form transmit on submit Bobs profile url as dfrn_url</text>
<clipPath id="clip18"><path d="M402,267 L974,267 L974,313 L402,313 L402,267 Z" /></clipPath>
<path d="M422,271.734375 L954,370.5703125" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip18)" />
<clipPath id="clip19"><path d="M402,329 L974,329 L974,377 L402,377 L402,329 Z" /></clipPath>
<path d="M422,271.734375 L954,370.5703125" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip19)" />
<clipPath id="clip20"><path d="M402,311 L974,311 L974,331 L402,331 L402,311 Z" /></clipPath>
<path d="M422,271.734375 L954,370.5703125" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip20)" />
<clipPath id="clip21"><path d="M402,267 L974,267 L974,377 L402,377 L402,267 Z" /></clipPath>
<path d="M944.5703125,373.9023438 L954,370.5703125 L946.3984375,364.0703125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip21)" />
<clipPath id="clip22"><path d="M402,267 L974,267 L974,377 L402,377 L402,267 Z" /></clipPath>
<path d="M944.5703125,373.9023438 L954,370.5703125 L946.3984375,364.0703125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip22)" />
<text x="405" y="323" style="font:10px Georgia">bob wants to make a request and is directed from karens profile page to karens dfrn-request page</text>
<clipPath id="clip23"><path d="M1111,729 L1186,729 L1186,813 L1111,813 L1111,729 Z" /></clipPath>
<path d="M1149.1875,733 L1149.4335938,763.3984375 L1149.5585938,778.6015625 L1149.8046875,809" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip23)" />
<clipPath id="clip24"><path d="M1111,729 L1186,729 L1186,813 L1111,813 L1111,729 Z" /></clipPath>
<path d="M1144.734375,800.3789063 L1149.8046875,809 L1154.734375,800.3007813 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip24)" />
<clipPath id="clip25"><path d="M1111,729 L1186,729 L1186,813 L1111,813 L1111,729 Z" /></clipPath>
<path d="M1144.734375,800.3789063 L1149.8046875,809 L1154.734375,800.3007813 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip25)" />
<clipPath id="clip26"><path d="M1115,1442 L1190,1442 L1190,1562 L1115,1562 L1115,1442 Z" /></clipPath>
<path d="M1152.7773438,1446 L1152.625,1558" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip26)" />
<clipPath id="clip27"><path d="M1115,1442 L1190,1442 L1190,1562 L1115,1562 L1115,1442 Z" /></clipPath>
<path d="M1147.6367188,1549.3320313 L1152.625,1558 L1157.6367188,1549.3476563 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip27)" />
<clipPath id="clip28"><path d="M1115,1442 L1190,1442 L1190,1562 L1115,1562 L1115,1442 Z" /></clipPath>
<path d="M1147.6367188,1549.3320313 L1152.625,1558 L1157.6367188,1549.3476563 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip28)" />
<clipPath id="clip29"><path d="M458,1201 L893,1201 L893,1375 L458,1375 L458,1201 Z" /></clipPath>
<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip29)" />
<clipPath id="clip30"><path d="M458,1391 L893,1391 L893,1565 L458,1565 L458,1391 Z" /></clipPath>
<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip30)" />
<clipPath id="clip31"><path d="M458,1373 L575,1373 L575,1393 L458,1393 L458,1373 Z" /></clipPath>
<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip31)" />
<clipPath id="clip32"><path d="M776,1373 L893,1373 L893,1393 L776,1393 L776,1373 Z" /></clipPath>
<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip32)" />
<clipPath id="clip33"><path d="M573,1373 L778,1373 L778,1393 L573,1393 L573,1373 Z" /></clipPath>
<path d="M889,1561.9492188 L462,1205.3515625" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip33)" />
<clipPath id="clip34"><path d="M458,1201 L893,1201 L893,1565 L458,1565 L458,1201 Z" /></clipPath>
<path d="M471.8515625,1207.0664063 L462,1205.3515625 L465.4414063,1214.7421875 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip34)" />
<clipPath id="clip35"><path d="M458,1201 L893,1201 L893,1565 L458,1565 L458,1201 Z" /></clipPath>
<path d="M471.8515625,1207.0664063 L462,1205.3515625 L465.4414063,1214.7421875 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip35)" />
<text x="576" y="1385" style="font:10px Georgia">redirict to bobs dfrn_request page</text>
<clipPath id="clip36"><path d="M339,1216 L414,1216 L414,1404 L339,1404 L339,1216 Z" /></clipPath>
<path d="M375.1171875,1220 L376.0625,1400" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip36)" />
<clipPath id="clip37"><path d="M339,1216 L414,1216 L414,1404 L339,1404 L339,1216 Z" /></clipPath>
<path d="M371.015625,1391.3671875 L376.0625,1400 L381.015625,1391.3125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip37)" />
<clipPath id="clip38"><path d="M339,1216 L414,1216 L414,1404 L339,1404 L339,1216 Z" /></clipPath>
<path d="M371.015625,1391.3671875 L376.0625,1400 L381.015625,1391.3125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip38)" />
<clipPath id="clip39"><path d="M618,2024 L1072,2024 L1072,2158 L618,2158 L618,2024 Z" /></clipPath>
<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip39)" />
<clipPath id="clip40"><path d="M618,2174 L1072,2174 L1072,2309 L618,2309 L618,2174 Z" /></clipPath>
<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip40)" />
<clipPath id="clip41"><path d="M618,2156 L650,2156 L650,2176 L618,2176 L618,2156 Z" /></clipPath>
<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip41)" />
<clipPath id="clip42"><path d="M1041,2156 L1072,2156 L1072,2176 L1041,2176 L1041,2156 Z" /></clipPath>
<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip42)" />
<clipPath id="clip43"><path d="M648,2156 L1043,2156 L1043,2176 L648,2176 L648,2156 Z" /></clipPath>
<path d="M622,2305.015625 L1068.1992188,2028" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip43)" />
<clipPath id="clip44"><path d="M618,2024 L1072,2024 L1072,2309 L618,2309 L618,2024 Z" /></clipPath>
<path d="M1063.4804688,2036.8164063 L1068.1992188,2028 L1058.2070313,2028.3203125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip44)" />
<clipPath id="clip45"><path d="M618,2024 L1072,2024 L1072,2309 L618,2309 L618,2024 Z" /></clipPath>
<path d="M1063.4804688,2036.8164063 L1068.1992188,2028 L1058.2070313,2028.3203125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip45)" />
<text x="651" y="2168" style="font:10px Georgia">http://karenhomepage.com/dfrn_request?confirm_key=”ABC123”</text>
<clipPath id="clip46"><path d="M1111,2063 L1186,2063 L1186,2210 L1111,2210 L1111,2063 Z" /></clipPath>
<path d="M1149.0703125,2067 L1149.5625,2206" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip46)" />
<clipPath id="clip47"><path d="M1111,2063 L1186,2063 L1186,2210 L1111,2210 L1111,2063 Z" /></clipPath>
<path d="M1144.53125,2197.359375 L1149.5625,2206 L1154.53125,2197.3203125 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip47)" />
<clipPath id="clip48"><path d="M1111,2063 L1186,2063 L1186,2210 L1111,2210 L1111,2063 Z" /></clipPath>
<path d="M1144.53125,2197.359375 L1149.5625,2206 L1154.53125,2197.3203125 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip48)" />
<clipPath id="clip49"><path d="M342,2309 L417,2309 L417,2429 L342,2429 L342,2309 Z" /></clipPath>
<path d="M378.875,2313 L378.5351563,2425" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip49)" />
<clipPath id="clip50"><path d="M342,2309 L417,2309 L417,2429 L342,2429 L342,2309 Z" /></clipPath>
<path d="M373.5625,2416.3242188 L378.5351563,2425 L383.5625,2416.3554688 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip50)" />
<clipPath id="clip51"><path d="M342,2309 L417,2309 L417,2429 L342,2429 L342,2309 Z" /></clipPath>
<path d="M373.5625,2416.3242188 L378.5351563,2425 L383.5625,2416.3554688 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip51)" />
<clipPath id="clip52"><path d="M1111,445 L1186,445 L1186,496 L1111,496 L1111,445 Z" /></clipPath>
<path d="M1148.7851563,449 L1149.3125,492" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip52)" />
<clipPath id="clip53"><path d="M1111,445 L1186,445 L1186,496 L1111,496 L1111,445 Z" /></clipPath>
<path d="M1144.2070313,483.4023438 L1149.3125,492 L1154.2070313,483.2773438 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip53)" />
<clipPath id="clip54"><path d="M1111,445 L1186,445 L1186,496 L1111,496 L1111,445 Z" /></clipPath>
<path d="M1144.2070313,483.4023438 L1149.3125,492 L1154.2070313,483.2773438 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip54)" />
<clipPath id="clip55"><path d="M1026,642 L1272,642 L1272,662 L1026,662 L1026,642 Z" /></clipPath>
<path d="M1149.703125,646 L1149.2695313,694" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip55)" />
<clipPath id="clip56"><path d="M1026,678 L1272,678 L1272,698 L1026,698 L1026,678 Z" /></clipPath>
<path d="M1149.703125,646 L1149.2695313,694" style="fill:none;stroke:rgb(182,44,37);stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip56)" />
<clipPath id="clip57"><path d="M1026,660 L1272,660 L1272,680 L1026,680 L1026,660 Z" /></clipPath>
<path d="M1149.703125,646 L1149.2695313,694" style="fill:none;stroke:rgb(182,44,37);opacity:0.09803921568627451;stroke-width:3;stroke-dasharray:18,9;stroke-dashoffset:0" clip-path="url(#clip57)" />
<clipPath id="clip58"><path d="M1026,642 L1272,642 L1272,698 L1026,698 L1026,642 Z" /></clipPath>
<path d="M1144.3476563,685.296875 L1149.2695313,694 L1154.3476563,685.3867188 Z" style="fill:rgb(182,44,37);stroke:none" clip-path="url(#clip58)" />
<clipPath id="clip59"><path d="M1026,642 L1272,642 L1272,698 L1026,698 L1026,642 Z" /></clipPath>
<path d="M1144.3476563,685.296875 L1149.2695313,694 L1154.3476563,685.3867188 Z" style="fill:none;stroke:rgb(182,44,37);stroke-width:3" clip-path="url(#clip59)" />
<text x="1029" y="672" style="font:10px Georgia">Bob fills request form and presses submit</text>
</svg>

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -1,6 +1,6 @@
<?php
define('UPDATE_VERSION' , 1208);
define('UPDATE_VERSION' , 1209);
/**
*

4
util/convert_innodb.sql Normal file
View file

@ -0,0 +1,4 @@
SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' engine=InnoDB;')
FROM information_schema.tables
WHERE engine = 'MyISAM';

101
util/daemon.php Normal file
View file

@ -0,0 +1,101 @@
<?php
/**
* @file util/daemon.php
* @brief Run the poller from a daemon.
*
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
*/
function shutdown() {
posix_kill(posix_getpid(), SIGHUP);
}
if (in_array("start", $_SERVER["argv"])) {
$mode = "start";
}
if (in_array("stop", $_SERVER["argv"])) {
$mode = "stop";
}
if (in_array("status", $_SERVER["argv"])) {
$mode = "status";
}
if (!isset($mode)) {
die("Please use either 'start', 'stop' or 'status'.\n");
}
@include(".htconfig.php");
if (!isset($pidfile)) {
die('Please specify a pid file in the variable $pidfile in the .htconfig.php. For example:'."\n".
'$pidfile = "/path/to/daemon.pid";'."\n");
}
if (in_array($mode, array("stop", "status"))) {
$pid = @file_get_contents($pidfile);
if (!$pid) {
die("Pidfile wasn't found. Is the daemon running?\n");
}
}
if ($mode == "status") {
if (posix_kill($pid, 0)) {
die("Daemon process $pid is running.\n");
}
unlink($pidfile);
die("Daemon process $pid isn't running.\n");
}
if ($mode == "stop") {
posix_kill($pid, SIGTERM);
unlink($pidfile);
die("Worker daemon process $pid was killed.\n");
}
echo "Starting worker daemon.\n";
if (isset($a->config['php_path'])) {
$php = $a->config['php_path'];
} else {
$php = "php";
}
// Switch over to daemon mode.
if ($pid = pcntl_fork())
return; // Parent
fclose(STDIN); // Close all of the standard
fclose(STDOUT); // file descriptors as we
fclose(STDERR); // are running as a daemon.
register_shutdown_function('shutdown');
if (posix_setsid() < 0)
return;
if ($pid = pcntl_fork())
return; // Parent
$pid = getmypid();
file_put_contents($pidfile, $pid);
// Now running as a daemon.
while (true) {
// Just to be sure that this script really runs endlessly
set_time_limit(0);
// Call the poller
$cmdline = $php.' include/poller.php';
exec($cmdline);
// Now sleep for 5 minutes
sleep(300);
}
?>

File diff suppressed because it is too large Load diff

View file

@ -32,16 +32,30 @@ sudo apt-get install -y apache2
sudo a2enmod rewrite actions ssl
sudo cp /vagrant/util/vagrant_vhost.sh /usr/local/bin/vhost
sudo chmod guo+x /usr/local/bin/vhost
sudo vhost -s 192.168.22.10.xip.io -d /var/www -p /etc/ssl/xip.io -c xip.io -a friendica.dev
sudo a2dissite 000-default
sudo service apache2 restart
if [ $( lsb_release -c | cut -f 2 ) == "trusty" ]; then
sudo vhost -s 192.168.22.10.xip.io -d /var/www -p /etc/ssl/xip.io -c xip.io -a friendica-trusty.dev
sudo a2dissite 000-default
sudo service apache2 restart
elif [ $( lsb_release -c | cut -f 2 ) == "xenial" ]; then
sudo vhost -s 192.168.22.11.xip.io -d /var/www -p /etc/ssl/xip.io -c xip.io -a friendica-xenial.dev
sudo a2dissite 000-default
sudo systemctl restart apache2
fi
#Install php
echo ">>> Installing PHP5"
sudo apt-get install -y php5 libapache2-mod-php5 php5-cli php5-mysql php5-curl php5-gd
sudo apt-get install -y imagemagick
sudo apt-get install -y php5-imagick
sudo service apache2 restart
if [ $( lsb_release -c | cut -f 2 ) == "trusty" ]; then
echo ">>> Installing PHP5"
sudo apt-get install -y php5 libapache2-mod-php5 php5-cli php5-mysql php5-curl php5-gd
sudo apt-get install -y imagemagick
sudo apt-get install -y php5-imagick
sudo service apache2 restart
elif [ $( lsb_release -c | cut -f 2 ) == "xenial" ]; then
echo ">>> Installing PHP7"
sudo apt-get install -y php libapache2-mod-php php-cli php-mysql php-curl php-gd
sudo apt-get install -y imagemagick
sudo apt-get install -y php-imagick
sudo systemctl restart apache2
fi
#Install mysql
@ -59,12 +73,21 @@ Q1="GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;"
Q2="FLUSH PRIVILEGES;"
SQL="${Q1}${Q2}"
$MYSQL -uroot -proot -e "$SQL"
service mysql restart
if [ $( lsb_release -c | cut -f 2 ) == "trusty" ]; then
service mysql restart
elif [ $( lsb_release -c | cut -f 2 ) == "xenial" ]; then
systemctl restart mysql
fi
#configure rudimentary mail server (local delivery only)
#add Friendica accounts for local user accounts, use email address like vagrant@friendica.dev, read the email with 'mail'.
debconf-set-selections <<< "postfix postfix/mailname string friendica.dev"
if [ $( lsb_release -c | cut -f 2 ) == "trusty" ]; then
debconf-set-selections <<< "postfix postfix/mailname string friendica-trusty.dev"
elif [ $( lsb_release -c | cut -f 2 ) == "xenial" ]; then
debconf-set-selections <<< "postfix postfix/mailname string friendica-xenial.dev"
fi
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local Only'"
sudo apt-get install -y postfix mailutils libmailutils-dev
sudo echo -e "friendica1: vagrant\nfriendica2: vagrant\nfriendica3: vagrant\nfriendica4: vagrant\nfriendica5: vagrant" >> /etc/aliases && sudo newaliases

View file

@ -464,3 +464,20 @@ td.federation-data {
#settings-form .pageflags {
margin: 0 0 20px 30px;
}
/* admin pending user notes */
td.pendingnote {
padding-left: 20px;
padding-right: 20px;
}
td.pendingnote > p > span {
font-weight: bold;
}
/* warning message */
.warning-message {
padding: 10px;
margin: 5px;
border-left: 5px solid #f00;
font-weight: bold;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,13 @@
<div id='adminpage'>
<h1>{{$title}} - {{$page}}</h1>
{{if $showwarning}}
<div id="admin-warning-message-wrapper">
{{foreach $warningtext as $wt}}
<p class="warning-message">{{$wt}}</p>
{{/foreach}}
</div>
{{/if}}
<dl>
<dt>{{$queues.label}}</dt>

View file

@ -39,6 +39,9 @@
<a href="{{$baseurl}}/regmod/deny/{{$u.hash}}" title='{{$deny}}'><span class='icon dislike'></span></a>
</td>
</tr>
<tr>
<td class="pendingnote"><p><span>{{$pendingnotetext}}:</span> {{$u.note}}</p></td>
</tr>
{{/foreach}}
</tbody>
</table>

View file

@ -57,6 +57,10 @@
</div>
<div id="register-nickname-end" ></div>
{{if $permonly}}
{{include file="field_textarea.tpl" field=$permonlybox}}
{{/if}}
{{$publish}}
<div id="register-submit-wrapper">

View file

@ -9,6 +9,7 @@
{{include file="field_themeselect.tpl" field=$mobile_theme}}
{{include file="field_input.tpl" field=$itemspage_mobile_network}}
{{include file="field_input.tpl" field=$ajaxint}}
{{include file="field_checkbox.tpl" field=$nowarn_insecure}}
{{include file="field_checkbox.tpl" field=$no_auto_update}}
{{include file="field_checkbox.tpl" field=$nosmile}}
{{include file="field_checkbox.tpl" field=$noinfo}}

View file

@ -64,8 +64,8 @@
<div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
{{if $item.vote}}
<div class="wall-item-like-buttons" id="wall-item-like-buttons-{{$item.id}}">
<a href="#" class="icon like" title="{{$item.vote.like.0|escape:'html'}}" onclick="dolike({{$item.id}},'like'); return false"></a>
{{if $item.vote.dislike}}<a href="#" class="icon dislike" title="{{$item.vote.dislike.0|escape:'html'}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>{{/if}}
<a href="#" class="icon like{{if $item.responses.like.self}} active{{/if}}" title="{{$item.vote.like.0|escape:'html'}}" onclick="dolike({{$item.id}},'like'); return false"></a>
{{if $item.vote.dislike}}<a href="#" class="icon dislike{{if $item.responses.dislike.self}} active{{/if}}" title="{{$item.vote.dislike.0|escape:'html'}}" onclick="dolike({{$item.id}},'dislike'); return false"></a>{{/if}}
{{if $item.vote.share}}<a href="#" class="icon recycle wall-item-share-buttons" title="{{$item.vote.share.0|escape:'html'}}" onclick="jotShare({{$item.id}}); return false"></a>{{/if}}
<img id="like-rotator-{{$item.id}}" class="like-rotator" src="images/rotator.gif" alt="{{$item.wait|escape:'html'}}" title="{{$item.wait|escape:'html'}}" style="display: none;" />
</div>
@ -88,9 +88,9 @@
{{/if}}
{{if $item.isevent }}
<div class="wall-item-attend-wrapper">
<a href="#" id="attendyes-{{$item.id}}" class="icon attendyes" onclick="dolike({{$item.id}},'attendyes'); return false;" title="{{$item.attend.0|escape:'html'}}"></a>
<a href="#" id="attendno-{{$item.id}}" class="icon attendno" onclick="dolike({{$item.id}},'attendno'); return false;" title="{{$item.attend.1|escape:'html'}}"></a>
<a href="#" id="attendmaybe-{{$item.id}}" class="icon attendmaybe" onclick="dolike({{$item.id}},'attendmaybe'); return false;" title="{{$item.attend.2|escape:'html'}}"></a>
<a href="#" id="attendyes-{{$item.id}}" class="icon attendyes{{if $item.responses.attendyes.self}} active{{/if}}" onclick="dolike({{$item.id}},'attendyes'); return false;" title="{{$item.attend.0|escape:'html'}}"></a>
<a href="#" id="attendno-{{$item.id}}" class="icon attendno{{if $item.responses.attendno.self}} active{{/if}}" onclick="dolike({{$item.id}},'attendno'); return false;" title="{{$item.attend.1|escape:'html'}}"></a>
<a href="#" id="attendmaybe-{{$item.id}}" class="icon attendmaybe{{if $item.responses.attendmaybe.self}} active{{/if}}" onclick="dolike({{$item.id}},'attendmaybe'); return false;" title="{{$item.attend.2|escape:'html'}}"></a>
</div>
{{/if}}
<div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-{{$item.id}}" >

View file

@ -1,127 +0,0 @@
@import url('../greenzero/style.css');
body {background-image:none;
}
.wall-item-content-wrapper {
border-top: 1px solid #ccc;
//border-top:none;
border-left:none;
border-right:none;
border-radius:0px;
//border:none;
//background: #f8f8f8 !important;
}
.wall-item-content-wrapper.comment {
// background: #f8f8f8 !important;
// border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
border-left:none;
border-right:none;
border-radius:0px;
}
.wall-item-tools {
// border-top: 1px solid #ccc;
// background: #f8f8f8 !important;
background: #ffffff !important;
}
.comment-edit-text-empty, .comment-edit-text-full {
border: 1px solid #ccc;
border-left: 1px solid #EEE;
background: #ffffff;
}
.comment-edit-wrapper, .comment-wwedit-wrapper {
// background: #ffffff; !important;
//background: #f8f8f8 !important;
}
section {
margin: 0px 10%;
margin-right:12%;
background-image:none;
}
aside {
margin-left: 10%;
background-image:none;
}
nav {
margin-left: 32px;
margin-right: 5%;
}
nav #site-location {
top: 80px;
right: 5%;
}
.wall-item-photo, .photo, .contact-block-img, .my-comment-photo {
border-radius: 3px;
-moz-border-radius: 3px;
}
.tabs { background-image:none;
}
.tab.active {
padding: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #CCCCCC;
//background: #F8F8F8;
font-weight: bold;
}
.tab { margin-right: 1px ;
}
#group-sidebar {
margin-bottom: 10px;
border:none;
}
#nets-sidebar {
margin-bottom: 10px;
border:none;
}
#saved-search-list {
border:none;
}
blockquote {
//background-color: #f8f8f8;
border: 1px solid #ccc;
-moz-border-radius: 3px;
border-radius: 3px;
}
.widget {
border: none;
}
.wall-item-content {
max-height: 20000px;
overflow: none;
}
.nav-commlink, .nav-login-link {
margin-top: 67px;
height: 15px;
float:left;
padding: 6px 3px;
}
nav .nav-link {
//float: left;
}

View file

@ -1,127 +0,0 @@
@import url('../purplezero/style.css');
body {background-image:none;
}
.wall-item-content-wrapper {
border-top: 1px solid #ccc;
//border-top:none;
border-left:none;
border-right:none;
border-radius:0px;
//border:none;
//background: #f8f8f8 !important;
}
.wall-item-content-wrapper.comment {
// background: #f8f8f8 !important;
// border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
border-left:none;
border-right:none;
border-radius:0px;
}
.wall-item-tools {
// border-top: 1px solid #ccc;
// background: #f8f8f8 !important;
background: #ffffff !important;
}
.comment-edit-text-empty, .comment-edit-text-full {
border: 1px solid #ccc;
border-left: 1px solid #EEE;
background: #ffffff;
}
.comment-edit-wrapper, .comment-wwedit-wrapper {
// background: #ffffff; !important;
// background: #f8f8f8 !important;
}
section {
margin: 0px 10%;
margin-right:12%;
background-image:none;
}
aside {
margin-left: 10%;
background-image:none;
}
nav {
margin-left: 32px;
margin-right: 5%;
}
nav #site-location {
top: 80px;
right: 5%;
}
.wall-item-photo, .photo, .contact-block-img, .my-comment-photo {
border-radius: 3px;
-moz-border-radius: 3px;
}
.tabs { background-image:none;
}
.tab.active {
padding: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #CCCCCC;
// background: #F8F8F8;
font-weight: bold;
}
.tab { margin-right: 1px ;
}
#group-sidebar {
margin-bottom: 10px;
border:none;
}
#nets-sidebar {
margin-bottom: 10px;
border:none;
}
#saved-search-list {
border:none;
}
blockquote {
background-color: #f8f8f8;
border: 1px solid #ccc;
-moz-border-radius: 3px;
border-radius: 3px;
}
.widget {
border: none;
}
.wall-item-content {
max-height: 20000px;
overflow: none;
}
.nav-commlink, .nav-login-link {
margin-top: 67px;
height: 15px;
float:left;
padding: 6px 3px;
}
nav .nav-link {
//float: left;
}

View file

@ -1,127 +0,0 @@
@import url('../duepuntozero/style.css');
body {background-image:none;
}
.wall-item-content-wrapper {
border-top: 1px solid #ccc;
//border-top:none;
border-left:none;
border-right:none;
border-radius:0px;
//border:none;
//background: #f8f8f8 !important;
}
.wall-item-content-wrapper.comment {
background: #f8f8f8 !important;
// border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
border-left:none;
border-right:none;
border-radius:0px;
}
.wall-item-tools {
// border-top: 1px solid #ccc;
// background: #f8f8f8 !important;
background: #ffffff !important;
}
.comment-edit-text-empty, .comment-edit-text-full {
border: 1px solid #ccc;
border-left: 1px solid #EEE;
background: #ffffff;
}
.comment-edit-wrapper, .comment-wwedit-wrapper {
// background: #ffffff; !important;
background: #f8f8f8 !important;
}
section {
margin: 0px 10%;
margin-right:12%;
background-image:none;
}
aside {
margin-left: 10%;
background-image:none;
}
nav {
margin-left: 32px;
margin-right: 5%;
}
nav #site-location {
top: 80px;
right: 5%;
}
.wall-item-photo, .photo, .contact-block-img, .my-comment-photo {
border-radius: 3px;
-moz-border-radius: 3px;
}
.tabs { background-image:none;
}
.tab.active {
padding: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #CCCCCC;
background: #F8F8F8;
font-weight: bold;
}
.tab { margin-right: 1px ;
}
#group-sidebar {
margin-bottom: 10px;
border:none;
}
#nets-sidebar {
margin-bottom: 10px;
border:none;
}
#saved-search-list {
border:none;
}
blockquote {
background-color: #f8f8f8;
border: 1px solid #ccc;
-moz-border-radius: 3px;
border-radius: 3px;
}
.widget {
border: none;
}
.wall-item-content {
max-height: 20000px;
overflow: none;
}
.nav-commlink, .nav-login-link {
margin-top: 67px;
height: 15px;
float:left;
padding: 6px 3px;
}
nav .nav-link {
//float: left;
}

View file

@ -1,89 +0,0 @@
<?php
/**
* Theme settings
*/
function theme_content(&$a){
if(!local_user())
return;
$resize = get_pconfig(local_user(), 'cleanzero', 'resize' );
$color = get_pconfig(local_user(), 'cleanzero', 'color' );
$font_size = get_pconfig(local_user(), 'cleanzero', 'font_size' );
$theme_width= get_pconfig(local_user(), 'cleanzero', 'theme_width' );
return cleanzero_form($a,$color,$font_size,$resize,$theme_width);
}
function theme_post(&$a){
if(! local_user())
return;
if (isset($_POST['cleanzero-settings-submit'])){
set_pconfig(local_user(), 'cleanzero', 'resize', $_POST['cleanzero_resize']);
set_pconfig(local_user(), 'cleanzero', 'color', $_POST['cleanzero_color']);
set_pconfig(local_user(), 'cleanzero', 'font_size', $_POST['cleanzero_font_size']);
set_pconfig(local_user(), 'cleanzero', 'theme_width', $_POST['cleanzero_theme_width']);
}
}
function theme_admin(&$a){
$resize = get_config('cleanzero', 'resize' );
$color = get_config('cleanzero', 'color' );
$font_size = get_config('cleanzero', 'font_size' );
$theme_width= get_config('cleanzero', 'theme_width' );
return cleanzero_form($a,$color,$font_size,$resize,$theme_width);
}
function theme_admin_post(&$a){
if (isset($_POST['cleanzero-settings-submit'])){
set_config('cleanzero', 'resize', $_POST['cleanzero_resize']);
set_config('cleanzero', 'color', $_POST['cleanzero_color']);
set_config('cleanzero', 'font_size', $_POST['cleanzero_font_size']);
set_config('cleanzero', 'theme_width', $_POST['cleanzero_theme_width']);
}
}
function cleanzero_form(&$a, $color,$font_size,$resize,$theme_width){
$colors = array(
"cleanzero"=>"cleanzero",
"cleanzero-green"=>"green",
"cleanzero-purple"=>"purple"
);
$font_sizes = array(
'12'=>'12',
"---"=>"---",
"16"=>"16",
"14"=>"14",
'10'=>'10',
);
$resizes = array(
"0"=>"0 (no resizing)",
"600"=>"1 (600px)",
"300"=>"2 (300px)",
"250"=>"3 (250px)",
"150"=>"4 (150px)",
);
$theme_widths =array (
"standard"=>"standard",
"narrow"=>"narrow",
"wide"=>"wide",
);
$t = get_markup_template("theme_settings.tpl" );
$o .= replace_macros($t, array(
'$submit' => t('Submit'),
'$baseurl' => $a->get_baseurl(),
'$title' => t("Theme settings"),
'$resize' => array('cleanzero_resize',t ('Set resize level for images in posts and comments (width and height)'),$resize,'',$resizes),
'$font_size' => array('cleanzero_font_size', t('Set font-size for posts and comments'), $font_size, '', $font_sizes),
'$theme_width' => array('cleanzero_theme_width', t('Set theme width'), $theme_width, '', $theme_widths),
'$color' => array('cleanzero_color', t('Color scheme'), $color, '', $colors),
));
return $o;
}

View file

@ -1,69 +0,0 @@
(function( $ ) {
$.fn.aeImageResize = function( params ) {
var aspectRatio = 0
// Nasty I know but it's done only once, so not too bad I guess
// Alternate suggestions welcome :)
, isIE6 = $.browser.msie && (6 == ~~ $.browser.version)
;
// We cannot do much unless we have one of these
if ( !params.height && !params.width ) {
return this;
}
// Calculate aspect ratio now, if possible
if ( params.height && params.width ) {
aspectRatio = params.width / params.height;
}
// Attach handler to load
// Handler is executed just once per element
// Load event required for Webkit browsers
return this.one( "load", function() {
// Remove all attributes and CSS rules
this.removeAttribute( "height" );
this.removeAttribute( "width" );
this.style.height = this.style.width = "";
var imgHeight = this.height
, imgWidth = this.width
, imgAspectRatio = imgWidth / imgHeight
, bxHeight = params.height
, bxWidth = params.width
, bxAspectRatio = aspectRatio;
// Work the magic!
// If one parameter is missing, we just force calculate it
if ( !bxAspectRatio ) {
if ( bxHeight ) {
bxAspectRatio = imgAspectRatio + 1;
} else {
bxAspectRatio = imgAspectRatio - 1;
}
}
// Only resize the images that need resizing
if ( (bxHeight && imgHeight > bxHeight) || (bxWidth && imgWidth > bxWidth) ) {
if ( imgAspectRatio > bxAspectRatio ) {
bxHeight = ~~ ( imgHeight / imgWidth * bxWidth );
} else {
bxWidth = ~~ ( imgWidth / imgHeight * bxHeight );
}
this.height = bxHeight;
this.width = bxWidth;
}
})
.each(function() {
// Trigger load event (for Gecko and MSIE)
if ( this.complete || isIE6 ) {
$( this ).trigger( "load" );
}
});
};
})( jQuery );

View file

@ -1 +0,0 @@
(function(d){d.fn.aeImageResize=function(a){var i=0,j=d.browser.msie&&6==~~d.browser.version;if(!a.height&&!a.width)return this;if(a.height&&a.width)i=a.width/a.height;return this.one("load",function(){this.removeAttribute("height");this.removeAttribute("width");this.style.height=this.style.width="";var e=this.height,f=this.width,g=f/e,b=a.height,c=a.width,h=i;h||(h=b?g+1:g-1);if(b&&e>b||c&&f>c){if(g>h)b=~~(e/f*c);else c=~~(f/e*b);this.height=b;this.width=c}}).each(function(){if(this.complete||j)d(this).trigger("load")})}})(jQuery);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

View file

@ -1,127 +0,0 @@
@import url('../duepuntozero/style.css');
body {background-image:none;
}
.wall-item-content-wrapper {
border-top: 1px solid #ccc;
//border-top:none;
border-left:none;
border-right:none;
border-radius:0px;
//border:none;
//background: #f8f8f8 !important;
}
.wall-item-content-wrapper.comment {
background: #f8f8f8 !important;
// border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
border-left:none;
border-right:none;
border-radius:0px;
}
.wall-item-tools {
// border-top: 1px solid #ccc;
// background: #f8f8f8 !important;
background: #ffffff !important;
}
.comment-edit-text-empty, .comment-edit-text-full {
border: 1px solid #ccc;
border-left: 1px solid #EEE;
background: #ffffff;
}
.comment-edit-wrapper, .comment-wwedit-wrapper {
// background: #ffffff; !important;
background: #f8f8f8 !important;
}
section {
margin: 0px 10%;
margin-right:12%;
background-image:none;
}
aside {
margin-left: 10%;
background-image:none;
}
nav {
margin-left: 32px;
margin-right: 5%;
}
nav #site-location {
top: 80px;
right: 5%;
}
.wall-item-photo, .photo, .contact-block-img, .my-comment-photo {
border-radius: 3px;
-moz-border-radius: 3px;
}
.tabs { background-image:none;
}
.tab.active {
padding: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
border: 1px solid #CCCCCC;
background: #F8F8F8;
font-weight: bold;
}
.tab { margin-right: 1px ;
}
#group-sidebar {
margin-bottom: 10px;
border:none;
}
#nets-sidebar {
margin-bottom: 10px;
border:none;
}
#saved-search-list {
border:none;
}
blockquote {
background-color: #f8f8f8;
border: 1px solid #ccc;
-moz-border-radius: 3px;
border-radius: 3px;
}
.widget {
border: none;
}
.wall-item-content {
max-height: 20000px;
overflow: none;
}
.nav-commlink, .nav-login-link {
margin-top: 67px;
height: 15px;
float:left;
padding: 6px 3px;
}
nav .nav-link {
//float: left;
}

View file

@ -1,140 +0,0 @@
<?php
$color=false;
$cleanzero_font_size=false;
$cleanzero_theme_width=false;
$site_color = get_config("cleanzero","color");
$site_cleanzero_font_size = get_config("cleanzero", "font_size" );
$site_cleanzero_theme_width = get_config("cleanzero", "theme_width");
if (local_user()) {
$color = get_pconfig(local_user(), "cleanzero","color");
$cleanzero_font_size = get_pconfig(local_user(), "cleanzero", "font_size");
$cleanzero_theme_width = get_pconfig(local_user(), "cleanzero", "theme_width");
}
if ($color===false) $color=$site_color;
if ($color===false) $color="cleanzero";
if ($cleanzero_font_size===false) $cleanzero_font_size=$site_cleanzero_font_size;
if ($cleanzero_theme_width===false) $cleanzero_theme_width=$site_cleanzero_theme_width;
if ($cleanzero_theme_width===false) $cleanzero_theme_width="standard";
if (file_exists("$THEMEPATH/$color/style.css")){
echo file_get_contents("$THEMEPATH/$color/style.css");
}
if($cleanzero_font_size == "16"){
echo "
.wall-item-content-wrapper {
font-size: 16px;
}
.wall-item-content-wrapper.comment {
font-size: 16px;
}
";
}
if($cleanzero_font_size == "14"){
echo "
.wall-item-content-wrapper {
font-size: 14px;
}
.wall-item-content-wrapper.comment {
font-size: 14px;
}
";
}
if($cleanzero_font_size == "12"){
echo "
.wall-item-content-wrapper {
font-size: 12px;
}
.wall-item-content-wrapper.comment {
font-size: 12px;
}
";
}
if($cleanzero_font_size == "10"){
echo "
.wall-item-content-wrapper {
font-size: 10px;
}
.wall-item-content-wrapper.comment {
font-size: 10px;
}
";
}
if ($cleanzero_theme_width === "standard") {
echo "
section {
margin: 0px 10%;
margin-right:10%;
}
aside {
margin-left: 10%;
}
nav {
margin-left: 10%;
margin-right: 10%;
}
nav #site-location {
right: 10%;
}
";
}
if ($cleanzero_theme_width === "narrow") {
echo "
section {
margin: 0px 15%;
margin-right:15%;
}
aside {
margin-left: 15%;
}
nav {
margin-left: 15%;
margin-right: 15%;
}
nav #site-location {
right: 15%;
}
";
}
if ($cleanzero_theme_width === "wide") {
echo "
section {
margin: 0px 5%;
margin-right:5%;
}
aside {
margin-left: 5%;
}
nav {
margin-left: 5%;
margin-right: 5%;
}
nav #site-location {
right: 5%;
}
";
}

View file

@ -1,86 +0,0 @@
<nav>
{{$langselector}}
<div id="site-location">{{$sitelocation}}</div>
<span id="nav-commlink-wrapper">
{{if $nav.register}}<a id="nav-register-link" class="nav-commlink {{$nav.register.2}} {{$sel.register}}" href="{{$nav.register.0}}" title="{{$nav.register.3}}" >{{$nav.register.1}}</a>{{/if}}
{{if $nav.network}}
<a id="nav-network-link" class="nav-commlink {{$nav.network.2}} {{$sel.network}}" href="{{$nav.network.0}}" title="{{$nav.network.3}}" >{{$nav.network.1}}</a>
<span id="net-update" class="nav-ajax-left"></span>
{{/if}}
{{if $nav.home}}
<a id="nav-home-link" class="nav-commlink {{$nav.home.2}} {{$sel.home}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" >{{$nav.home.1}}</a>
<span id="home-update" class="nav-ajax-left"></span>
{{/if}}
{{if $nav.community}}
<a id="nav-community-link" class="nav-commlink {{$nav.community.2}} {{$sel.community}}" href="{{$nav.community.0}}" title="{{$nav.community.3}}" >{{$nav.community.1}}</a>
{{/if}}
{{if $nav.introductions}}
<a id="nav-notify-link" class="nav-commlink {{$nav.introductions.2}} {{$sel.introductions}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a>
<span id="intro-update" class="nav-ajax-left"></span>
{{/if}}
{{if $nav.messages}}
<a id="nav-messages-link" class="nav-commlink {{$nav.messages.2}} {{$sel.messages}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" >{{$nav.messages.1}}</a>
<span id="mail-update" class="nav-ajax-left"></span>
{{/if}}
{{if $nav.notifications}}
<a id="nav-notifications-linkmenu" class="nav-commlink" href="{{$nav.notifications.0}}" rel="#nav-notifications-menu" title="{{$nav.notifications.1}}">{{$nav.notifications.1}}</a>
<span id="notify-update" class="nav-ajax-left"></span>
<ul id="nav-notifications-menu" class="menu-popup">
<li id="nav-notifications-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
<li id="nav-notifications-mark-all"><a href="#" onclick="notifyMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
<li class="empty">{{$emptynotifications}}</li>
</ul>
{{/if}}
</span>
<span id="banner">{{$banner}}</span>
<span id="nav-link-wrapper">
{{if $nav.logout}}<a id="nav-logout-link" class="nav-link {{$nav.logout.2}}" href="{{$nav.logout.0}}" title="{{$nav.logout.3}}" >{{$nav.logout.1}}</a> {{/if}}
{{if $nav.login}}<a id="nav-login-link" class="nav-login-link {{$nav.login.2}}" href="{{$nav.login.0}}" title="{{$nav.login.3}}" >{{$nav.login.1}}</a> {{/if}}
{{if $nav.help}} <a id="nav-help-link" class="nav-link {{$nav.help.2}}" target="friendica-help" href="{{$nav.help.0}}" title="{{$nav.help.3}}" >{{$nav.help.1}}</a>{{/if}}
{{if $nav.apps}}<a id="nav-apps-link" class="nav-link {{$nav.apps.2}}" href="{{$nav.apps.0}}" title="{{$nav.apps.3}}" >{{$nav.apps.1}}</a>{{/if}}
<a id="nav-search-link" class="nav-link {{$nav.search.2}}" href="{{$nav.search.0}}" title="{{$nav.search.3}}" >{{$nav.search.1}}</a>
<a id="nav-directory-link" class="nav-link {{$nav.directory.2}}" href="{{$nav.directory.0}}" title="{{$nav.directory.3}}" >{{$nav.directory.1}}</a>
{{if $nav.admin}}<a id="nav-admin-link" class="nav-link {{$nav.admin.2}}" href="{{$nav.admin.0}}" title="{{$nav.admin.3}}" >{{$nav.admin.1}}</a>{{/if}}
{{if $nav.settings}}<a id="nav-settings-link" class="nav-link {{$nav.settings.2}}" href="{{$nav.settings.0}}" title="{{$nav.settings.3}}">{{$nav.settings.1}}</a>{{/if}}
{{if $nav.profiles}}<a id="nav-profiles-link" class="nav-link {{$nav.profiles.2}}" href="{{$nav.profiles.0}}" title="{{$nav.profiles.3}}" >{{$nav.profiles.1}}</a>{{/if}}
{{if $nav.contacts}}<a id="nav-contacts-link" class="nav-link {{$nav.contacts.2}}" href="{{$nav.contacts.0}}" title="{{$nav.contacts.3}}" >{{$nav.contacts.1}}</a>{{/if}}
{{if $nav.manage}}<a id="nav-manage-link" class="nav-link {{$nav.manage.2}} {{$sel.manage}}" href="{{$nav.manage.0}}" title="{{$nav.manage.3}}">{{$nav.manage.1}}</a>{{/if}}
</span>
<span id="nav-end"></span>
</nav>
<ul id="nav-notifications-template" style="display:none;" rel="template">
<li class="{4}"><a href="{0}"><img data-src="{1}" height="24" width="24" alt="" />{2} <span class="notif-when">{3}</span></a></li>
</ul>
<script>
var pagetitle = null;
$("nav").bind('nav-update', function(e,data){
if (pagetitle==null) pagetitle = document.title;
var count = $(data).find('notif').attr('count');
if (count>0) {
document.title = "("+count+") "+pagetitle;
} else {
document.title = pagetitle;
}
});
</script>

View file

@ -1,11 +0,0 @@
{{include file="field_select.tpl" field=$color}}
{{include file="field_select.tpl" field=$font_size}}
{{include file="field_select.tpl" field=$resize}}
{{include file="field_select.tpl" field=$theme_width}}
<div class="settings-submit-wrapper">
<input type="submit" value="{{$submit}}" class="settings-submit" name="cleanzero-settings-submit" />
</div>

View file

@ -1,126 +0,0 @@
<?php
/*
* Name: cleanzero
* Description: Theme with clean design derived from the zero theme family. Including options to set color schemes, font sizes and resizing of images in posts
* Version:
* Author: Christian Vogeley (https://christian-vogeley.de/profile/christian)
*/
function cleanzero_init(&$a) {
$a->theme_info = array(
'extends' => 'duepuntozero',
);
set_template_engine($a, 'smarty3');
$a->page['htmlhead'] .= <<< EOT
<script>
function insertFormatting(comment,BBcode,id) {
var tmpStr = $("#comment-edit-text-" + id).val();
if(tmpStr == comment) {
tmpStr = "";
$("#comment-edit-text-" + id).addClass("comment-edit-text-full");
$("#comment-edit-text-" + id).removeClass("comment-edit-text-empty");
openMenu("comment-edit-submit-wrapper-" + id);
$("#comment-edit-text-" + id).val(tmpStr);
}
textarea = document.getElementById("comment-edit-text-" +id);
if (document.selection) {
textarea.focus();
selected = document.selection.createRange();
if (BBcode == "url"){
selected.text = "["+BBcode+"]" + "http://" + selected.text + "[/"+BBcode+"]";
} else
selected.text = "["+BBcode+"]" + selected.text + "[/"+BBcode+"]";
} else if (textarea.selectionStart || textarea.selectionStart == "0") {
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
if (BBcode == "url"){
textarea.value = textarea.value.substring(0, start) + "["+BBcode+"]" + "http://" + textarea.value.substring(start, end) + "[/"+BBcode+"]" + textarea.value.substring(end, textarea.value.length);
} else
textarea.value = textarea.value.substring(0, start) + "["+BBcode+"]" + textarea.value.substring(start, end) + "[/"+BBcode+"]" + textarea.value.substring(end, textarea.value.length);
}
return true;
}
function cmtBbOpen(comment, id) {
if($(comment).hasClass('comment-edit-text-full')) {
$(".comment-edit-bb-" + id).show();
return true;
}
return false;
}
function cmtBbClose(comment, id) {
// if($(comment).hasClass('comment-edit-text-empty')) {
// $(".comment-edit-bb-" + id).hide();
// return true;
// }
return false;
}
$(document).ready(function() {
$('.group-edit-icon').hover(
function() {
$(this).addClass('icon'); $(this).removeClass('iconspacer');},
function() {
$(this).removeClass('icon'); $(this).addClass('iconspacer');}
);
$('.sidebar-group-element').hover(
function() {
id = $(this).attr('id');
$('#edit-' + id).addClass('icon'); $('#edit-' + id).removeClass('iconspacer');},
function() {
id = $(this).attr('id');
$('#edit-' + id).removeClass('icon');$('#edit-' + id).addClass('iconspacer');}
);
$('.savedsearchdrop').hover(
function() {
$(this).addClass('drop'); $(this).addClass('icon'); $(this).removeClass('iconspacer');},
function() {
$(this).removeClass('drop'); $(this).removeClass('icon'); $(this).addClass('iconspacer');}
);
$('.savedsearchterm').hover(
function() {
id = $(this).attr('id');
$('#drop-' + id).addClass('icon'); $('#drop-' + id).addClass('drophide'); $('#drop-' + id).removeClass('iconspacer');},
function() {
id = $(this).attr('id');
$('#drop-' + id).removeClass('icon');$('#drop-' + id).removeClass('drophide'); $('#drop-' + id).addClass('iconspacer');}
);
});
</script>
EOT;
// get resize configuration
$resize=false;
$site_resize = get_config('cleanzero', 'resize' );
if(local_user()) $resize = get_pconfig(local_user(), 'cleanzero', 'resize' );
if ($resize===false) $resize=$site_resize;
if ($resize===false) $resize=0;
if (intval($resize) > 0) {
//load jquery.ae.image.resize.js
$imageresizeJS = $a->get_baseurl($ssl_state)."/view/theme/cleanzero/js/jquery.ae.image.resize.js";
$a->page['htmlhead'] .= sprintf('<script language="JavaScript" src="%s" ></script>', $imageresizeJS);
$a->page['htmlhead'] .= '
<script>
$(function() {
$(".wall-item-content img").aeImageResize({height: '.$resize.', width: '.$resize.'});
});
</script>';}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

View file

@ -1,105 +0,0 @@
@import url('../duepuntozero/style.css');
.wall-item-content-wrapper {
border: none;
}
.wall-item-content-wrapper.comment {
background: #ffffff !important;
border-left: 1px solid #EEE;
}
.wall-item-tools {
background: none;
}
.comment-edit-text-empty, .comment-edit-text-full {
border: none;
border-left: 1px solid #EEE;
background: #EEEEEE;
}
.comment-edit-wrapper, .comment-wwedit-wrapper {
background: #ffffff !important;
}
section {
margin: 0px 32px;
}
aside {
margin-left: 32px;
}
nav {
margin-left: 32px;
margin-right: 32px;
}
nav #site-location {
top: 80px;
right: 36px;
}
.wall-item-photo, .photo, .contact-block-img, .my-comment-photo {
border-radius: 3px;
-moz-border-radius: 3px;
margin-top: 15px;
}
.wall-item-photo.comment {
margin-top: 26px;
}
.triangle-isosceles {
position:relative;
padding:15px;
margin:1em 0 3em;
color:#000;
background:#EEEEEE; /* default background for browsers without gradient support */
/* css3 */
background:-webkit-gradient(linear, 0 0, 0 100%, from(#EEEEEE), to(#ffffff));
background:-moz-linear-gradient(#EEEEEE, #ffffff);
background:-o-linear-gradient(#EEEEEE, #ffffff);
background:linear-gradient(#EEEEEE, #ffffff);
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
}
/* Variant : for left/right positioned triangle
------------------------------------------ */
.triangle-isosceles.left {
margin-left:30px;
background:#F8F8F8;
border: 2px solid #CCCCCC;
}
/* THE TRIANGLE
------------------------------------------------------------------------------------------------------------------------------- */
/* creates triangle */
.triangle-isosceles:after {
content:"";
position:absolute;
bottom:-8px; /* value = - border-top-width - border-bottom-width */
left:30px; /* controls horizontal position */
border-width:15px 15px 0; /* vary these values to change the angle of the vertex */
border-style:solid;
border-color:#f8f8f8 transparent;
/* reduce the damage in FF3.0 */
display:block;
width:0;
}
/* Variant : left
------------------------------------------ */
.triangle-isosceles.left:after {
top:12px; /* controls vertical position */
left:-30px; /* value = - border-left-width - border-right-width */
bottom:auto;
border-width:10px 30px 10px 0;
border-color:transparent #f8f8f8;
}

View file

@ -1,34 +0,0 @@
<div class="comment-wwedit-wrapper" id="comment-edit-wrapper-{{$id}}" style="display: block;">
<form class="comment-edit-form" id="comment-edit-form-{{$id}}" action="item" method="post" onsubmit="post_comment({{$id}}); return false;">
<input type="hidden" name="type" value="{{$type}}" />
<input type="hidden" name="profile_uid" value="{{$profile_uid}}" />
<input type="hidden" name="parent" value="{{$parent}}" />
{{*<!--<input type="hidden" name="return" value="{{$return_path}}" />-->*}}
<input type="hidden" name="jsreload" value="{{$jsreload}}" />
<input type="hidden" name="preview" id="comment-preview-inp-{{$id}}" value="0" />
<input type="hidden" name="post_id_random" value="{{$rand_num}}" />
<div class="comment-edit-photo" id="comment-edit-photo-{{$id}}" >
<a class="comment-edit-photo-link" href="{{$mylink}}" title="{{$mytitle}}"><img class="my-comment-photo" src="{{$myphoto}}" alt="{{$mytitle}}" title="{{$mytitle}}" /></a>
</div>
<div class="comment-edit-photo-end"></div>
<textarea id="comment-edit-text-{{$id}}" class="comment-edit-text-empty triangle-isosceles left" style="display: block;" name="body" onFocus="commentOpen(this,{{$id}});" onBlur="commentClose(this,{{$id}});" >{{$comment}}</textarea>
{{if $qcomment}}
{{foreach $qcomment as $qc}}
<span class="fakelink qcomment" onclick="commentInsert(this,{{$id}}); return false;" >{{$qc}}</span>
&nbsp;
{{/foreach}}
{{/if}}
<div class="comment-edit-text-end"></div>
<div class="comment-edit-submit-wrapper" id="comment-edit-submit-wrapper-{{$id}}" style="display: none;" >
<input type="submit" onclick="post_comment({{$id}}); return false;" id="comment-edit-submit-{{$id}}" class="comment-edit-submit" name="submit" value="{{$submit}}" />
<span onclick="preview_comment({{$id}});" id="comment-edit-preview-link-{{$id}}" class="fakelink">{{$preview}}</span>
<div id="comment-edit-preview-{{$id}}" class="comment-edit-preview" style="display:none;"></div>
</div>
<div class="comment-edit-end"></div>
</form>
</div>

View file

@ -1,55 +0,0 @@
<div class="wall-item-outside-wrapper {{$item.indent}}{{$item.previewing}}" id="wall-item-outside-wrapper-{{$item.id}}" >
<div class="wall-item-content-wrapper {{$item.indent}}" id="wall-item-content-wrapper-{{$item.id}}" >
<div class="wall-item-info" id="wall-item-info-{{$item.id}}">
<div class="wall-item-photo-wrapper" id="wall-item-photo-wrapper-{{$item.id}}"
onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">
<a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-photo-link" id="wall-item-photo-link-{{$item.id}}">
<img src="{{$item.thumb}}" class="wall-item-photo{{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" style="height: 80px; width: 80px;" alt="{{$item.name}}" /></a>
<span onclick="openClose('wall-item-photo-menu-{{$item.id}}');" class="fakelink wall-item-photo-menu-button" id="wall-item-photo-menu-button-{{$item.id}}">menu</span>
<div class="wall-item-photo-menu" id="wall-item-photo-menu-{{$item.id}}">
<ul>
{{$item.item_photo_menu}}
</ul>
</div>
</div>
<div class="wall-item-photo-end"></div>
<div class="wall-item-wrapper" id="wall-item-wrapper-{{$item.id}}" >
{{if $item.lock}}<div class="wall-item-lock"><img src="images/lock_icon.gif" class="lockview" alt="{{$item.lock}}" onclick="lockview(event,{{$item.id}});" /></div>
{{else}}<div class="wall-item-lock"></div>{{/if}}
<div class="wall-item-location" id="wall-item-location-{{$item.id}}">{{$item.location}}</div>
</div>
</div>
<div class="wall-item-author">
<a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.sparkle}}" id="wall-item-name-{{$item.id}}" >{{$item.name}}</span></a>
<div class="wall-item-ago" id="wall-item-ago-{{$item.id}}">{{$item.ago}}</div>
</div>
<div class="wall-item-content" id="wall-item-content-{{$item.id}}" >
<div class="wall-item-title" id="wall-item-title-{{$item.id}}">{{$item.title}}</div>
<div class="wall-item-title-end"></div>
<div class="wall-item-body triangle-isosceles left" id="wall-item-body-{{$item.id}}" >{{$item.body}}</div>
</div>
<div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
<div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-{{$item.id}}" >
{{if $item.drop.dropping}}<a href="item/drop/{{$item.id}}" onclick="return confirmDelete();" class="icon drophide" title="{{$item.drop.delete}}" onmouseover="imgbright(this);" onmouseout="imgdull(this);" ></a>{{/if}}
</div>
{{if $item.drop.pagedrop}}<input type="checkbox" onclick="checkboxhighlight(this);" title="{{$item.drop.select}}" class="item-select" name="itemselected[]" value="{{$item.id}}" />{{/if}}
<div class="wall-item-delete-end"></div>
</div>
</div>
<div class="wall-item-wrapper-end"></div>
<div class="wall-item-conv" id="wall-item-conv-{{$item.id}}" >
{{if $item.conv}}
<a href='{{$item.conv.href}}' id='context-{{$item.id}}' title='{{$item.conv.title}}'>{{$item.conv.title}}</a>
{{/if}}
</div>
<div class="wall-item-outside-wrapper-end {{$item.indent}}" ></div>
</div>

View file

@ -1,64 +0,0 @@
<?php
/*
* Name: Comix-Plain
* Description: Comix theme with a standard font
* Version: 1.0
* Author: Mike Macgirvin <mike@macgirvin.com>
*/
function comix_plain_init(&$a) {
$a->theme_info = array(
'extends' => 'duepuntozero',
);
set_template_engine($a, 'smarty3');
$a->page['htmlhead'] .= <<< EOT
<script>
$(document).ready(function() {
$('html').click(function() { $("#nav-notifications-menu" ).hide(); });
$('.group-edit-icon').hover(
function() {
$(this).addClass('icon'); $(this).removeClass('iconspacer');},
function() {
$(this).removeClass('icon'); $(this).addClass('iconspacer');}
);
$('.sidebar-group-element').hover(
function() {
id = $(this).attr('id');
$('#edit-' + id).addClass('icon'); $('#edit-' + id).removeClass('iconspacer');},
function() {
id = $(this).attr('id');
$('#edit-' + id).removeClass('icon');$('#edit-' + id).addClass('iconspacer');}
);
$('.savedsearchdrop').hover(
function() {
$(this).addClass('drop'); $(this).addClass('icon'); $(this).removeClass('iconspacer');},
function() {
$(this).removeClass('drop'); $(this).removeClass('icon'); $(this).addClass('iconspacer');}
);
$('.savedsearchterm').hover(
function() {
id = $(this).attr('id');
$('#drop-' + id).addClass('icon'); $('#drop-' + id).addClass('drophide'); $('#drop-' + id).removeClass('iconspacer');},
function() {
id = $(this).attr('id');
$('#drop-' + id).removeClass('icon');$('#drop-' + id).removeClass('drophide'); $('#drop-' + id).addClass('iconspacer');}
);
});
</script>
EOT;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

View file

@ -1,109 +0,0 @@
@import url('../duepuntozero/style.css');
body {
font-family: "Comic Sans MS", sans !important;
font-size: 13px;
}
.wall-item-content-wrapper {
border: none;
}
.wall-item-content-wrapper.comment {
background: #ffffff !important;
border-left: 1px solid #EEE;
}
.wall-item-tools {
background: none;
}
.comment-edit-text-empty, .comment-edit-text-full {
border: none;
border-left: 1px solid #EEE;
background: #EEEEEE;
}
.comment-edit-wrapper, .comment-wwedit-wrapper {
background: #ffffff !important;
}
section {
margin: 0px 32px;
}
aside {
margin-left: 32px;
}
nav {
margin-left: 32px;
margin-right: 32px;
}
nav #site-location {
top: 80px;
right: 36px;
}
.wall-item-photo, .photo, .contact-block-img, .my-comment-photo {
border-radius: 3px;
-moz-border-radius: 3px;
margin-top: 15px;
}
.wall-item-photo.comment {
margin-top: 26px;
}
.triangle-isosceles {
position:relative;
padding:15px;
margin:1em 0 3em;
color:#000;
background:#EEEEEE; /* default background for browsers without gradient support */
/* css3 */
background:-webkit-gradient(linear, 0 0, 0 100%, from(#EEEEEE), to(#ffffff));
background:-moz-linear-gradient(#EEEEEE, #ffffff);
background:-o-linear-gradient(#EEEEEE, #ffffff);
background:linear-gradient(#EEEEEE, #ffffff);
-webkit-border-radius:10px;
-moz-border-radius:10px;
border-radius:10px;
}
/* Variant : for left/right positioned triangle
------------------------------------------ */
.triangle-isosceles.left {
margin-left:30px;
background:#F8F8F8;
border: 2px solid #CCCCCC;
}
/* THE TRIANGLE
------------------------------------------------------------------------------------------------------------------------------- */
/* creates triangle */
.triangle-isosceles:after {
content:"";
position:absolute;
bottom:-8px; /* value = - border-top-width - border-bottom-width */
left:30px; /* controls horizontal position */
border-width:15px 15px 0; /* vary these values to change the angle of the vertex */
border-style:solid;
border-color:#f8f8f8 transparent;
/* reduce the damage in FF3.0 */
display:block;
width:0;
}
/* Variant : left
------------------------------------------ */
.triangle-isosceles.left:after {
top:12px; /* controls vertical position */
left:-30px; /* value = - border-left-width - border-right-width */
bottom:auto;
border-width:10px 30px 10px 0;
border-color:transparent #f8f8f8;
}

View file

@ -1,34 +0,0 @@
<div class="comment-wwedit-wrapper" id="comment-edit-wrapper-{{$id}}" style="display: block;">
<form class="comment-edit-form" id="comment-edit-form-{{$id}}" action="item" method="post" onsubmit="post_comment({{$id}}); return false;">
<input type="hidden" name="type" value="{{$type}}" />
<input type="hidden" name="profile_uid" value="{{$profile_uid}}" />
<input type="hidden" name="parent" value="{{$parent}}" />
{{*<!--<input type="hidden" name="return" value="{{$return_path}}" />-->*}}
<input type="hidden" name="jsreload" value="{{$jsreload}}" />
<input type="hidden" name="preview" id="comment-preview-inp-{{$id}}" value="0" />
<input type="hidden" name="post_id_random" value="{{$rand_num}}" />
<div class="comment-edit-photo" id="comment-edit-photo-{{$id}}" >
<a class="comment-edit-photo-link" href="{{$mylink}}" title="{{$mytitle}}"><img class="my-comment-photo" src="{{$myphoto}}" alt="{{$mytitle}}" title="{{$mytitle}}" /></a>
</div>
<div class="comment-edit-photo-end"></div>
<textarea id="comment-edit-text-{{$id}}" class="comment-edit-text-empty triangle-isosceles left" style="display: block;" name="body" onFocus="commentOpen(this,{{$id}});" onBlur="commentClose(this,{{$id}});" >{{$comment}}</textarea>
{{if $qcomment}}
{{foreach $qcomment as $qc}}
<span class="fakelink qcomment" onclick="commentInsert(this,{{$id}}); return false;" >{{$qc}}</span>
&nbsp;
{{/foreach}}
{{/if}}
<div class="comment-edit-text-end"></div>
<div class="comment-edit-submit-wrapper" id="comment-edit-submit-wrapper-{{$id}}" style="display: none;" >
<input type="submit" onclick="post_comment({{$id}}); return false;" id="comment-edit-submit-{{$id}}" class="comment-edit-submit" name="submit" value="{{$submit}}" />
<span onclick="preview_comment({{$id}});" id="comment-edit-preview-link-{{$id}}" class="fakelink">{{$preview}}</span>
<div id="comment-edit-preview-{{$id}}" class="comment-edit-preview" style="display:none;"></div>
</div>
<div class="comment-edit-end"></div>
</form>
</div>

View file

@ -1,55 +0,0 @@
<div class="wall-item-outside-wrapper {{$item.indent}} {{$item.shiny}}{{$item.previewing}}" id="wall-item-outside-wrapper-{{$item.id}}" >
<div class="wall-item-content-wrapper {{$item.indent}} {{$item.shiny}}" id="wall-item-content-wrapper-{{$item.id}}" >
<div class="wall-item-info" id="wall-item-info-{{$item.id}}">
<div class="wall-item-photo-wrapper" id="wall-item-photo-wrapper-{{$item.id}}"
onmouseover="if (typeof t{{$item.id}} != 'undefined') clearTimeout(t{{$item.id}}); openMenu('wall-item-photo-menu-button-{{$item.id}}')"
onmouseout="t{{$item.id}}=setTimeout('closeMenu(\'wall-item-photo-menu-button-{{$item.id}}\'); closeMenu(\'wall-item-photo-menu-{{$item.id}}\');',200)">
<a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-photo-link" id="wall-item-photo-link-{{$item.id}}">
<img src="{{$item.thumb}}" class="wall-item-photo{{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" style="height: 80px; width: 80px;" alt="{{$item.name}}" /></a>
<span onclick="openClose('wall-item-photo-menu-{{$item.id}}');" class="fakelink wall-item-photo-menu-button" id="wall-item-photo-menu-button-{{$item.id}}">menu</span>
<div class="wall-item-photo-menu" id="wall-item-photo-menu-{{$item.id}}">
<ul>
{{$item.item_photo_menu}}
</ul>
</div>
</div>
<div class="wall-item-photo-end"></div>
<div class="wall-item-wrapper" id="wall-item-wrapper-{{$item.id}}" >
{{if $item.lock}}<div class="wall-item-lock"><img src="images/lock_icon.gif" class="lockview" alt="{{$item.lock}}" onclick="lockview(event,{{$item.id}});" /></div>
{{else}}<div class="wall-item-lock"></div>{{/if}}
<div class="wall-item-location" id="wall-item-location-{{$item.id}}">{{$item.location}}</div>
</div>
</div>
<div class="wall-item-author">
<a href="{{$item.profile_url}}" target="redir" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.sparkle}}" id="wall-item-name-{{$item.id}}" >{{$item.name}}</span></a>
<div class="wall-item-ago" id="wall-item-ago-{{$item.id}}">{{$item.ago}}</div>
</div>
<div class="wall-item-content" id="wall-item-content-{{$item.id}}" >
<div class="wall-item-title" id="wall-item-title-{{$item.id}}">{{$item.title}}</div>
<div class="wall-item-title-end"></div>
<div class="wall-item-body triangle-isosceles left" id="wall-item-body-{{$item.id}}" >{{$item.body}}</div>
</div>
<div class="wall-item-tools" id="wall-item-tools-{{$item.id}}">
<div class="wall-item-delete-wrapper" id="wall-item-delete-wrapper-{{$item.id}}" >
{{if $item.drop.dropping}}<a href="item/drop/{{$item.id}}" onclick="return confirmDelete();" class="icon drophide" title="{{$item.drop.delete}}" onmouseover="imgbright(this);" onmouseout="imgdull(this);" ></a>{{/if}}
</div>
{{if $item.drop.pagedrop}}<input type="checkbox" onclick="checkboxhighlight(this);" title="{{$item.drop.select}}" class="item-select" name="itemselected[]" value="{{$item.id}}" />{{/if}}
<div class="wall-item-delete-end"></div>
</div>
</div>
<div class="wall-item-wrapper-end"></div>
<div class="wall-item-conv" id="wall-item-conv-{{$item.id}}" >
{{if $item.conv}}
<a href='{{$item.conv.href}}' id='context-{{$item.id}}' title='{{$item.conv.title}}'>{{$item.conv.title}}</a>
{{/if}}
</div>
<div class="wall-item-outside-wrapper-end {{$item.indent}} {{$item.shiny}}" ></div>
</div>

View file

@ -1,64 +0,0 @@
<?php
/*
* Name: Comix
* Description: An irreverent theme
* Version: 1.0
* Author: Mike Macgirvin <mike@macgirvin.com>
*/
function comix_init(&$a) {
$a->theme_info = array(
'extends' => 'duepuntozero',
);
set_template_engine($a, 'smarty3');
$a->page['htmlhead'] .= <<< EOT
<script>
$(document).ready(function() {
$('html').click(function() { $("#nav-notifications-menu" ).hide(); });
$('.group-edit-icon').hover(
function() {
$(this).addClass('icon'); $(this).removeClass('iconspacer');},
function() {
$(this).removeClass('icon'); $(this).addClass('iconspacer');}
);
$('.sidebar-group-element').hover(
function() {
id = $(this).attr('id');
$('#edit-' + id).addClass('icon'); $('#edit-' + id).removeClass('iconspacer');},
function() {
id = $(this).attr('id');
$('#edit-' + id).removeClass('icon');$('#edit-' + id).addClass('iconspacer');}
);
$('.savedsearchdrop').hover(
function() {
$(this).addClass('drop'); $(this).addClass('icon'); $(this).removeClass('iconspacer');},
function() {
$(this).removeClass('drop'); $(this).removeClass('icon'); $(this).addClass('iconspacer');}
);
$('.savedsearchterm').hover(
function() {
id = $(this).attr('id');
$('#drop-' + id).addClass('icon'); $('#drop-' + id).addClass('drophide'); $('#drop-' + id).removeClass('iconspacer');},
function() {
id = $(this).attr('id');
$('#drop-' + id).removeClass('icon');$('#drop-' + id).removeClass('drophide'); $('#drop-' + id).addClass('iconspacer');}
);
});
</script>
EOT;
}

Some files were not shown because too many files have changed in this diff Show more