Merge branch '3.4.2'

This commit is contained in:
Fabrixxm 2015-09-29 09:58:16 +02:00
commit 4b6afbf681
195 changed files with 51776 additions and 46358 deletions

View file

@ -1,3 +1,48 @@
Version 3.4.2
Updates to the documentation (tobias, silke, annando)
Updates to the translations (tobiasd & translation teams)
Updates to themes frost-mobile, vier, duepuntozero, quattro (annando, tobiasd)
Enancements of the communications via OStatus and Diaspora protocols (annando)
Option to automatically follow OStatus contacts was moved from addon to the core (annando)
Add tool to import OStatus contacts from an old account (annando)
SALMON slaps with OStatus were reworked (annando)
Fix for saving searches (rabuzarus)
Fix separation of list items in contact editor (issue #1747) (tobiasd)
When a picture is uploaded, "don't send a note about this new picture" is now the default behaviour (tobiasd)
Show profile url in contact-edit overview listing (issue #1745) (tobiasd)
The vagrant VM usage was changed so that the "installation" is now done automatically on the first run. Example users are automatically put into the database (silke)
Buttons to insert images or attachment to a post use a popup browser to select a previously uploaded item or upload a new one (fabrixxm, rabuzarus)
Improvements in contact handling (annando)
Friendica node can now query other nodes about their users and the contact lists (annando)
Contact recommendation is done only for recently active users (annando)
Admins can opt for search the local DB for contacts instead of the global directory (annando)
The global directory is queried in the background to update local DB and improve similar searches in the future. (annando)
By communication over the Diaspora protocol, red#matrix sources are now correctly identified, hubzilla is detected (annando)
Adopt limitation of usage of "-" in username to avoid conflicts with GNU Social and Diaspora (annando)
The [url] tag now also suppots ftp, mailto, gopher links (annando)
An "inspect queue" module was added to the admin panel (tobiasd)
Fix some missing SQL data escapes (fabrixxm)
Improved the accessibility of the web UI for better screen reader compatibility (annando)
Added access keys (annando)
Support for the public relay server of Diaspora (annando)
Support for the new nodeinfo protocol (successor of current statistics.json), addon deprecated as functionality has been moved into the core (annando)
Fix issue with moved Friendica profiles and Diaspora communication (issue #1491) (annando)
Show more information on contact request page (issue #1739) (annando)
Support for newer versions of the Twidere client was enhanced (annando)
Support for inline [code] tag usage (fabrixxm)
Fix login form in aside (issue #1348) (annando)
Show both url-style and webfinger-style identity address in profile (issue #1621) (tobiasd)
Add button to reload all active plugins in admin plugins page to ensure new hooks are used (fabrixxm)
Make the hardcoded path to global directory configurable (annando)
Change default directory to dir.friendi.ca (annando)
Improve cache system with granular expire time (annando)
Remove oohembed code (issue #1855) (annando)
Checks for mcrypt availability before enable or use RINO2 (fabrixm)
Fix following email contacts (issue #1896) (annando)
Parse BBCode in contact request notification email (annando)
Version 3.4.1
Implement server-to-server encryption (RINO) using php-encryption library as "RINO 2", deprecate "RINO 1" (issue #1655) (fabrixxm)

View file

@ -64,6 +64,8 @@ you wish to communicate with the Diaspora network.
3. Create an empty database and note the access details (hostname, username,
password, database name).
- Friendica needs the permission to create and delete fields and tables in its own database.
4. If you know in advance that it will be impossible for the web server to
write or create files in your web directory, create an empty file called

View file

@ -17,9 +17,9 @@ require_once('include/dbstructure.php');
define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Lily of the valley');
define ( 'FRIENDICA_VERSION', '3.4.1' );
define ( 'FRIENDICA_VERSION', '3.4.2' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1185 );
define ( 'DB_UPDATE_VERSION', 1188 );
define ( 'EOL', "<br />\r\n" );
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
@ -84,6 +84,15 @@ define ( 'LOGGER_DEBUG', 2 );
define ( 'LOGGER_DATA', 3 );
define ( 'LOGGER_ALL', 4 );
/**
* cache levels
*/
define ( 'CACHE_MONTH', 0 );
define ( 'CACHE_WEEK', 1 );
define ( 'CACHE_DAY', 2 );
define ( 'CACHE_HOUR', 3 );
/**
* registration policies
*/
@ -274,6 +283,7 @@ define ( 'ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post' );
define ( 'ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update' );
define ( 'ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag' );
define ( 'ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite' );
define ( 'ACTIVITY_SHARE', NAMESPACE_ACTIVITY_SCHEMA . 'share' );
define ( 'ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke' );
define ( 'ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood' );
@ -1618,9 +1628,9 @@ if(! function_exists('load_contact_links')) {
$url = normalise_link($rr['url']);
$ret[$url] = $rr;
}
}
else
} else
$ret['empty'] = true;
$a->contacts = $ret;
return;
}
@ -1658,8 +1668,7 @@ function explode_querystring($query) {
if($arg_st !== false) {
$base = substr($query, 0, $arg_st);
$arg_st += 1;
}
else {
} else {
$base = '';
$arg_st = 0;
}
@ -1708,6 +1717,15 @@ function random_digits($digits) {
return $rn;
}
function get_server() {
$server = get_config("system", "directory");
if ($server == "")
$server = "http://dir.friendi.ca";
return($server);
}
function get_cachefile($file, $writemode = true) {
$cache = get_itemcachepath();
@ -1793,7 +1811,11 @@ function get_lockpath() {
if ($temppath != "") {
$lockpath = $temppath."/lock";
if (!is_dir($lockpath))
mkdir($lockpath);
elseif (!is_writable($lockpath))
$lockpath = $temppath;
if (is_dir($lockpath) AND is_writable($lockpath)) {
set_config("system", "lockpath", $lockpath);
@ -1804,15 +1826,23 @@ function get_lockpath() {
}
function get_temppath() {
$a = get_app();
$temppath = get_config("system","temppath");
if (($temppath != "") AND is_dir($temppath) AND is_writable($temppath))
return($temppath);
$temppath = sys_get_temp_dir();
if (($temppath != "") AND is_dir($temppath) AND is_writable($temppath)) {
$temppath .= "/".$a->get_hostname();
if (!is_dir($temppath))
mkdir($temppath);
if (is_dir($temppath) AND is_writable($temppath)) {
set_config("system", "temppath", $temppath);
return($temppath);
}
}
return("");
}

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 3.4.0 (Lily of the valley)
-- DB_UPDATE_VERSION 1185
-- Friendica 3.4.1 (Lily of the valley)
-- DB_UPDATE_VERSION 1188
-- ------------------------------------------
@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS `auth_codes` (
CREATE TABLE IF NOT EXISTS `cache` (
`k` varchar(255) NOT NULL PRIMARY KEY,
`v` text NOT NULL,
`expire_mode` int(11) NOT NULL DEFAULT 0,
`updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
INDEX `updated` (`updated`)
) DEFAULT CHARSET=utf8;
@ -136,6 +137,7 @@ CREATE TABLE IF NOT EXISTS `contact` (
`hub-verify` varchar(255) NOT NULL DEFAULT '',
`last-update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`success_update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`failure_update` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`name-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`uri-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`avatar-date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
@ -300,18 +302,25 @@ CREATE TABLE IF NOT EXISTS `gcign` (
CREATE TABLE IF NOT EXISTS `gcontact` (
`id` int(10) unsigned NOT NULL auto_increment PRIMARY KEY,
`name` varchar(255) NOT NULL DEFAULT '',
`nick` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`nurl` varchar(255) NOT NULL DEFAULT '',
`photo` varchar(255) NOT NULL DEFAULT '',
`connect` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` datetime DEFAULT '0000-00-00 00:00:00',
`last_contact` datetime DEFAULT '0000-00-00 00:00:00',
`last_failure` datetime DEFAULT '0000-00-00 00:00:00',
`location` varchar(255) NOT NULL DEFAULT '',
`about` text NOT NULL,
`keywords` text NOT NULL,
`gender` varchar(32) NOT NULL DEFAULT '',
`community` tinyint(1) NOT NULL DEFAULT 0,
`network` varchar(255) NOT NULL DEFAULT '',
`generation` tinyint(3) NOT NULL DEFAULT 0,
INDEX `nurl` (`nurl`)
`server_url` varchar(255) NOT NULL DEFAULT '',
INDEX `nurl` (`nurl`),
INDEX `updated` (`updated`)
) DEFAULT CHARSET=utf8;
--
@ -352,6 +361,28 @@ CREATE TABLE IF NOT EXISTS `group_member` (
INDEX `uid_gid_contactid` (`uid`,`gid`,`contact-id`)
) DEFAULT CHARSET=utf8;
--
-- TABLE gserver
--
CREATE TABLE IF NOT EXISTS `gserver` (
`id` int(10) unsigned NOT NULL auto_increment PRIMARY KEY,
`url` varchar(255) NOT NULL DEFAULT '',
`nurl` varchar(255) NOT NULL DEFAULT '',
`version` varchar(255) NOT NULL DEFAULT '',
`site_name` varchar(255) NOT NULL DEFAULT '',
`info` text NOT NULL,
`register_policy` tinyint(1) NOT NULL DEFAULT 0,
`poco` varchar(255) NOT NULL DEFAULT '',
`noscrape` varchar(255) NOT NULL DEFAULT '',
`network` varchar(32) NOT NULL DEFAULT '',
`platform` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_poco_query` datetime DEFAULT '0000-00-00 00:00:00',
`last_contact` datetime DEFAULT '0000-00-00 00:00:00',
`last_failure` datetime DEFAULT '0000-00-00 00:00:00',
INDEX `nurl` (`nurl`)
) DEFAULT CHARSET=utf8;
--
-- TABLE guid
--

70
doc/Accesskeys.md Normal file
View file

@ -0,0 +1,70 @@
Accesskeys in Friendica
=======================
General
-------
* p: profile
* n: network
* c: community
* s: search
* a: admin
* f: notifications
* u: user menu (in themes "vier" and "quattro")
/profile
--------
* m: Status Messages and Posts
* r: Profile Details
* h: Photo Albums
* v: Videos
* e: Events and Calendar
* t: Personal Notes
/contacts (contact list)
---------
* g: Suggestions
* l: Show all Contacts
* o: Only show unblocked contacts
* b: Only show blocked contacts
* i: Only show ignored contacts
* y: Only show archived contacts
* h: Only show hidden contacts
/contacts (single contact view)
-------------------------------
* b: Toggle Blocked status
* i: Toggle Ignored status
* v: Toggle Archive status
* r: Repair
/message
--------
* m: New message
/network
--------
* e: Sort by Comment Date
* t: Sort by Post Date
* r: Conversation (Posts that mention or involve you)
* w: New posts
* b: Bookmarks
* m: Favourite Posts
/notifications
--------------
* y: System
* w: Network
* r: Personal
* h: Home
* i: Introductions
/settings
---------
* o: Account
* t: Additional features
* w: Social Networks
* l: Plugins
* d: Delegations
* b: Connected apps
* e: Export personal data
* r: Remove account

View file

@ -60,6 +60,14 @@ Block
<p style="clear:both;">&nbsp;</p>
<pre>You should not read any further if you want to be surprised.[spoiler]There is a happy end.[/spoiler]</pre>
You should not read any further if you want to be surprised.<br />*click to open/close*
(The text between thhe opening and the closing of the spoiler tag will be visible once the link is clicked. So *"There is a happy end."* wont be visible until the spoiler is uncovered.)
<p style="clear:both;">&nbsp;</p>
**Table**
<pre>[table border=1]
[tr]

View file

@ -49,7 +49,7 @@ Just unpack the file and rename the directory to „jappixmini“.
Next, upload this directory and the .tgz-file into your addon directory of your friendica installation.
Now you can activate the plugin globally on the admin pages.
In the plugin sidebar, you will find an entry of jappix now (where you can also find twitter, statusnet and others).
In the plugin sidebar, you will find an entry of jappix now (where you can also find twitter, GNU Social and others).
The following page shows the settings of this plugin.
Activate the BOSH proxy.

View file

@ -4,14 +4,13 @@ Connectors
* [Home](help)
Connectors allow you to connect with external social networks and services.
They are only required for posting to existing accounts on Facebook, Twitter, and StatusNet.
They are only required for posting to existing accounts on Twitter or GNU Social.
There is also a connector for accessing your email INBOX.
If the following network connectors are installed on your system, select the following links to visit the appropriate settings page and configure them for your account:
* [Facebook](/settings/addon)
* [Twitter](/settings/addon)
* [StatusNet](/settings/addon)
* [GNU Social](/settings/addon)
* [Email](/settings)
Instructions For Connecting To People On Specific Services
@ -30,10 +29,10 @@ Diaspora
Add the Diaspora 'handle' to the 'Connect/Follow' text box on your [Contacts](contacts) page.
Identi.ca/StatusNet/GNU-Social
GNU Social
---
These are described as the "federated social web" or OStatus contacts.
This is described as the "federated social web" or OStatus contacts.
Please note that there are **no** privacy provisions on the OStatus network.
Any message which is delivered to **any** OStatus member is visible to anybody in the world and will negate any privacy settings that you have in effect.
@ -43,7 +42,7 @@ Since OStatus communications do not use authentication, if you select the profil
To connect with an OStatus member insert their profile URL or Identity address into the Connect box on your [Contacts](contacts) page.
The StatusNet connector may be used if you wish posts to appear on an OStatus site using an existing OStatus account.
The GNU Social connector may be used if you wish posts to appear on an OStatus site using an existing OStatus account.
It is not necessary to do this, as you may 'follow' OStatus members from Friendica and they may follow you (by placing their own Identity Address into your 'Connect' page).
Blogger, Wordpress, RSS feeds, arbitrary web pages
@ -69,23 +68,3 @@ Configure the email connector from your [Settings](settings) page.
Once this has been done, you may enter an email address to connect with using the Connect box on your [Contacts](contacts) page.
They must be the sender of a message which is currently in your INBOX for the connection to succeed.
You may include email contacts in private conversations.
Facebook
---
The Facebook connector is a plugin/addon which allows you to interact with friends on Facebook from within Friendica.
If enabled, your Facebook friend list will be imported, and you will see and be able to respond to Facebook posts.
Facebook members may also be added to private conversation groups.
You will not be able to connect with individual Facebook accounts - but will have your entire friend list imported and updated if new friends are added.
Assuming the Facebook plugin/addon has been installed on your system, it can be enabled by going to your [Plugin Settings](settings/addon) page, and then selecting "Facebook Connector Settings" on that page.
This will only appear if the Facebook plugin/addon has been installed.
Follow the instruction to install or remove the Facebook connector.
You may also choose whether your public postings are posted to Facebook by default.
You may toggle this setting at any time from the Permissions settings of the status post editor (click the lock icon).
This setting has no effect on private conversations - which will always be delivered to Facebook friends who are included in the permissions.
(Note: At this time, Facebook contacts will not be able to view any private photos.
This will be resolved in a future release.
Facebook contacts may however see any public photos you have uploaded.)

View file

@ -69,7 +69,7 @@ Do not worry about cross-posting.
###Client software
There are free software clients that do somehow work with Friendica but most of them need love and maintenance.
Also, they were mostly made for other platforms using the StatusNet API.
Also, they were mostly made for other platforms using the GNU Social API.
This means they lack the features that are really specific to Friendica.
Popular clients you might want to have a look at are:

View file

@ -19,6 +19,8 @@ Admins
* **[Can I configure multiple domains with the same code instance?](help/FAQ#multiple)**
* **[Where can I find the source code of friendica, addons and themes?](help/FAQ#sources)**
* **[I've changed the my email address now the admin panel is gone?](help/FAQ#adminaccount1)**
* **[Can there be more then just one admin for a node?](help/FAQ#adminaccount2)**
User
--------
@ -119,7 +121,7 @@ No. The act of 'following' a hashtags is an interesting technology, but presents
1. Posts would have to be copied to all sites on the network that are "listening" to that hashtag. This would increase the storage demands to the detriment of small sites. It would make the use of shared hosting practically impossible.
2. Making spam easy (tag spam is quite a serious issue on identi.ca for instance)
2. Making spam easy (tag spam is a serious issue on Twitter for instance)
3. It creates a natural bias towards large sites which hold more tagged content - if your network uses tagging instead of other conversation federation mechanisms such as groups/forums.
@ -151,7 +153,7 @@ RSS feed of the conversations at your site
###Are there any clients for friendica I can use?
Friendica is using a [Twitter/StatusNet compatible API](help/api), which means you can use any Twitter/StatusNet/GNU Social client for your plattform as long as you can change the API path in its settings.
Friendica is using a [Twitter/GNU Social compatible API](help/api), which means you can use any Twitter/GNU Social client for your plattform as long as you can change the API path in its settings.
Here is a list of known working clients:
* Android
@ -198,3 +200,14 @@ There you will always find the current stable version of friendica.
Addons are listed at [this page](https://github.com/friendica/friendica-addons).
If you are searching for new themes, you can find them at [Friendica-Themes.com](http://friendica-themes.com/)
<a name="adminaccount1"></a>
###I've changed the my email address now the admin panel is gone?
Have a look into your <tt>.htconfig.php</tt> and fix your email address there.
<a name="adminaccount2"></a>
###Can there be more then just one admin for a node?
Yes. You just have to list more then one email address in the
<tt>.htconfig.php</tt> file. The listed emails need to be separated by a comma.

View file

@ -40,7 +40,7 @@ These private conversations work best when your friends are Friendica members. W
This is a trust issue you need to be aware of. No software in the world can prevent your friends from leaking your confidential and trusted communications. Only a wise choice of friends.
But it isn't as clear cut when dealing with status.net, identi.ca and other network providers. You are encouraged to be **very** cautious when other network members are in a group because it's entirely possible for your private messages to end up in a public newsfeed. If you look at the Contact Edit page for any person, we will tell you whether or not they are members of an insecure network where you should exercise caution.
But it isn't as clear cut when dealing with GNU Social and other network providers. You are encouraged to be **very** cautious when other network members are in a group because it's entirely possible for your private messages to end up in a public newsfeed. If you look at the Contact Edit page for any person, we will tell you whether or not they are members of an insecure network where you should exercise caution.
Once you have created a post, you can not change the permissions assigned. Within seconds it has been delivered to lots of people - and perhaps everybody it was addressed to. If you mistakenly created a message and wish you could take it back, the best you can do is to delete it. We will send out a delete notification to everybody who received the message - and this should wipe out the message with the same speed it was initially propagated. In most cases it will be completely wiped from the Internet - in under a minute. Again, this applies to Friendica networks. Once a message spreads to other networks, it may not be removed quickly and in some cases it may not be removed at all.
@ -62,8 +62,8 @@ Our developers are working on solutions to allow access to your friends - no mat
Your profile and "wall" may also be visited by your friends from other networks, and you can block access to these by web visitors that Friendica doesn't know. Be aware that this could include some of your friends on other networks.
This may produce undesired results when posting a long status message to (for instance) Twitter and even Facebook. When Friendica sends a post to these networks which exceeds the service length limit, we truncate it and provide a link to the original. The original is a link back to your Friendica profile. As Friendica cannot prove who they are, it may not be possible for these people to view your post in full.
This may produce undesired results when posting a long status message to (for instance) Twitter or App.net. When Friendica sends a post to these networks which exceeds the service length limit, we truncate it and provide a link to the original. The original is a link back to your Friendica profile. As Friendica cannot prove who they are, it may not be possible for these people to view your post in full.
For people in this situation we would recommend providing a "Twitter-length" summary, with more detail for friends that can see the post in full.
Blocking your profile or entire Friendica site from unknown web visitors also has serious implications for communicating with StatusNet/identi.ca members. These networks communicate with others via public protocols that are not authenticated. In order to view your posts, these networks have to access them as an "unknown web visitor". If we allowed this, it would mean anybody could in fact see your posts, and you've instructed Friendica not to allow this. So be aware that the act of blocking your profile to unknown visitors also has the effect of blocking outbound communication with public networks (such as identi.ca) and feed readers such as Google Reader.
Blocking your profile or entire Friendica site from unknown web visitors also has serious implications for communicating with GNU Social members. These networks communicate with others via public protocols that are not authenticated. In order to view your posts, these networks have to access them as an "unknown web visitor". If we allowed this, it would mean anybody could in fact see your posts, and you've instructed Friendica not to allow this. So be aware that the act of blocking your profile to unknown visitors also has the effect of blocking outbound communication with public networks (such as GNU Social) and feed readers such as Google Reader.

View file

@ -10,6 +10,8 @@ Friendica Documentation and Resources
* [BBCode tag reference](help/BBCode)
* [Comment, sort and delete posts](help/Text_comment)
* [Profiles](help/Profiles)
* [Accesskey reference](help/Accesskeys
* [Events](help/events)
* You and other users
* [Connectors](help/Connectors)
* [Making Friends](help/Making-Friends)
@ -27,10 +29,10 @@ Friendica Documentation and Resources
* [Install](help/Install)
* [Settings](help/Settings)
* [Installing Connectors (Facebook/Twitter/StatusNet)](help/Installing-Connectors)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Message Flow](help/Message-Flow)
* [Using SSL with Friendica](help/SSL)
* [Twitter/StatusNet API Functions](help/api)
* [Twitter/GNU Social API Functions](help/api)
**Developer Manual**
@ -40,6 +42,7 @@ Friendica Documentation and Resources
* [How to translate Friendica](help/translations)
* [Bugs and Issues](help/Bugs-and-Issues)
* [Plugin Development](help/Plugins)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
**External Resources**

View file

@ -16,51 +16,19 @@ This value reduces the data that is send from the server to the client. 50 is a
Set "OStatus conversation completion interval" to "never".
If you have many OStatus contacts then completing of conversations can be very time wasting. The downside: You won't see every comment in OStatus threads.
Set "Path for lock file" to an empty folder outside your web root.
Lock files help avoid the possibility of several background processes running at the same time.
For example: It can happen that the poller.php takes longer than expected.
When there is no lock file, it is possible for several instances of poller.php to run at the same time - which would slow down the system and affect the maximum numbers of processes and database connections.
Please define a full file path that is writeable by the web server process.
If your site is located at "/var/www/sitename/htdocs/" you could maybe create a folder "/var/www/sitename/temp/".
If you have many OStatus contacts then completing of conversations can take some time. Since you will miss several comments in OStatus threads, you maybe should consider the option "At post arrival" instead.
Enable "Use MySQL full text engine"
When using MyISAM (default) this speeds up search.
Set "Path to item cache" to an empty value outside your web root.
Parsed BBCode and some external images will be put there.
Parsing BBCode is a time wasting process that also makes heave use of the CPU.
You can use the same folder you used for the lock file.
**Warning!**
The folder for item cache is cleaned up regularly.
Every file that exceeds the cache duration is deleted. **If you accidentally point the cache path to your web root then you will delete your web root!**
So double check that the folder only contains temporary content that can be deleted at any time.
You have been warned.
When using MyISAM (default) or InnoDB on MariaDB 10 this speeds up search.
Plugins
--------
Active the following plugins:
Alternate Pagination
Privacy Image Cache
rendertime
###Alternate Pagination
This plugin reduces the database load massively.
Downside: You can't see the total number of pages available at each module, and have this replaced with "older" and "newer" links.
Go to the admin settings of "altpager" and set it to "global".
###rendertime
This plugin doesn't speed up your system.
@ -111,13 +79,6 @@ In a Debian-based distribution you will need to install the packages named "php5
Please refer to external documentation for a more detailed explanation how to set up a system based upon FCGI.
###APC
APC is an opcode cache.
It speeds up the processing of PHP code.
When APC is enabled, Friendica uses it to store configuration data between different requests.
This helps speeding up the page creation time.
###Database
There are scripts like [tuning-primer.sh](http://www.day32.com/MySQL/) and [mysqltuner.pl](http://mysqltuner.pl) that analyze your database server and give hints on values that could be changed.

View file

@ -65,6 +65,8 @@ If you copy the directory tree to your webserver, make sure that you also copy .
Create an empty database and note the access details (hostname, username, password, database name).
Friendica needs the permission to create and delete fields and tables in its own database.
###Run the installer
Point your web browser to the new site and follow the instructions.

View file

@ -1,13 +1,13 @@
Installing Connectors (Facebook/Twitter/StatusNet)
Installing Connectors (Twitter/GNU Social)
==================================================
* [Home](help)
Friendica uses plugins to provide connectivity to some networks, such as Facebook and Twitter.
Friendica uses plugins to provide connectivity to some networks, such as Twitter or App.net.
There is also a plugin to post through to an existing account on a StatusNet service.
You only need this to post to an already existing StatusNet account, but not to communicate with StatusNet members in general.
There is also a plugin to post through to an existing account on a GNU Social service.
You only need this to post to an already existing GNU Social account, but not to communicate with GNU Social members in general.
All three plugins require an account on the target network.
In addition you (or typically the server administrator) will need to obtain an API key to provide authenticated access to your Friendica server.
@ -51,7 +51,7 @@ After this, your users can configure their Twitter account settings from "Settin
Find the author's documentation here: [http://diekershoff.homeunix.net/redmine/wiki/friendikaplugin/Twitter_Plugin](http://diekershoff.homeunix.net/redmine/wiki/friendikaplugin/Twitter_Plugin)
StatusNet Plugin for Friendica
GNU Social Plugin for Friendica
---
* Author: Tobias Diekershoff
@ -60,77 +60,33 @@ StatusNet Plugin for Friendica
###Configuration
When the addon is activated the user has to aquire the following in order to connect to the StatusNet account of choice.
When the addon is activated the user has to aquire the following in order to connect to the GNU Social account of choice.
* The base URL for the StatusNet API, for identi.ca this is https://identi.ca/api/
* The base URL for the GNU Social API, for quitter.se this is https://quitter.se/api/
* OAuth Consumer key & secret
To get the OAuth Consumer key pair the user has to
1 ask her Friendica admin if a pair already exists or
2 has to register the Friendica server as a client application on the StatusNet server.
2 has to register the Friendica server as a client application on the GNU Social server.
This can be done from the account settings under "Settings -> Connections -> Register an OAuth client application -> Register a new application" on the StatusNet server.
This can be done from the account settings under "Settings -> Connections -> Register an OAuth client application -> Register a new application" on the GNU Social server.
During the registration of the OAuth client remember the following:
* Application names must be unique on the StatusNet site, so we recommend a Name of 'friendica-nnnn', replace 'nnnn' with a random number or your website name.
* Application names must be unique on the GNU Social site, so we recommend a Name of 'friendica-nnnn', replace 'nnnn' with a random number or your website name.
* there is no callback url
* register a desktop client
* with read & write access
* the Source URL should be the URL of your Friendica server
After the required credentials for the application are stored in the configuration you have to actually connect your Friendica account with StatusNet.
After the required credentials for the application are stored in the configuration you have to actually connect your Friendica account with GNU Social.
This is done from the Settings -> Connector Settings page.
Follow the Sign in with StatusNet button, allow access and then copy the security code into the box provided.
Follow the Sign in with GNU Social button, allow access and then copy the security code into the box provided.
Friendica will then try to acquire the final OAuth credentials from the API.
If successful, the addon settings will allow you to select to post your public messages to your StatusNet account (have a look behind the little lock symbol beneath the status "editor" on your Home or Network pages).
If successful, the addon settings will allow you to select to post your public messages to your GNU Social account (have a look behind the little lock symbol beneath the status "editor" on your Home or Network pages).
###More documentation
Find the author's documentation here: [http://diekershoff.homeunix.net/redmine/wiki/friendikaplugin/StatusNet_Plugin](http://diekershoff.homeunix.net/redmine/wiki/friendikaplugin/StatusNet_Plugin)
The Friendica/Facebook connector
---
###Configuration
First, register an API key for your site on [Facebook](developer.facebook.com).
This requires a Facebook account, and may require additional authentication in the form of credit card or mobile phone verification.
We'd be very happy if you include "Friendica" in the application name to increase name recognition.
The Friendica icons are also present in the images directory and may be uploaded as a Facebook app icon.
Use images/friendica-16.jpg for the Icon and images/friendica-128.jpg for the logo.
The url should be your site URL with a trailing slash.
You **may** be required to provide a privacy and/or terms of service URL.
Navigate to Set Web->Site URL & Domain -> Website Settings.
Set Site URL to yoursubdomain.yourdomain.com.
Set Site Domain to your yourdomain.com.
Install the Facebook plugin on your Friendica site at 'admin/plugins'.
You should then see a link for Facebook under 'Plugin Features' on the sidebar of the admin panel.
Select it.
Enter the App-ID and App Secret that Facebook gave you.
Change any other settings as desired.
On Friendica, each member who wishes to use the Facebook connector should visit the Facebook Settings section of their "Settings->Connector Settings" page, and click 'Install Facebook Connector'.
Choose the appropriate settings for your usage and privacy requirements.
This will ask you to log into Facebook and grant permission to the plugin to do its stuff.
Allow it to do so.
You're done.
To turn it off visit the Connector Settings page again and 'Remove Facebook posting'.
Videos and embeds will not be posted if there is no other content.
Links and images will be converted to a format suitable for the Facebook API and long posts truncated - with a link to view the full post.
Facebook contacts will also not be able to view "private" photos, as they are not able to authenticate to your site.
We will address this in a future release.

View file

@ -51,14 +51,11 @@ This will take you through a similar process.
Connect to users of alternate networks
---
###StatusNet/GNUSocial, Google Plus, Twitter, Diaspora
###GNU Social, Twitter, Diaspora
You can also use your Identity Address or other people's Identity Addresses to become friends across networks.
The list of possible networks is growing all the time.
If you know (for instance) "bob" on identi.ca (a StatusNet site) you could put bob@identi.ca into your Contact page and become friends across networks.
(Or you can put in the URL to Bob's identi.ca page if you wish).
You can also be "partial" friends with somebody on Google Plus by putting in their gmail address.
Google Plus does not yet support all the protocols we need for direct messaging, but you should be able to follow status updates from within Friendica.
If you know (for instance) "bob" on gnusocial.de (a GNU Social site) you could put bob@gnusocial.de into your Contact page and become friends across networks.
(Or you can put in the URL to Bob's gnusocial.de page if you wish).
You can do the same for Twitter accounts and Diaspora accounts.
@ -70,10 +67,10 @@ If you have supplied your mailbox connection information on your Settings page,
You can also reply to them from within Friendica.
People can also become friends with you from other networks.
If a friend of yours has an identi.ca account, they can become friends with you by putting your Friendica Identity Address into their identi.ca subscription dialog box.
If a friend of yours has an GNU Social account, they can become friends with you by putting your Friendica Identity Address into their GNU Social subscription dialog box.
A similar mechanism is available for Diaspora members, by putting your identity address into their search bar.
Note: Some versions of StatusNet software may require the full URL to your profile and may not work with the identity address.
Note: Some versions of GNU Social software may require the full URL to your profile and may not work with the identity address.
Notification
---

View file

@ -21,7 +21,7 @@ Friendica will recreate your account on the new server, with your contacts and g
A message is sent to Friendica contacts, to inform them about your move:
If your contacts are runnning on an updated server, your details on their side will be automatically updated.
StatusNet/GNUSocial/Diaspora contacts
GNU Social/Diaspora contacts
---
Contacts on Statusnet/Identi.ca or Diaspora will be archived, as we can't inform them about your move.
Contacts on GNU Social or Diaspora will be archived, as we can't inform them about your move.
You should ask them to remove your contact from their lists and re-add you, and you should do the same with their contact.

View file

@ -2,7 +2,6 @@ Friendica Addon/Plugin development
==========================
Please see the sample addon 'randplace' for a working example of using some of these features.
The facebook addon provides an example of integrating both "addon" and "module" functionality.
Addons work by intercepting event hooks - which must be registered.
Modules work by intercepting specific page requests (by URL path).

View file

@ -200,7 +200,7 @@ This configures the URL to update the global directory, and is supplied in the d
The undocumented part is that if this is not set, the global directory is completely unavailable to the application.
This allows a private community to be completely isolated from the global mistpark network.
$a->config['system']['directory_submit_url'] = 'http://dir.friendica.com/submit';
$a->config['system']['directory'] = 'http://dir.friendi.ca';
Developer Settings
---

View file

@ -23,7 +23,7 @@ You can tag a person on a different network or one that is **not in your social
Unless their system blocks unsolicited "mentions", the person tagged will likely receive a "Mention" post/activity or become a direct participant in the conversation in the case of public posts. Please note that Friendica blocks incoming "mentions" from people with no relationship to you. This is a spam prevention measure.
Remote mentions are delivered using the OStatus protocol. This protocol is used by Friendica and StatusNet and several other systems, but is not currently implemented in Diaspora.
Remote mentions are delivered using the OStatus protocol. This protocol is used by Friendica and GNU Social and several other systems, but is not currently implemented in Diaspora.
Friendica makes no distinction between people and groups for the purpose of tagging. (Some other networks use !group to indicate a group.)

View file

@ -17,7 +17,7 @@ Inside, you'll find a "Vagrantfile" and some scripts in the utils folder.
3. Run "vagrant up" from inside the friendica clone.
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 to finish the Friendica installation.
5. Open 192.168.22.10 in a browser.
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).
7. Check the changes in your browser in the VM.
@ -30,13 +30,7 @@ If you want to stop vagrant after finishing your work, run the following command
in the development directory.
Import test data
----------------
If you want some test data in your vagrant Friendica instance import the database dump friendica_test_data.sql like so (inside the VM):
$> mysql -u root -p friendica < /vagrant/friendica_test_data.sql
The vagrant Friendica instance contains a test database.
You will then have the following accounts to login:
* admin, password admin

View file

@ -1,40 +1,280 @@
Implemented API calls
===
The friendica API aims to be compatible to the [StatusNet API](http://status.net/wiki/Twitter-compatible_API) which aims to be compatible to the [Twitter API 1.0](https://dev.twitter.com/docs/api/1).
The Friendica API aims to be compatible to the [GNU Social API](http://skilledtests.com/wiki/Twitter-compatible_API) and the [Twitter API](https://dev.twitter.com/rest/public).
Please refer to the linked documentation for further information.
General
---
## Implemented API calls
### Unsupported parameters
* cursor: Not implemented in StatusNet
* trim_user: Not implemented in StatusNet
* contributor_details: Not implemented in StatusNet
* place_id: Not implemented in StatusNet
* display_coordinates: Not implemented in StatusNet
### General
#### Unsupported parameters
* cursor: Not implemented in GNU Social
* trim_user: Not implemented in GNU Social
* contributor_details: Not implemented in GNU Social
* place_id: Not implemented in GNU Social
* display_coordinates: Not implemented in GNU Social
* include_rts: To-Do
* include_my_retweet: Retweets in friendica are implemented in a different way
* include_my_retweet: Retweets in Friendica are implemented in a different way
### Different behaviour
#### Different behaviour
* screen_name: The nick name in friendica is only unique in each network but not for all networks. The users are searched in the following priority: Friendica, StatusNet/GNU Social, Diaspora, pump.io, Twitter. If no contact was found by this way, then the first contact is taken.
* include_entities: Default is "false". If set to "true" then the plain text is formatted so that links are having descriptions.
### Return values
#### Return values
* cid: Contact id of the user (important for "contact_allow" and "contact_deny")
* network: network of the user
account/verify_credentials
---
### account/rate_limit_status
### Parameters
### account/verify_credentials
#### Parameters
* skip_status: Don't show the "status" field. (Default: false)
* include_entities: "true" shows entities for pictures and links (Default: false)
statuses/update, statuses/update_with_media
---
### conversation/show
Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
### Parameters
#### Parameters
* id: id of the post
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* include_rts
* trim_user
* contributor_details
### direct_messages
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* skip_status
### direct_messages/all
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
### direct_messages/conversation
Shows all direct messages of a conversation
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* uri: URI of the conversation
### direct_messages/new
#### Parameters
* user_id: id of the user
* screen_name: screen name (for technical reasons, this value is not unique!)
* text: The message
* replyto: ID of the replied direct message
* title: Title of the direct message
### direct_messages/sent
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
### favorites
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* user_id
* screen_name
Favorites aren't displayed to other users, so "user_id" and "screen_name". So setting this value will result in an empty array.
### favorites/create
#### Parameters
* id
* include_entities: "true" shows entities for pictures and links (Default: false)
### favorites/destroy
#### Parameters
* id
* include_entities: "true" shows entities for pictures and links (Default: false)
### followers/ids
#### Parameters
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
#### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing followers of other users.
### friendica/photo
#### Parameters
* photo_id: Resource id of a photo.
Returns data of a picture with the given resource.
### friendica/photos/list
Returns a list of all photo resources of the logged in user.
### friends/ids
#### Parameters
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
#### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing friends of other users.
### help/test
### media/upload
#### Parameters
* media: image data
### oauth/request_token
#### Parameters
* oauth_callback
#### Unsupported parameters
* x_auth_access_type
### oauth/access_token
#### Parameters
* oauth_verifier
#### Unsupported parameters
* x_auth_password
* x_auth_username
* x_auth_mode
### statuses/destroy
#### Parameters
* id: message number
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* trim_user
### statuses/followers
* include_entities: "true" shows entities for pictures and links (Default: false)
### statuses/friends
* include_entities: "true" shows entities for pictures and links (Default: false)
### statuses/friends_timeline
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* include_rts
* trim_user
* contributor_details
### statuses/home_timeline
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* include_rts
* trim_user
* contributor_details
### statuses/mentions
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* include_rts
* trim_user
* contributor_details
### statuses/public_timeline
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* trim_user
### statuses/replies
#### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* include_rts
* trim_user
* contributor_details
### statuses/retweet
#### Parameters
* id: message number
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* trim_user
### statuses/show
#### Parameters
* id: message number
* conversation: if set to "1" show all messages of the conversation with the given id
* include_entities: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* include_my_retweet
* trim_user
### statuses/update, statuses/update_with_media
#### Parameters
* title: Title of the status
* status: Status in text format
* htmlstatus: Status in HTML format
@ -49,379 +289,157 @@ statuses/update, statuses/update_with_media
* contact_deny
* network
* include_entities: "true" shows entities for pictures and links (Default: false)
* media_ids: (By now only a single value, no array)
### Unsupported parameters
#### Unsupported parameters
* trim_user
* place_id
* display_coordinates
users/search
---
### statuses/user_timeline
#### Parameters
* user_id: id of the user
* screen_name: screen name (for technical reasons, this value is not unique!)
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
### Parameters
#### Unsupported parameters
* include_rts
* trim_user
* contributor_details
### statusnet/config
### statusnet/version
#### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing followers of other users.
### users/search
#### Parameters
* q: name of the user
### Unsupported parameters
#### Unsupported parameters
* page
* count
* include_entities
users/show
---
### Parameters
### users/show
#### Parameters
* user_id: id of the user
* screen_name: screen name (for technical reasons, this value is not unique!)
* include_entities: "true" shows entities for pictures and links (Default: false)
statuses/home_timeline
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_rts
* trim_user
* contributor_details
statuses/friends_timeline
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_rts
* trim_user
* contributor_details
statuses/public_timeline
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* trim_user
statuses/show
---
### Parameters
* id: message number
* conversation: if set to "1" show all messages of the conversation with the given id
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_my_retweet
* trim_user
statuses/retweet
---
### Parameters
* id: message number
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* trim_user
statuses/destroy
---
### Parameters
* id: message number
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* trim_user
statuses/mentions
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_rts
* trim_user
* contributor_details
statuses/replies
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_rts
* trim_user
* contributor_details
statuses/user_timeline
---
### Parameters
* user_id: id of the user
* screen_name: screen name (for technical reasons, this value is not unique!)
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* exclude_replies: don't show replies (default: false)
* conversation_id: Shows all statuses of a given conversation.
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_rts
* trim_user
* contributor_details
conversation/show
---
Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
### Parameters
* id: id of the post
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* include_rts
* trim_user
* contributor_details
favorites
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* user_id
* screen_name
Favorites aren't displayed to other users, so "user_id" and "screen_name". So setting this value will result in an empty array.
account/rate_limit_status
---
help/test
---
statuses/friends
---
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
#### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing friends of other users.
statuses/followers
---
## Not Implemented API calls
The following API calls are implemented in GNU Social but not in Friendica: (incomplete)
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing followers of other users.
statusnet/config
---
statusnet/version
---
friends/ids
---
### Parameters
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing friends of other users.
followers/ids
---
Parameters
---
* stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
### Unsupported parameters
* user_id
* screen_name
* cursor
Friendica doesn't allow showing followers of other users.
direct_messages/new
---
### Parameters
* user_id: id of the user
* screen_name: screen name (for technical reasons, this value is not unique!)
* text: The message
* replyto: ID of the replied direct message
* title: Title of the direct message
direct_messages/conversation
---
Shows all direct messages of a conversation
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* uri: URI of the conversation
direct_messages/all
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
direct_messages/sent
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
direct_messages
---
### Parameters
* count: Items per page (default: 20)
* page: page number
* since_id: minimal id
* max_id: maximum id
* getText: Defines the format of the status field. Can be "html" or "plain"
* include_entities: "true" shows entities for pictures and links (Default: false)
### Unsupported parameters
* skip_status
oauth/request_token
---
### Parameters
* oauth_callback
### Unsupported parameters
* x_auth_access_type
oauth/access_token
---
### Parameters
* oauth_verifier
### Unsupported parameters
* x_auth_password
* x_auth_username
* x_auth_mode
Not Implemented API calls
===
The following list is extracted from the [API source file](https://github.com/friendica/friendica/blob/master/include/api.php) (at the very bottom):
* favorites/create
* favorites/destroy
* statuses/retweets_of_me
* friendships/create
* friendships/destroy
* friendships/exists
* friendships/show
* account/update_location
* account/update_profile_background_image
* account/update_profile_image
* blocks/create
* blocks/destroy
The following are things from the Twitter API also not implemented in StatusNet:
* statuses/retweeted_to_me
* statuses/retweeted_by_me
The following API calls from the Twitter API aren't implemented neither in Friendica nor in GNU Social:
* statuses/mentions_timeline
* statuses/retweets/:id
* statuses/oembed
* statuses/retweeters/ids
* statuses/lookup
* direct_messages/show
* search/tweets
* direct_messages/destroy
* account/end_session
* friendships/no_retweets/ids
* friendships/incoming
* friendships/outgoing
* friendships/update
* friends/list
* friendships/lookup
* account/settings
* account/update_delivery_device
* notifications/follow
* notifications/leave
* blocks/exists
* blocks/blocking
* lists
Usage Examples
===
BASH / cURL
---
* account/update_profile
* account/update_profile_background_image
* account/update_profile_image
* blocks/list
* blocks/ids
* users/lookup
* users/show
* users/search
* account/remove_profile_banner
* account/update_profile_banner
* users/profile_banner
* mutes/users/create
* mutes/users/destroy
* mutes/users/ids
* mutes/users/list
* users/suggestions/:slug
* users/suggestions
* users/suggestions/:slug/members
* favorites/list
* lists/list
* lists/statuses
* lists/members/destroy
* lists/memberships
* lists/subscribers
* lists/subscribers/create
* lists/subscribers/show
* lists/subscribers/destroy
* lists/members/create_all
* lists/members/show
* lists/members
* lists/members/create
* lists/destroy
* lists/update
* lists/create
* lists/show
* lists/subscriptions
* lists/members/destroy_all
* lists/ownerships
* saved_searches/list
* saved_searches/show/:id
* saved_searches/create
* saved_searches/destroy/:id
* geo/id/:place_id
* geo/reverse_geocode
* geo/search
* geo/place
* trends/place
* trends/available
* help/configuration
* help/languages
* help/privacy
* help/tos
* trends/closest
* users/report_spam
## Usage Examples
### BASH / cURL
Betamax has documentated some example API usage from a [bash script](https://en.wikipedia.org/wiki/Bash_(Unix_shell) employing [curl](https://en.wikipedia.org/wiki/CURL) (see [his posting](https://betamax65.de/display/betamax65/43539)).
/usr/bin/curl -u USER:PASS https://YOUR.FRIENDICA.TLD/api/statuses/update.xml -d source="some source id" -d status="the status you want to post"
Python
---
The [RSStoFriedika](https://github.com/pafcu/RSStoFriendika) code can be used as an example of how to use the API with python.
The lines for posting are located at [line 21](https://github.com/pafcu/RSStoFriendika/blob/master/RSStoFriendika.py#L21) and following.
### Python
The [RSStoFriedika](https://github.com/pafcu/RSStoFriendika) code can be used as an example of how to use the API with python. The lines for posting are located at [line 21](https://github.com/pafcu/RSStoFriendika/blob/master/RSStoFriendika.py#L21) and following.
def tweet(server, message, group_allow=None):
url = server + '/api/statuses/update'

View file

@ -60,6 +60,14 @@ Block Tags
<p style="clear:both;">&nbsp;</p>
<pre>Wer überrascht werden möchte sollte nicht weiter lesen.[spoiler]Es gibt ein Happy End.[/spoiler]</pre>
Wer überrascht werden möchte sollte nicht weiter lesen.<br />*klicken zum öffnen/schließen*
(Der Text zweischen dem öffnenden und dem schließenden Teil des spoiler Tags wird nicht angezeigt, bis der Link angeklickt wurde. In dem Fall wird *"Es gibt ein Happy End."* also erst angezeigt, wenn der Spoiler verraten wird.)
<p style="clear:both;">&nbsp;</p>
**Tabelle**
<pre>[table border=1]
[tr]
@ -127,7 +135,15 @@ Wenn *url* entweder oembed oder opengraph unterstützt wird das eingebettete
Objekt (z.B. ein Dokument von scribd) eingebunden.
Der Titel der Seite mit einem Link zur *url* wird ebenfalls angezeigt.
Um eine Karte in einen Beitrag einzubinden, muss das *openstreetmap* Addon aktiviert werden. Ist dies der Fall, kann mit
<pre>[map]Broadway 26, New York[/map]</pre>
eine Karte von [OpenStreetmap](http://openstreetmap.org) eingebettet werden. Zur Identifikation des Ortes können entweder seine Koordinaten in der Form
<pre>[map=lat,long]</pre>
oder eine Adresse in obiger Form verwendet werden.
Spezielle Tags
-------

View file

@ -54,7 +54,7 @@ oder als normaler Download von hier: https://github.com/friendica/friendica-addo
Entpacke diese Datei (ggf. den entpackten Ordner in „jappixmini“ umbenennen) und lade sowohl den entpackten Ordner komplett als auch die .tgz Datei in den Addon Ordner Deiner Friendica Installation hoch.
Nach dem Upload gehts in den Friendica Adminbereich und dort zu den Plugins.
Aktiviere das Jappixmini Addon und gehe anschließend über die Plugins Seitenleiste (dort wo auch die Twitter-, Impressums-, StatusNet-, usw. Einstellungen gemacht werden) zu den Jappix Grundeinstellungen.
Aktiviere das Jappixmini Addon und gehe anschließend über die Plugins Seitenleiste (dort wo auch die Twitter-, Impressums-, GNU Social-, usw. Einstellungen gemacht werden) zu den Jappix Grundeinstellungen.
Setze hier den Haken zur Aktivierung des BOSH Proxys.
Weiter gehts in den Einstellungen Deines Friendica Accounts.

View file

@ -4,15 +4,14 @@ Konnektoren (Connectors)
* [Zur Startseite der Hilfe](help)
Konnektoren erlauben es Dir, Dich mit anderen sozialen Netzwerken zu verbinden.
Konnektoren werden nur bei bestehenden Facebook-, Twitter und StatusNet-Accounts benötigt.
Konnektoren werden nur bei bestehenden Twitter und GNU Social-Accounts benötigt.
Außerdem gibt es einen Konnektor, um Deinen Email-Posteingang zu nutzen.
Wenn Du keinen eigenen Knoten betreibst und wissen willst, ob der server Deiner Wahl diese Konnektoren installiert hat, kannst Du Dich darüber auf der Seite '&lt;domain_des_friendica-servers&gt;/friendica' informieren.
Sind die Netzwerk-Konnektoren auf Deinem System installiert sind, kannst Du mit den folgenden Links die Einstellungsseiten besuchen und für Deinen Account konfigurieren:
* [Facebook](/settings/connectors)
* [Twitter](/settings/connectors)
* [StatusNet / GNU Social](/settings/connectors)
* [GNU Social](/settings/connectors)
* [Email](/settings/connectors)
Anleitung, um sich mit Personen in bestimmten Netzwerken zu verbinden
@ -29,9 +28,9 @@ Ebenso kannst Du deren Identitäts-Adresse in der "Verbinden"-Box auf Deiner ["K
Füge die Diaspora-Identitäts-Adresse (z.B. name@diasporapod.com)auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein.
**Identi.ca/StatusNet/GNU-Social**
**GNU Social**
Diese Netzwerke werden als "federated social web" bzw. "OStatus"-Kontakte bezeichnet.
Dieses Netzwerk wird als "federated social web" bzw. "OStatus"-Kontakte bezeichnet.
Bitte beachte, dass es **keine** Einstellungen zur Privatssphäre im OStatus-Netzwerk gibt.
**Jede** Nachricht, die an eines dieser OStatus-Mitglieder verschickt wird, ist für jeden auf der Welt sichtbar; alle Privatssphäreneinstellungen verlieren ihre Wirkung.
@ -41,7 +40,7 @@ Da die OStatus-Kommunikation keine Authentifizierung benutzt, können OStatus-Nu
Um Dich mit einem OStatus-Mitglied zu verbinden, trage deren Profil-URL oder Identitäts-Adresse auf Deiner ["Kontakte"-Seite](contacts) in das Feld "Neuen Kontakt hinzufügen" ein.
Der StatusNet-Konnektor kann genutzt werden, wenn Du Beiträge schreiben willst, die auf einer OStatus-Seite über einen existierenden OStatus-Account erscheinen sollen.
Der GNU Social-Konnektor kann genutzt werden, wenn Du Beiträge schreiben willst, die auf einer OStatus-Seite über einen existierenden OStatus-Account erscheinen sollen.
Das ist nicht notwendig, wenn Du OStatus-Mitgliedern von Friendica aus folgst und diese Dir auch folgen, indem sie auf Deiner Kontaktseite ihre eigene Identitäts-Adresse eingeben.
@ -68,23 +67,3 @@ Konfiguriere den Email-Konnektor auf Deiner [Einstellungsseite](settings).
Wenn Du das gemacht hast, kannst Du auf Deiner ["Kontakte"-Seite](contacts) die Email-Adresse in das Feld "Neuen Kontakt hinzufügen" eintragen.
Diese Email-Adresse muss jedoch bereits mit einer Nachricht in Deinem Email-Posteingang auf dem Server liegen.
Du hast die Möglichkeit, Email-Kontakte in Deine privaten Unterhaltungen einzubeziehen.
**Facebook**
Der Facebook-Konnektor ist ein Plugin/Addon, dass es Dir erlaubt, von Friendica aus mit Freunden auf Facebook zu interagieren.
Wenn er aktiviert ist, wird Deine Facebook-Freundesliste importiert und Du wirst Facebook-Beiträge sehen und kommentieren können.
Facebook-Freunde können außerdem zu privaten Gesprächen hinzugefügt werden.
Du hast nicht die Möglichkeit, einzelne Facebook-Accounts hinzuzufügen, sondern nur Deine gesamte Freundesliste, die aktualisiert wird, wenn neue Freunde hinzugefügt werden.
Wenn das Facebook-Plugin/Addon installiert ist, kannst Du diesen auf Deiner Einstellungsseite unter ["Facebook Connector Settings"](/settings/connectors) einstellen.
Dieser Eintrag erscheint nur, wenn das Plugin/Addon installiert ist.
Folge den Vorgaben, um den Facebook-Konnektor zu installieren oder löschen.
Du kannst ebenfalls auswählen, ob Deine öffentlichen Posts auch standardmäßig bei Facebook veröffentlicht werden sollen.
Du kannst diese Einstellung jederzeit im aktuellen Beitrag beeinflussen, indem Du auf das "Schloss"-Icon unter dem Beitragseditor gehst.
Diese Einstellung hat keine Auswirkung auf private Unterhaltungen.
Diese werden immer an Facebook-Freunde mit den entsprechenden Genehmigungen geschickt.
(Beachte: Aktuell können Facebook-Kontakte keine privaten Fotos sehen.
Das wird zukünftig gelöst.
Facebook-Kontakte können aber trotzdem öffentliche Fotos sehen, die Du hochgeladen hast.)

View file

@ -131,7 +131,7 @@ Die Möglichkeit, einem hashtag zu folgen, ist eine interessante Technik, führt
1.) Alle Beiträge, die diesen tag nutzen, müssten zu allen Seiten im Netzwerk kopiert werden. Das erhöht den Speicherbedarf und beeinträchtigt kleine Seiten. Die Nutzung von geteilten Hosting-Angeboten (Shared Hosting) wäre praktisch unmöglich.
2.) Die Verbreitung von Spam wäre vereinfacht (tag-Spam ist z.B. bei identi.ca ein schwerwiegendes Problem)
2.) Die Verbreitung von Spam wäre vereinfacht (tag-Spam ist z.B. bei Twitter ein schwerwiegendes Problem)
3.) Der wichtigste Grund der gegen diese Technik spricht ist, dass sie eine natürliche Ausrichtung auf größere Seiten mit mehr getaggten Inhalten zur Folge hat. Dies kann z.B. aufkommen, wenn Dein Netzwerk tags anstelle von anderen Kommunikationsmitteln wie Gruppen oder Foren nutzt.

View file

@ -59,7 +59,7 @@ Dies ist eine Vertrauensfrage, die du beachten musst.
Keine Software der Welt kann deine Freunde davon abhalten, die privaten Unterhaltungen zu veröffentlichen.
Nur eine gute Auswahl deiner Freunde.
Bei status.net, identi.ca und anderen Netzwerk-Anbietern ist es nicht so gesichert.
Bei GNu Social und anderen Netzwerk-Anbietern ist es nicht so gesichert.
Du musst **sehr** vorsichtig sein, wenn du Mitglieder anderer Netzwerke in einer deiner Gruppen hast, da es möglich ist, dass deine privaten Nachrichten in einem öffentlichen Stream enden.
Wenn du auf die "Kontakt bearbeiten"-Seite einer Person gehst, zeigen wir dir, ob sie Mitglied eines unsicheren Netzwerks ist oder nicht.
@ -104,9 +104,9 @@ Da Friendica nicht bestätigen kann, um wen es sich handelt, kann es passieren,
Für Leute, die davon betroffen sind, schlagen wir vor, eine Zusammenfassung in Twitter-Länge zu erstellen mit mehr Details für Freunde, die den ganzen Beitrag sehen können.
Dein Profil oder deine gesamte Friendica-Seite zu blockieren, hat außerdem ernsthafte Einflüsse auf deine Kommunikation mit StatusNet/identi.ca-Nutzern.
Dein Profil oder deine gesamte Friendica-Seite zu blockieren, hat außerdem ernsthafte Einflüsse auf deine Kommunikation mit GNU Social-Nutzern.
Diese Netzwerke kommunizieren mit anderen über öffentliche Protokolle, die nicht authentifiziert werden.
Um deine Beiträge zu sehen, müssen diese Netzwerke deine Beiträge als "unbekannte Webbesucher" ansehen.
Wenn wir das erlauben, würde es dazu führen, das absolut jeder deine Beiträge sehen.
Und du hast Friendica so eingestellt, das nicht zuzulassen.
Beachte also, dass das Blockieren von unbekannten Besuchern auch dazu führen kann, dass öffentliche Netzwerke (wie identi.ca) und Newsfeed-Reader wie Google Reader auch geblockt werden.
Beachte also, dass das Blockieren von unbekannten Besuchern auch dazu führen kann, dass öffentliche Netzwerke (wie GNU Social) und Newsfeed-Reader auch geblockt werden.

View file

@ -10,6 +10,8 @@ Friendica - Dokumentation und Ressourcen
* [Referenz der BBCode Elemente](help/BBCode)
* [Beiträge kommentieren, einordnen und löschen](help/Text_comment)
* [Profile](help/Profiles)
* [Referenz der Accesskeys](help/Accesskeys)
* [Veranstaltungen](help/events) (EN)
* Du und andere Nutzer
* [Konnektoren (Connectors)](help/Connectors)
* [Freunde finden](help/Making-Friends)
@ -29,13 +31,23 @@ Friendica - Dokumentation und Ressourcen
* [Installation](help/Install)
* [Konfigurationen](help/Settings)
* [Plugins](help/Plugins)
* [Konnektoren (Connectors) installieren (Facebook/Twitter/StatusNet)](help/Installing-Connectors)
* [Konnektoren (Connectors) installieren (Twitter/GNU Social)](help/Installing-Connectors)
* [Nachrichtenfluss](help/Message-Flow)
* [Betreibe deine Seite mit einem SSL-Zertifikat](help/SSL)
* [Entwickler](help/Developers)
* [Twitter/StatusNet API Functions](help/api) (EN)
* [Twitter/GNU Social API Functions](help/api) (EN)
* [Translation of Friendica](help/translations) (EN)
**Entwickler Dokumentation**
* [Where to get started?](help/Developers-Intro)
* [Help on Github](help/Github)
* [Help on Vagrant](help/Vagrant)
* [How to translate Friendica](help/translations)
* [Bugs and Issues](help/Bugs-and-Issues)
* [Plugin Development](help/Plugins)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
**Externe Ressourcen**

View file

@ -22,56 +22,19 @@ Dieser Wert reduziert die Daten, die vom Server an den Client geschickt werden.
setze "Intervall zum Vervollständigen von OStatus Unterhaltungen" auf "niemals"
Wenn du viele OStatus-Kontakte hast, dann kann die Vervollständigung von Unterhaltungen sehr zeitraubend sein.
Der Nachteil: Du siehst nicht jede Antwort einer OStatus-Unterhaltung.
setze "Pfad für die Sperrdatei" auf einen Ordner außerhalb deines Stammverzeichnisses deines Servers.
Sperrdateien sorgen dafür, dass Hintergrundprozesse nicht parallel ablaufen.
Als Beispiel: Es kann passieren, dass die poller.php länger als erwartet läuft.
Ohne Sperrdatei kann es passieren, dass mehrere Instanzen der poller.php zur gleichen Zeit laufen.
Dies würde das System verlangsamen und Einfluss auf die maximale Anzahl an Prozessen und Datenbankverbindungen nehmen.
Bitte definiere einen kompletten Pfad, auf den der Server einen Schreibzugriff hat. Wenn deine Seite unter "/var/www/namederseite/htdocs/" liegt, dann kannst du z.B. einen Ordner unter "/var/www/sitename/temp/" erstellen.
Der Nachteil: Du siehst nicht jede Antwort einer OStatus-Unterhaltung. Aus diesem Grund ist die Option "Beim Empfang von Nachrichten" in der Regel ein guter Kompromiss.
setze "Nutze MySQL full text engine".
Wenn du MyISAM (Standardeinstellung) nutzt, dann beschleunigt dies die Suche.
setze "Pfad zum Eintrag Cache" auf einen leeren Ordner außerhalb deines Stammverzeichnisses.
Verarbeiteter BBCode und einige externe Bilder werden hier gespeichert.
BBCode verarbeiten ist ein zeitintensiver Prozess, der zudem eine hohe CPU-Leistung erfordert.
Du kannst den gleichen Ordner nutzen, den du für die Sperrdatei genutzt hast.
**Warnung!**
Der Ordner für den Eintrag-Cache wird regelmäßig geleert.
Jede Datei, die die Cache-Dauer überschreitet, wird gelöscht. **Wenn du versehentlich den Cache-Pfad auf dein Stammverzeichnis legst, dann würde dir dies das gesamte Stammverzeichnis löschen.**
Prüfe also doppelt, dass der gewählte Ordner nur temporäre Dateien enthält, die jederzeit gelöscht werden können.
Wenn du MyISAM (Standardeinstellung) oder InnoDB mit MariaDB 10 nutzt, dann beschleunigt dies die Suche.
Plugins
--------
Aktiviere die folgenden Plugins:
Alternate Pagination
Privacy Image Cache
rendertime
###Alternate Pagination
**Beschreibung**
Dieses Plugin reduziert die Ladezeit der Datenbank massiv.
Nachteil: Du kannst nicht mehr die Anzahl aller Seiten sehen.
**Einrichtung**
Gehe auf admin/plugins/altpager und wähle "global".
###rendertime
**Beschreibung**
@ -130,14 +93,6 @@ Wenn du Apache nutzt, dann denk darüber nach, FCGI zu nutzen.
Wenn du eine Debian-basierte Distribution nutzt, dann wirst du die Pakete "php5-cgi" und "libapache2-mod-fcgid" benötigen.
Nutze externe Dokumente, um eine detailiertere Erklärung für die Einrichtung eines Systems auf FCGI-Basis zu erhalten.
**APC**
APC ist ein Zwischenspeicher für die Verarbeitung des Befehlscodes.
Es beschleunigt die Verarbeitung des PHP-Codes.
Wenn APC aktiviert ist, dann nutzt Friendica dies, um Konfigurationseinstellungen für verschiedene Anfragen zwischenzuspeichern.
Dies beschleunigt die Reaktionszeit der Seite.
###Database
Es gibt Skripte wie [tuning-primer.sh](http://www.day32.com/MySQL/) und [mysqltuner.pl](http://mysqltuner.pl), die den Datenbankserver analysieren und Hinweise darauf geben, welche Werte verändert werden könnten.

View file

@ -70,6 +70,8 @@ Wir planen, diese Einschränkung in einer zukünftigen Version zu beheben.
3. Erstelle eine leere Datenbank und notiere alle Zugangsdaten (Adresse der Datenbank, Nutzername, Passwort, Datenbankname).
Friendica benötigt die Berechtigungen um neue Felder in dieser Datenbank zu ertellen (create) und zu löschen (delete).
4. Besuche deine Webseite mit deinem Browser und befolge die Anleitung. Bitte beachte jeden Fehler und korrigiere diese, bevor du fortfährst.
5. *Wenn* die automatisierte Installation aus irgendeinem Grund fehlschlägt, dann prüfe das Folgende:

View file

@ -1,12 +1,12 @@
Konnektoren installieren (Facebook/Twitter/StatusNet)
Konnektoren installieren (Twitter/GNU Social)
==================================================
* [Zur Startseite der Hilfe](help)
Friendica nutzt Plugins, um die Verbindung zu anderen Netzwerken wie Facebook und Twitter zu gewährleisten.
Friendica nutzt Plugins, um die Verbindung zu anderen Netzwerken wie Twitter oder App.net zu gewährleisten.
Es gibt außerdem ein Plugin, um über einen bestehenden Status.Net-Account diesen Service zu nutzen.
Du brauchst dieses Plugin aber nicht, um mit Status.Net-Mitgliedern von Friendica aus zu kommunizieren - es sei denn, du wünschst es, über einen existierenden Account einen Beitrag zu schreiben.
Es gibt außerdem ein Plugin, um über einen bestehenden GNU Social-Account diesen Service zu nutzen.
Du brauchst dieses Plugin aber nicht, um mit GNU Social-Mitgliedern von Friendica aus zu kommunizieren - es sei denn, du wünschst es, über einen existierenden Account einen Beitrag zu schreiben.
Alle drei Plugins benötigen einen Account im gewünschten Netzwerk.
Zusätzlich musst du (bzw. der Administrator der Seite) einen API-Schlüssel holen, um einen authentifizierten Zugriff zu deinem Friendica-Server herstellen zu lassen.
@ -47,7 +47,7 @@ $a->config['twitter']['consumersecret'] = 'your consumer_secret here';
Anschließend kann der Nutzer deiner Seite die Twitter-Einstellungen selbst eintragen: "Einstellungen -> Connector Einstellungen".
**StatusNet Plugin für Friendica**
**GNU Social Plugin für Friendica**
* Author: Tobias Diekershoff
* tobias.diekershoff@gmx.net
@ -56,64 +56,29 @@ Anschließend kann der Nutzer deiner Seite die Twitter-Einstellungen selbst eint
Konfiguration
Wenn das Addon aktiv ist, muss der Nutzer die folgenden Einstellungen vornehmen, um sich mit dem StatusNet-Account seiner Wahl zu verbinden.
Wenn das Addon aktiv ist, muss der Nutzer die folgenden Einstellungen vornehmen, um sich mit dem GNU Social-Account seiner Wahl zu verbinden.
* Die Basis-URL des StatusNet-API; für identi.ca ist es https://identi.ca/api/
* Die Basis-URL des GNU Social-API; für quitter.se ist es https://quitter.se/api/
* OAuth Consumer key & Geheimnis
Um das OAuth-Schlüsselpaar zu erhalten, muss der Nutzer
(a) seinen Friendica-Admin fragen, ob bereits ein Schlüsselpaar existiert oder
(b) einen Friendica-Server als Anwendung auf dem StatusNet-Server anmelden.
(b) einen Friendica-Server als Anwendung auf dem GNU Social-Server anmelden.
Dies kann über Einstellungen --> Connections --> "Register an OAuth client application" -> "Register a new application" auf dem StatusNet-Server durchgeführt werden.
Dies kann über Einstellungen --> Connections --> "Register an OAuth client application" -> "Register a new application" auf dem GNU Social-Server durchgeführt werden.
Während der Registrierung des OAuth-Clients ist Folgendes zu beachten:
* Der Anwendungsname muss auf der StatusNet-Seite einzigartig sein, daher empfehlen wir einen Namen wie "friendica-nnnn", ersetze dabei "nnnn" mit einer frei gewählten Nummer oder deinem Webseitennamen.
* Der Anwendungsname muss auf der GNU Social-Seite einzigartig sein, daher empfehlen wir einen Namen wie "friendica-nnnn", ersetze dabei "nnnn" mit einer frei gewählten Nummer oder deinem Webseitennamen.
* es gibt keine Callback-URL
* Registriere einen Desktop-Client
* stelle Lese- und Schreibrechte ein
* die Quell-URL sollte die URL deines Friendica-Servers sein
Sobald die benötigten Daten gespeichert sind, musst du deinen Friendica-Account mit StatusNet verbinden.
Sobald die benötigten Daten gespeichert sind, musst du deinen Friendica-Account mit GNU Social verbinden.
Das kannst du über Einstellungen --> Connector-Einstellungen durchführen.
Folge dem "Einloggen mit StatusNet"-Button, erlaube den Zugriff und kopiere den Sicherheitscode in die entsprechende Box.
Folge dem "Einloggen mit GNU Social"-Button, erlaube den Zugriff und kopiere den Sicherheitscode in die entsprechende Box.
Friendica wird dann versuchen, die abschließende OAuth-Einstellungen über die API zu beziehen.
Wenn es geklappt hat, kannst du in den Einstellungen festlegen, ob deine öffentlichen Nachrichten automatisch in deinem StatusNet-Account erscheinen soll (achte hierbei auf das kleine Schloss-Symbol im Status-Editor)
**Installiere den Friendica/Facebook-Konnektor**
* Registriere einen API-Schlüssel für deine Seite auf [developer.facebook.com](Facebook).
Hierfür benötigst du einen Facebook-Account und ggf. weitere Authentifizierungen über eine Kreditkarten- oder Mobilfunknummer.
a. Wir würden uns sehr darüber freuen, wenn du "Friendica" in dem Anwendungsnamen eintragen würdest, um die Bekanntheit des Namens zu erhöhen. Das Friendica-Icon ist im Bildverzeichnis enthalten und kann als Anwendungs-Icon für die Facebook-App genutzt werden. Nutze [images/friendica-16.jpg](images/friendica-16.jpg) für das Icon und [images/friendica-128.jpg](images/friendica-128.jpg) für das Logo.
b. Die URL sollte deine Seite mit dem abschließenden Schrägstrich sein
Es **kann** notwendig sein, dass du eine "Privacy"- oder "Terms of service"-URL angeben musst.
c. Setze nun noch unter "App Domains" die URL auf deineSubdomain.deineDomain.de und bei "Website with Facebook Login" die URL zu deineDomain.de.
d. Installiere nun das Facebook-Plugin auf deiner Friendica-Seite über "admin/plugins". Du solltest links in der Sidebar einen Facebook-Link unter "Plugin Features" finden. Klicke diesen an.
e. Gib nun die App-ID und das App-Secret ein, die Facebook dir gegeben hat. Ändere die anderen Daten, wie es gewünscht ist.
Auf Friendica kann nun jeder Nutzer, der eine Verbindung zu Facebook wünscht, die Seite "Einstellungen -> Connector-Einstellungen" aufrufen und dort "Installiere Facebook-Connector" auswählen.
Wähle die gewünschten Einstellungen für deine Nutzungs- und Privatsphäreansprüche.
Hier meldest du dich bei Facebook an und gibst dem Plugin die nötigen Zugriffsrechte, um richtig zu funktionieren.
Erlaube dieses.
Und fertig. Um es abzustellen, gehe wieder auf die Einstellungsseite und auf "Remove Facebook posting".
Videos und eingebetteter Code werden nicht gepostet, wenn sonst kein anderer Inhalt enthalten ist.
Links und Bilder werden in ein Format übertragen, das von der Facebook-API verstanden wird.
Lange Texte werden verkürzt und mit einem Link zum Originalbeitrag versehen.
Facebook-Kontakte können außerdem keine privaten Fotos sehen, da diese nicht richtig authentifiziert werden können, wenn sie deine Seite besuchen.
Dieser Fehler wird zukünftig bearbeitet.
Wenn es geklappt hat, kannst du in den Einstellungen festlegen, ob deine öffentlichen Nachrichten automatisch in deinem GNU Social-Account erscheinen soll (achte hierbei auf das kleine Schloss-Symbol im Status-Editor)

View file

@ -41,10 +41,7 @@ Dies wird dich durch einen ähnlichen Prozess leiten.
Du kannst deine oder andere Identitäts-Adressen ebenfalls nutzen, um über verschiedene Netzwerke hinweg Freundschaften aufzubauen.
Die Liste möglicher Netzwerke steigt immer weiter.
Wenn du z.B. "bob" auf identi.ca (eine Status.Net-Seite) kennst, dann kannst du bob@identi.ca auf deiner "Kontakt"-Seite verbinden. (Oder du kannst die URL von Bobs identi.ca-Seite eintragen, wenn du es wünscht).
Du kannst auch "teilweise" mit Leuten auf Google Buzz befreundet sein, wenn du deren GMail-Adresse einträgst.
Google Buzz unterstützt bisher noch nicht alle Protokolle, die wir für die direkte Kommunikation benötigen, aber es sollte möglich sein, Statusupdates von Friendica zu folgen.
Das Gleiche gilt für Twitter- und Diaspora-Accounts.
Wenn du z.B. "bob" auf quitter.se (eine GNU Social-Seite) kennst, dann kannst du bob@quitter.se auf deiner "Kontakt"-Seite verbinden. (Oder du kannst die URL von Bobs quitter.se-Seite eintragen, wenn du es wünscht).
Tatsächlich kannst du jedem und jeder Website folgen, der/die einen Syndication-Feed (RSS/Atom etc.) zur Verfügung stellt.
Wenn wir einen Informationsstrom und einen Namen dazu finden, können wir auch versuchen, uns damit zu verbinden.
@ -52,10 +49,10 @@ Wenn du deine Email-Postfachverbindung auf deiner Einstellungsseite konfiguriert
Du kannst diesen Personen außerdem von Friendica aus antworten.
Leute können sich ebenfalls von anderen Netzwerken aus mit dir befreunden.
Ein Freund von dir hat einen identi.ca-Account und kann sich mit dir befreunden, indem er deine Identitäts-Adresse in seine identi.ca-Verbinden-Dialogbox einträgt.
Ein Freund von dir hat einen GNU Social-Account und kann sich mit dir befreunden, indem er deine Identitäts-Adresse in seine GNU Social-Verbinden-Dialogbox einträgt.
Ein ähnlicher Mechanismus ist für Diaspora-Nutzer vorhanden, indem deine Identitäts-Adresse in ihre Suchleiste eingegeben wird.
Beachte: Manche StatusNet-Versionen benötigen die volle URL deines Profils und funktionieren möglicherweise nicht mit der Identitäts-Adresse.
Beachte: Manche GNU Social-Versionen benötigen die volle URL deines Profils und funktionieren möglicherweise nicht mit der Identitäts-Adresse.
Wenn jemand eine Freundschaftsanfrage schickt, erhältst du eine Benachrichtigung.
Du musst dann diese Anfrage bestätigen, um die Freundschaftsanfrage abzuschließen.

View file

@ -26,7 +26,7 @@ Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all
An deine Friendica Kontakte wird außerdem eine Nachricht gesendet um sie über deine neue Adresse zu informieren.
Wenn deine Kontakte ihren Account auf einem aktuellen Server haben werden deine Kontaktdetails automatisch aktualisiert.
Kontakte auf StatusNet/idendi.ca oder Diaspora werden archiviert, da wir ihnen keine Information über deinen Umzug zukommen lassen können.
Kontakte auf GNU Social oder Diaspora werden archiviert, da wir ihnen keine Information über deinen Umzug zukommen lassen können.
Du solltest sie persönlich anschreiben deinen Eintrag aus ihren Kontaktlisten zu entfernen und dich neu hinzuzufügen, anschließend solltest du da gleiche mit ihren Accounts tun.
Nach dem Umzug wird dein Account auf dem alten Server nicht mehr zuverlässig funktionieren und sollte deshalb gelöscht werden.

View file

@ -138,7 +138,7 @@ Dies erlaubt eine private Kommunikation, die komplett vom globalen Verzeichnis i
Konfiguriere:
```
$a->config['system']['directory_submit_url'] = 'http://dir.friendica.com/submit';
$a->config['system']['directory'] = 'http://dir.friendi.ca';
```

View file

@ -25,7 +25,7 @@ Bitte beachte, dass Friendica eingehende "Erwähnungs"-Nachrichten von Personen
Diese Maßnahme dient dazu, Spam zu vermeiden.
"Fernerwähnungen" werden durch das OStatus-Protokoll übermittelt.
Dieses Protokoll wird von Friendica, StatusNet und anderen Systemen genutzt, ist allerdings derzeit nicht in Diaspora eingebaut.
Dieses Protokoll wird von Friendica, GNU Social und anderen Systemen genutzt, ist allerdings derzeit nicht in Diaspora eingebaut.
Friendica unterscheidet bei Tags nicht zwischen Personen und Gruppen (einige andere Netzwerke nutzen "!gruppe", um solche zu markieren).

61
doc/events.md Normal file
View file

@ -0,0 +1,61 @@
# Events
* [Home](help)
A special form of postings are events.
The events you and your contacts share can be found at [/events](/events) on your node.
To get there go to your wall and follow the tab "events"
Depending on the theme you are using, there might be an additional link from the navigation menu to this page.
## Event Overview
The overview page shows the calendar of the current month, plus eventually some days in the beginning and the end.
Listed are all events for this month you created, or your contacts have shared with you.
This includes birthday reminders for contacts who share their birthday with you.
From the controls, you can switch between month/week/day view.
Flip through the view forwards and backwards.
And return to *today*.
To create a new event, you can either follow the link "Create New Event" or make a double click on the desired box in the calendarium for when the event should take place.
With a click on an existing event a pop-up box will be opened which shows you the event.
From there you can edit the event or view the event at the source link, if you are the one who created the event.
## Create a new Event
Following one of the methods mentioned above you reach a form to enter the event data.
Fields marked with a *** have to be filled.
* **Event Starts**: enter the date/time of the start of the event here
* **Event Finishes**: enter the finishing date/time for the event here
When you click in one of these fields a pop-up will be opened that allows you to pick the day and the time.
If you double clicked on the day box in the calendarium these fields will be pre-filled for you.
The finishing date/time has to be after the beginning date/time of the event.
But you don't have to specify it.
If the event is open-end or the finishing date/time does not matter, just select the box below the two first fields.
* **Adjust for viewer timezone**: If you check this box, the beginning and finisching times will automatically converted to the local time according to the timezone setting
This might prevent too early birthday wishes, or the panic attac that you have forgotten the birthday from your buddy at the other end of the world.
And similar events.
* **Title**: a title for the event
* **Description**: a longer description for the event
* **Location**: the location the event will took place
These three fields describe your events.
In the descirption and location field you can use BBCode to format the text.
* **Share this event**: when this box is checked the ACL will be shown to let you select with whom you wish to share the event. This works just like the controls of any other posting.
When you *Share* the event it will be posted to your wall with the access permissions you've selected.
But before you do, you can also *preview* the event in a pop-up box.
### Addons
#### OpenStreetMap
If this addon is activated on you friendica node, the content of the location field will be mathced with the identification service of OSM when you submit the event.
Should OSM find anything matching, a map for the location will be embedded automatically at the end of the events view.

View file

@ -29,11 +29,11 @@ Friendica Documentation and Resources
* [Install](help/Install)
* [Settings](help/Settings)
* [Plugins](help/Plugins)
* [Installing Connectors (Facebook/Twitter/StatusNet)](help/Installing-Connectors)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Message Flow](help/Message-Flow)
* [Using SSL with Friendica](help/SSL)
* [Developers](help/Developers)
* [Twitter/StatusNet API Functions](help/api)
* [Twitter/GNU Social API Functions](help/api)
* [Translation of Friendica](help/translations)

291
doc/themes.md Normal file
View file

@ -0,0 +1,291 @@
# Themes
* [Home](help)
To change the look of friendica you have to touch the themes.
The current default theme is [duepunto zero](https://github.com/friendica/friendica/tree/master/view/theme/duepuntozero) but there are numerous others.
Have a look at [friendica-themes.com](http://friendica-themes.com) for an overview of the existing themes.
In case none of them suits your needs, there are several ways to change a theme.
If you need help theming, there is a forum @[ftdevs@friendica.eu](https://friendica.eu/profile/ftdevs) where you can ask theme specific questions and present your themes.
So, how to work on the UI of friendica.
You can either directly edit an existing theme.
But you might loose your changes when the theme is updated by the friendica team.
If you are almost happy with an existing theme, the easiest way to cover your needs is to create a new theme, inheritating most of the properties of the parent theme and change just minor stuff.
The below for a more detailed description of theme heritage.
Some themes also allow users to select *variants* of the theme.
Those theme variants most often contain an additional [CSS](https://en.wikipedia.org/wiki/CSS) file to override some styling of the default theme values.
From the themes in the main repository *duepunto zero* and *vier* are using this methods for variations.
Quattro is using a slightly different approach.
Third you can start your theme from scratch.
Which is the most complex way to change friendicas look.
But it leaves you the most freedom.
So below for a *detailed* description and the meaning of some special files.
### Styling
If you want to change the styling of a theme, have a look at the themes CSS file.
In most cases, you can found these in
/view/theme/**your-theme-name**/style.css
sometimes, there is also a file called style.php in the theme directory.
This is only needed if the theme allowes the user to change certain things of the theme dynamically.
Say the font size or set a background image.
### Templates
If you want to change the structure of the theme, you need to change the templates used by the theme.
Friendica themes are using [SMARTY3](http://www.smarty.net/) for templating.
The default template can be found in
/view/templates
if you want to override any template within your theme create your version of the template in
/view/theme/**your-theme-name**/templates
any template that exists there will be used instead of the default one.
### Javascript
The same rule applies to the JavaScript files found in
/js
they will be overwritten by files in
/view/theme/**your-theme-name**/js.
## Expand an existing Theme
### Theme Variations
Many themes are more *theme families* then only one theme.
*duepunto zero* and *vier* allow easily to add new theme variation.
We will go through the process of creating a new variation for *duepunto zero*.
The same (well almost, some names change) procedure applies to the *vier* theme.
And similar steps are needed for *quattro* but this theme is using [lessc](http://lesscss.org/#docs) to maintaine the CSS files..
In
/view/theme/duepuntozero/deriv
you find a couple of CSS files that define color derivations from the duepunto theme.
These resemble some of the now as unsupported marked themes, that were inherited by the duepunto theme.
Darkzero and Easter Bunny for example.
The selection of the colorset is done in a combination of a template for a new form in the settings and aome functions in the theme.php file.
The template (theme_settings.tpl)
{{include file="field_select.tpl" field=$colorset}}
<div class="settings-submit-wrapper">
<input type="submit" value="{{$submit}}" class="settings-submit" name="duepuntozero-settings-submit" />
</div>
defines a formular consisting of a [select](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) pull-down which contains all aviable variants and s submit button.
See the documentation about [SMARTY3 templates](/help/snarty3-templates.md) for a summary of friendica specific blocks other then the select element.
But we don't really need to change anything at the template itself.
The template alone wont work though.
You make friendica aware of its existance and tell it how to use the template file, by defining a config.php file.
It needs to define at lest the following functions
* theme_content
* theme_post
and may also define functions for the admin interface
* theme_admin
* theme_admin_post.
theme_content and theme_admin are used to make the form available in the settings, repectively the admin panel.
The _post functions handle the processing of the send form, in this case they save to selected variand in friendicas database.
To make your own variation appear in the menu, all you need to do is to create a new CSS file in the deriv directoy and include it in the array in the config.php:
$colorset = array(
'default'=>t('default'),
'greenzero'=>t('greenzero'),
'purplezero'=>t('purplezero'),
'easterbunny'=>t('easterbunny'),
'darkzero'=>t('darkzero'),
'comix'=>t('comix'),
'slackr'=>t('slackr'),
);
the 1st part of the line is the name of the CSS file (without the .css) the 2nd part is the common name of the variant.
Calling the t() function with the common name makes the string translateable.
The selected 1st part will be saved in the database by the theme_post function.
function theme_post(&$a){
// non local users shall not pass
if(! local_user())
return;
// if the one specific submit button was pressed then proceed
if (isset($_POST['duepuntozero-settings-submit'])){
// and save the selection key into the personal config of the user
set_pconfig(local_user(), 'duepuntozero', 'colorset', $_POST['duepuntozero_colorset']);
}
}
Now that this information is set in the database, what should friendica do with it?
For this, have a look at the theme.php file of the *duepunto zero*.
There you'll find somethink alike
$colorset = get_pconfig( local_user(), 'duepuntozero','colorset');
if (!$colorset)
$colorset = get_config('duepuntozero', 'colorset');
if ($colorset) {
if ($colorset == 'greenzero')
$a->page['htmlhead'] .= '<link rel="stylesheet" href="view/theme/duepuntozero/deriv/greenzero.css" type="text/css" media="screen" />'."\n";
/* some more variants */
}
which tells friendica to get the personal config of a user.
Check if it is set and if not look for the global config.
And finally if a config for the colorset was found, apply it by adding a link to the CSS file into the HTML header of the page.
So you'll just need to add a if selection, fitting your variant keyword and link to the CSS file of it.
Done.
Now you can use the variant on your system.
But remember once the theme.php or the config.php you have to readd your variant to them.
If you think your color variation could be benifical for other friendica users as well, feel free to generate a pull request at github so we can include your work into the repository.
### Inheritation
Say, you like the duepuntozero but you want to have the content of the outer columns left and right exchanged.
That would be not a color variation as shown above.
Instead we will create a new theme, duepuntozero_lr, inherit the properties of duepuntozero and make small changes to the underlying php files.
So create a directory called duepunto_lr and create a file called theme.php with your favorite text editor.
The content of this file should be something like
<?php
/* meta informations for the theme, see below */
function duepuntozero_lr_init(&$a) {
$a-> theme_info = array(
'extends' => 'duepuntozero'.
);
set_template_engine($a, 'smarty3');
/* and more stuff e.g. the JavaScript function for the header */
}
Next take the default.php file found in the /view direcotry and exchange the aside and right_aside elements.
So the central part of the file now looks like this:
<body>
<?php if(x($page,'nav')) echo $page['nav']; ?>
<aside><?php if(x($page,'right_aside')) echo $page['right_aside']; ?></aside>
<section><?php if(x($page,'content')) echo $page['content']; ?>
<div id="page-footer"></div>
</section>
<right_aside><?php if(x($page,'aside')) echo $page['aside']; ?></right_aside>
<footer><?php if(x($page,'footer')) echo $page['footer']; ?></footer>
</body>
Finally we need a style.css file, inheriting the definitions from the parent theme and containing out changes for the new theme.
***Note***:You need to create the style.css and at lest import the base CSS file from the parent theme.
@import url('../duepuntozero/style.css');
Done.
But I agree it is not really useful at this state.
Nevertheless, to use it, you just need to activate in the admin panel.
That done, you can select it in the settings like any other activated theme.
## Creating a Theme from Scratch
Keep patient.
Basically what you have to do is identifying which template you have to change so it looks more like what you want.
Adopt the CSS of the theme accordingly.
And iterate the process until you have the theme the way you want it.
*Use the source Luke.* and don't hesitate to ask in @[ftdevs](https://friendica.eu/profile/ftdevs) or @[helpers](https://helpers.pyxis.uberspace.de/profile/helpers).
## Special Files
### unsupported
If a file with this name (which might be empty) exists in the theme directory, the theme is marked as *unsupported*.
An unsupported theme may not be selected by a user in the settings.
Users who are already using it wont notice anything.
### README(.md)
The contents of this file, with or without the .md which indicates [Markdown](https://daringfireball.net/projects/markdown/) syntax, will be displayed at most repository hosting services and in the theme page within the admin panel of friendica.
This file should contain information you want to let others know about your theme.
### screenshot.[png|jpg]
If you want to have a preview image of your theme displayed in the settings you should take a screenshot and save it with this name.
Supported formats are PNG and JPEG.
### theme.php
This is the main definition file of the theme.
In the header of that file, some meta information are stored.
For example, have a look at the theme.php of the *quattro* theme:
<?php
/**
* Name: Quattro
* Version: 0.6
* Author: Fabio <http://kirgroup.com/profile/fabrixxm>
* Maintainer: Fabio <http://kirgroup.com/profile/fabrixxm>
* Maintainer: Tobias <https://f.diekershoff.de/profile/tobias>
*/
You see the definition of the themes name, it's version and the initial author of the theme.
These three information should be listed.
If the original author is not anymore working on the theme, but a maintainer has taken over, the maintainer should be listed as well.
The information from the theme header will be displayed in the admin panelö.
Next crucial part of the theme.php file is a definition of an init function.
The name of the function is <theme-name>_init.
So in the case of quattro it is
function quattro_init(&$a) {
$a->theme_info = array();
set_template_engine($a, 'smarty3');
}
Here we have set the basic theme information, in this case they are empthy.
But the array needs to be set.
And we have set the template engine that should be used by friendica for this theme.
At the moment you should use the *smarty3* engine.
There once was a friendica specific templating engine as well but that is not used anymore.
If you like to use another templating engine, please implement it.
When you want to inherit stuff from another theme you have to *announce* this in the theme_info:
$a->theme_info = array(
'extends' => 'duepuntozero',
);
which declares *duepuntozero* as parent of the theme.
If you want to add something to the HTML header of the theme, one way to do so is by adding it to the theme.php file.
To do so, add something alike
$a->page['htmlhead'] .= <<< EOT
/* stuff you want to add to the header */
EOT;
The $a variable holds the friendica application.
So you can access the properties of this friendica session from the theme.php file as well.
### default.php
This file covers the structure of the underlying HTML layout.
The default file is in
/view/default.php
if you want to change it, say adding a 4th column for banners of your favourite FLOSS projects, place a new default.php file in your theme directory.
As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed.

View file

@ -51,12 +51,6 @@ $a->config['system']['maximagesize'] = 800000;
$a->config['php_path'] = 'php';
// You shouldn't need to change anything else.
// Location of global directory submission page.
$a->config['system']['directory_submit_url'] = 'http://dir.friendica.com/submit';
$a->config['system']['directory_search_url'] = 'http://dir.friendica.com/directory?search=';
// PuSH - aka pubsubhubbub URL. This makes delivery of public posts as fast as private posts
$a->config['system']['huburl'] = '[internal]';
@ -74,21 +68,8 @@ $a->config['system']['theme'] = 'duepuntozero';
$a->config['system']['no_regfullname'] = true;
// If set to true the priority settings of ostatus contacts are used
$a->config['system']['ostatus_use_priority'] = false;
// If enabled, all items are cached in the given directory
$a->config['system']['itemcache'] = "";
// If enabled, the lockpath is used for a lockfile to check if the poller is running
$a->config['system']['lockpath'] = "";
// If enabled, the MyBB fulltext engine is used
// $a->config['system']['use_fulltext_engine'] = true;
// Use the old style "share"
// $a->config['system']['old_share'] = false;
//Deny public access to the local directory
//$a->config['system']['block_local_dir'] = false;
// Location of the global directory
$a->config['system']['directory'] = 'http://dir.friendi.ca';

View file

@ -113,7 +113,7 @@ function terminate_friendship($user,$self,$contact) {
'$photo' => $self['photo'],
'$thumb' => $self['thumb'],
'$published' => datetime_convert('UTC','UTC', 'now', ATOM_TIME),
'$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':unfollow:' . random_string(),
'$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':unfollow:' . get_guid(32),
'$title' => '',
'$type' => 'text',
'$content' => t('stopped following'),
@ -267,7 +267,12 @@ function contact_photo_menu($contact) {
function random_profile() {
$r = q("select url from gcontact where url like '%%://%%/profile/%%' order by rand() limit 1");
$r = q("SELECT `url` FROM `gcontact` WHERE `network` = '%s'
AND `last_contact` >= `last_failure`
AND `updated` > UTC_TIMESTAMP - INTERVAL 1 MONTH
ORDER BY rand() LIMIT 1",
dbesc(NETWORK_DFRN));
if(count($r))
return dirname($r[0]['url']);
return '';

View file

@ -262,47 +262,40 @@ function scrape_feed($url) {
}
}
try {
$dom = HTML5_Parser::parse($s);
} catch (DOMException $e) {
logger('scrape_feed: parse error: ' . $e);
}
if(! $dom) {
logger('scrape_feed: failed to parse.');
return $ret;
}
$head = $dom->getElementsByTagName('base');
if($head) {
foreach($head as $head0) {
$basename = $head0->getAttribute('href');
break;
}
}
if(! $basename)
$basename = implode('/', array_slice(explode('/',$url),0,3)) . '/';
$items = $dom->getElementsByTagName('link');
$doc = new DOMDocument();
@$doc->loadHTML($s);
$xpath = new DomXPath($doc);
// get Atom/RSS link elements, take the first one of either.
$base = $xpath->query("//base");
foreach ($base as $node) {
$attr = array();
if($items) {
foreach($items as $item) {
$x = $item->getAttribute('rel');
if(($x === 'alternate') && ($item->getAttribute('type') === 'application/atom+xml')) {
if(! x($ret,'feed_atom'))
$ret['feed_atom'] = $item->getAttribute('href');
}
if(($x === 'alternate') && ($item->getAttribute('type') === 'application/rss+xml')) {
if(! x($ret,'feed_rss'))
$ret['feed_rss'] = $item->getAttribute('href');
}
}
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
if ($attr["href"] != "")
$basename = $attr["href"] ;
}
// Drupal and perhaps others only provide relative URL's. Turn them into absolute.
$list = $xpath->query("//link");
foreach ($list as $node) {
$attr = array();
if ($node->attributes->length)
foreach ($node->attributes as $attribute)
$attr[$attribute->name] = $attribute->value;
if (($attr["rel"] == "alternate") AND ($attr["type"] == "application/atom+xml"))
$ret["feed_atom"] = $attr["href"];
if (($attr["rel"] == "alternate") AND ($attr["type"] == "application/rss+xml"))
$ret["feed_rss"] = $attr["href"];
}
// Drupal and perhaps others only provide relative URLs. Turn them into absolute.
if(x($ret,'feed_atom') && (! strstr($ret['feed_atom'],'://')))
$ret['feed_atom'] = $basename . $ret['feed_atom'];
@ -509,6 +502,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
}
if($mode == PROBE_NORMAL) {
if(strlen($zot)) {
$s = fetch_url($zot);
if($s) {
@ -528,6 +522,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
}
}
if(strlen($dfrn)) {
$ret = scrape_dfrn(($hcard) ? $hcard : $dfrn);
if(is_array($ret) && x($ret,'dfrn-request')) {
@ -634,6 +629,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if($check_feed) {
$feedret = scrape_feed(($poll) ? $poll : $url);
logger('probe_url: scrape_feed ' . (($poll)? $poll : $url) . ' returns: ' . print_r($feedret,true), LOGGER_DATA);
if(count($feedret) && ($feedret['feed_atom'] || $feedret['feed_rss'])) {
$poll = ((x($feedret,'feed_atom')) ? unamp($feedret['feed_atom']) : unamp($feedret['feed_rss']));
@ -823,7 +819,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
}
}
Cache::set("probe_url:".$mode.":".$url,serialize($result));
// Only store into the cache if the value seems to be valid
if ($result['network'] != NETWORK_FEED)
Cache::set("probe_url:".$mode.":".$url,serialize($result), CACHE_DAY);
return $result;
}

View file

@ -9,6 +9,14 @@
require_once("include/html2plain.php");
require_once("mod/share.php");
require_once("include/Photo.php");
require_once("mod/item.php");
require_once('include/security.php');
require_once('include/contact_selectors.php');
require_once('include/html2bbcode.php');
require_once('mod/wall_upload.php');
require_once("mod/proxy.php");
require_once("include/message.php");
/*
* Twitter-Like API
@ -151,7 +159,6 @@
die('This api requires login');
}
require_once('include/security.php');
authenticate_success($record); $_SESSION["allow_api"] = true;
call_hooks('logged_in', $a->user);
@ -185,7 +192,11 @@
if (strpos($a->query_string, ".atom")>0) $type="atom";
if (strpos($a->query_string, ".as")>0) $type="as";
$stamp = microtime(true);
$r = call_user_func($info['func'], $a, $type);
$duration = (float)(microtime(true)-$stamp);
logger("API call duration: ".round($duration, 2)."\t".$a->query_string, LOGGER_DEBUG);
if ($r===false) return;
switch($type){
@ -504,8 +515,7 @@
$r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($uinfo[0]['url'])));
}
require_once('include/contact_selectors.php');
$network_name = network_to_name($uinfo[0]['network']);
$network_name = network_to_name($uinfo[0]['network'], $uinfo[0]['url']);
$ret = Array(
'id' => intval($r[0]['id']),
@ -686,10 +696,10 @@
$txt = requestdata('status');
//$txt = urldecode(requestdata('status'));
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
if((strpos($txt,'<') !== false) || (strpos($txt,'>') !== false)) {
require_once('library/HTMLPurifier.auto.php');
$txt = html2bb_video($txt);
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.DefinitionImpl', null);
@ -701,12 +711,10 @@
$a->argv[1]=$user_info['screen_name']; //should be set to username?
$_REQUEST['hush']='yeah'; //tell wall_upload function to return img info instead of echo
require_once('mod/wall_upload.php');
$bebop = wall_upload_post($a);
//now that we have the img url in bbcode we can add it to the status and insert the wall item.
$_REQUEST['body']=$txt."\n\n".$bebop;
require_once('mod/item.php');
item_post($a);
// this should output the last post (the one we just posted).
@ -729,18 +737,16 @@
// logger('api_post: ' . print_r($_POST,true));
if(requestdata('htmlstatus')) {
require_once('library/HTMLPurifier.auto.php');
require_once('include/html2bbcode.php');
$txt = requestdata('htmlstatus');
if((strpos($txt,'<') !== false) || (strpos($txt,'>') !== false)) {
require_once('library/HTMLPurifier.auto.php');
$txt = html2bb_video($txt);
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.DefinitionImpl', null);
$purifier = new HTMLPurifier($config);
$txt = $purifier->purify($txt);
@ -753,6 +759,11 @@
$_REQUEST['title'] = requestdata('title');
$parent = requestdata('in_reply_to_status_id');
// Twidere sends "-1" if it is no reply ...
if ($parent == -1)
$parent = "";
if(ctype_digit($parent))
$_REQUEST['parent'] = $parent;
else
@ -829,7 +840,6 @@
if(x($_FILES,'media')) {
// upload the image if we have one
$_REQUEST['hush']='yeah'; //tell wall_upload function to return img info instead of echo
require_once('mod/wall_upload.php');
$media = wall_upload_post($a);
if(strlen($media)>0)
$_REQUEST['body'] .= "\n\n".$media;
@ -856,7 +866,6 @@
// call out normal post function
require_once('mod/item.php');
item_post($a);
// this should output the last post (the one we just posted).
@ -879,7 +888,6 @@
return false;
}
require_once('mod/wall_upload.php');
$media = wall_upload_post($a, false);
if(!$media) {
// Output error
@ -996,9 +1004,9 @@
$status_info["entities"] = $converted["entities"];
if (($lastwall['item_network'] != "") AND ($status["source"] == 'web'))
$status_info["source"] = network_to_name($lastwall['item_network']);
elseif (($lastwall['item_network'] != "") AND (network_to_name($lastwall['item_network']) != $status_info["source"]))
$status_info["source"] = trim($status_info["source"].' ('.network_to_name($lastwall['item_network']).')');
$status_info["source"] = network_to_name($lastwall['item_network'], $user_info['url']);
elseif (($lastwall['item_network'] != "") AND (network_to_name($lastwall['item_network'], $user_info['url']) != $status_info["source"]))
$status_info["source"] = trim($status_info["source"].' ('.network_to_name($lastwall['item_network'], $user_info['url']).')');
// "uid" and "self" are only needed for some internal stuff, so remove it from here
unset($status_info["user"]["uid"]);
@ -1095,9 +1103,9 @@
$user_info["status"]["entities"] = $converted["entities"];
if (($lastwall['item_network'] != "") AND ($user_info["status"]["source"] == 'web'))
$user_info["status"]["source"] = network_to_name($lastwall['item_network']);
if (($lastwall['item_network'] != "") AND (network_to_name($lastwall['item_network']) != $user_info["status"]["source"]))
$user_info["status"]["source"] = trim($user_info["status"]["source"].' ('.network_to_name($lastwall['item_network']).')');
$user_info["status"]["source"] = network_to_name($lastwall['item_network'], $user_info['url']);
if (($lastwall['item_network'] != "") AND (network_to_name($lastwall['item_network'], $user_info['url']) != $user_info["status"]["source"]))
$user_info["status"]["source"] = trim($user_info["status"]["source"].' ('.network_to_name($lastwall['item_network'], $user_info['url']).')');
}
@ -1480,7 +1488,6 @@
if (!x($_REQUEST, "source"))
$_REQUEST["source"] = api_source();
require_once('mod/item.php');
item_post($a);
}
@ -1512,7 +1519,6 @@
$ret = api_statuses_show($a, $type);
require_once('include/items.php');
drop_item($id, false);
return($ret);
@ -1976,7 +1982,6 @@
$include_entities = strtolower(x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:"false");
if ($include_entities != "true") {
require_once("mod/proxy.php");
preg_match_all("/\[img](.*?)\[\/img\]/ism", $bbcode, $images);
@ -2079,7 +2084,6 @@
// If image cache is activated, then use the following sizes:
// thumb (150), small (340), medium (600) and large (1024)
if (!get_config("system", "proxy_disabled")) {
require_once("mod/proxy.php");
$media_url = proxy_url($url);
$sizes = array();
@ -2214,9 +2218,9 @@
$status["entities"] = $converted["entities"];
if (($item['item_network'] != "") AND ($status["source"] == 'web'))
$status["source"] = network_to_name($item['item_network']);
else if (($item['item_network'] != "") AND (network_to_name($item['item_network']) != $status["source"]))
$status["source"] = trim($status["source"].' ('.network_to_name($item['item_network']).')');
$status["source"] = network_to_name($item['item_network'], $user_info['url']);
else if (($item['item_network'] != "") AND (network_to_name($item['item_network'], $user_info['url']) != $status["source"]))
$status["source"] = trim($status["source"].' ('.network_to_name($item['item_network'], $user_info['url']).')');
// Retweets are only valid for top postings
@ -2471,8 +2475,6 @@
$sender = api_get_user($a);
require_once("include/message.php");
if ($_POST['screen_name']) {
$r = q("SELECT `id`, `nurl`, `network` FROM `contact` WHERE `uid`=%d AND `nick`='%s'",
intval(api_user()),

View file

@ -34,6 +34,15 @@ function diaspora2bb($s) {
$s = str_replace('&#35;','#',$s);
$search = array(" \n", "\n ");
$replace = array("\n", "\n");
do {
$oldtext = $s;
$s = str_replace($search, $replace, $s);
} while ($oldtext != $s);
$s = str_replace("\n\n", "<br>", $s);
$s = html2bbcode($s);
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands

View file

@ -268,6 +268,13 @@ function stripcode_br_cb($s) {
return '[code]' . str_replace('<br />', '', $s[1]) . '[/code]';
}
function bb_onelinecode_cb($match) {
if (strpos($match[1],"<br>")===false){
return "<key>".$match[1]."</key>";
}
return "<code>".$match[1]."</code>";
}
function tryoembed($match){
//$url = ((count($match)==2)?$match[1]:$match[2]);
$url = $match[1];
@ -887,8 +894,12 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$MAILSearchString = $URLSearchString;
// Remove all hashtag addresses
if ((!$tryoembed OR $simplehtml) AND ($simplehtml != 7))
if ((!$tryoembed OR $simplehtml) AND !in_array($simplehtml, array(3, 7)))
$Text = preg_replace("/([#@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '$1$3', $Text);
elseif ($simplehtml == 3)
$Text = preg_replace("/([@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<a href="$2">$3</a>',
$Text);
elseif ($simplehtml == 7)
$Text = preg_replace("/([@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<span class="vcard"><a href="$2" class="url" title="$3"><span class="fn nickname mention">$3</span></a></span>',
@ -1189,6 +1200,10 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$Text = preg_replace("/\[event\-adjust\](.*?)\[\/event\-adjust\]/ism",'',$Text);
}
//replace oneliner <code> with <key>
$Text = preg_replace_callback("|(?!<br[^>]*>)<code>([^<]*)</code>(?!<br[^>]*>)|ism", 'bb_onelinecode_cb', $Text);
// Unhide all [noparse] contained bbtags unspacefying them
// and triming the [noparse] tag.
@ -1203,7 +1218,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
// fix any escaped ampersands that may have been converted into links
$Text = preg_replace("/\<([^>]*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text);
$Text = preg_replace("/\<([^>]*?)(src|href)=\"(?!http|ftp|mailto|cid)(.*?)\>/ism",'<$1$2="">',$Text);
$Text = preg_replace("/\<([^>]*?)(src|href)=\"(?!http|ftp|mailto|gopher|cid)(.*?)\>/ism",'<$1$2="">',$Text);
if($saved_image)
$Text = bb_replace_images($Text, $saved_image);

View file

@ -5,33 +5,25 @@
class Cache {
public static function get($key) {
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($key))
return(apc_fetch($key));*/
$r = q("SELECT `v` FROM `cache` WHERE `k`='%s' limit 1",
dbesc($key)
);
if (count($r)) {
/*if (function_exists("apc_store"))
apc_store($key, $r[0]['v'], 600);*/
if (count($r))
return $r[0]['v'];
}
return null;
}
public static function set($key,$value) {
public static function set($key,$value, $duration = CACHE_MONTH) {
q("REPLACE INTO `cache` (`k`,`v`,`updated`) VALUES ('%s','%s','%s')",
q("REPLACE INTO `cache` (`k`,`v`,`expire_mode`,`updated`) VALUES ('%s','%s',%d,'%s')",
dbesc($key),
dbesc($value),
intval($duration),
dbesc(datetime_convert()));
/*if (function_exists("apc_store"))
apc_store($key, $value, 600);*/
}
@ -63,8 +55,17 @@
public static function clear(){
q("DELETE FROM `cache` WHERE `updated` < '%s'",
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
dbesc(datetime_convert('UTC','UTC',"now - 30 days")), intval(CACHE_MONTH));
q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
dbesc(datetime_convert('UTC','UTC',"now - 7 days")), intval(CACHE_WEEK));
q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
dbesc(datetime_convert('UTC','UTC',"now - 1 days")), intval(CACHE_DAY));
q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
dbesc(datetime_convert('UTC','UTC',"now - 1 hours")), intval(CACHE_HOUR));
}
}

View file

@ -1,5 +1,5 @@
<?php
require_once('include/diaspora.php');
function contact_profile_assign($current,$foreign_net) {
@ -70,7 +70,7 @@ function contact_poll_interval($current, $disabled = false) {
}
function network_to_name($s) {
function network_to_name($s, $profile = "") {
$nets = array(
NETWORK_DFRN => t('Friendica'),
@ -97,6 +97,10 @@ function network_to_name($s) {
$search = array_keys($nets);
$replace = array_values($nets);
return str_replace($search,$replace,$s);
$networkname = str_replace($search,$replace,$s);
if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora_is_redmatrix($profile))
$networkname = t("Redmatrix");
return $networkname;
}

View file

@ -892,9 +892,9 @@ function item_photo_menu($item){
foreach($menu as $k=>$v){
if(strpos($v,'javascript:') === 0) {
$v = substr($v,11);
$o .= "<li><a href=\"#\" onclick=\"$v\">$k</a></li>\n";
$o .= "<li role=\"menuitem\"><a onclick=\"$v\">$k</a></li>\n";
}
elseif ($v!="") $o .= "<li><a href=\"$v\">$k</a></li>\n";
elseif ($v!="") $o .= "<li role=\"menuitem\"><a href=\"$v\">$k</a></li>\n";
}
return $o;
}}

View file

@ -364,6 +364,7 @@ function db_definition() {
"fields" => array(
"k" => array("type" => "varchar(255)", "not null" => "1", "primary" => "1"),
"v" => array("type" => "text", "not null" => "1"),
"expire_mode" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"updated" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
@ -451,6 +452,7 @@ function db_definition() {
"hub-verify" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"last-update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"success_update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"failure_update" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"name-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"uri-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"avatar-date" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
@ -625,21 +627,28 @@ function db_definition() {
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nick" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"connect" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"updated" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_contact" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_failure" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"location" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"about" => array("type" => "text", "not null" => "1"),
"keywords" => array("type" => "text", "not null" => "1"),
"gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"community" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"network" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"generation" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
"server_url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
),
"indexes" => array(
"PRIMARY" => array("id"),
"nurl" => array("nurl"),
"updated" => array("updated"),
)
);
$database["glink"] = array(
@ -683,6 +692,29 @@ function db_definition() {
"uid_gid_contactid" => array("uid","gid","contact-id"),
)
);
$database["gserver"] = array(
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"nurl" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"version" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"site_name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"info" => array("type" => "text", "not null" => "1"),
"register_policy" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"poco" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"noscrape" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"platform" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"last_poco_query" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_contact" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
"last_failure" => array("type" => "datetime", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
"PRIMARY" => array("id"),
"nurl" => array("nurl"),
)
);
$database["guid"] = array(
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),

124
include/diaspora.php Executable file → Normal file
View file

@ -1,5 +1,10 @@
<?php
/*
To-Do:
- GET /people/9aed8882b9f64896/stream
*/
require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/bb2diaspora.php');
@ -17,6 +22,12 @@ function diaspora_dispatch_public($msg) {
return;
}
// Use a dummy importer to import the data for the public copy
$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
$result = diaspora_dispatch($importer,$msg);
logger("Dispatcher reported ".$result, LOGGER_DEBUG);
// Now distribute it to the followers
$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' )
AND `account_expired` = 0 AND `account_removed` = 0 ",
@ -30,7 +41,7 @@ function diaspora_dispatch_public($msg) {
}
}
else
logger('diaspora_public: no subscribers');
logger('diaspora_public: no subscribers for '.$msg["author"].' '.print_r($msg, true));
}
@ -578,7 +589,7 @@ function diaspora_request($importer,$xml) {
// perhaps we were already sharing with this person. Now they're sharing with us.
// That makes us friends.
if($contact['rel'] == CONTACT_IS_FOLLOWER && $importer['page-flags'] != PAGE_COMMUNITY) {
if($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) {
q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
intval(CONTACT_IS_FRIEND),
intval($contact['id']),
@ -755,12 +766,12 @@ function diaspora_request($importer,$xml) {
return;
}
function diaspora_post_allow($importer,$contact) {
function diaspora_post_allow($importer,$contact, $is_comment = false) {
// perhaps we were already sharing with this person. Now they're sharing with us.
// That makes us friends.
// Normally this should have handled by getting a request - but this could get lost
if($contact['rel'] == CONTACT_IS_FOLLOWER && $importer['page-flags'] != PAGE_COMMUNITY) {
if($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) {
q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
intval(CONTACT_IS_FRIEND),
intval($contact['id']),
@ -775,8 +786,13 @@ function diaspora_post_allow($importer,$contact) {
if($contact['rel'] == CONTACT_IS_SHARING || $contact['rel'] == CONTACT_IS_FRIEND)
return true;
if($contact['rel'] == CONTACT_IS_FOLLOWER)
if($importer['page-flags'] == PAGE_COMMUNITY)
if(($importer['page-flags'] == PAGE_COMMUNITY) OR $is_comment)
return true;
// Messages for the global users are always accepted
if ($importer['uid'] == 0)
return true;
return false;
}
@ -818,23 +834,24 @@ function diaspora_post($importer,$xml,$msg) {
}
$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
if(! $contact)
return;
if(! $contact) {
logger('diaspora_post: A Contact for handle '.$diaspora_handle.' and user '.$importer['uid'].' was not found');
return 203;
}
if(! diaspora_post_allow($importer,$contact)) {
if(! diaspora_post_allow($importer,$contact, false)) {
logger('diaspora_post: Ignoring this author.');
return 202;
}
$message_id = $diaspora_handle . ':' . $guid;
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1",
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
intval($importer['uid']),
dbesc($message_id),
dbesc($guid)
);
if(count($r)) {
logger('diaspora_post: message exists: ' . $guid);
return;
return 208;
}
$created = unxmlify($xml->created_at);
@ -900,7 +917,9 @@ function diaspora_post($importer,$xml,$msg) {
DiasporaFetchGuid($datarray);
$message_id = item_store($datarray);
return;
logger("Stored item with message id ".$message_id, LOGGER_DEBUG);
return 201;
}
@ -944,9 +963,8 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) {
$objecttype = $item["object-type"];
$message_id = $author.':'.$guid;
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1",
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
intval($uid),
dbesc($message_id),
dbesc($guid)
);
if(count($r))
@ -954,9 +972,21 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) {
$person = find_diaspora_person_by_handle($author);
$contact_id = get_contact($person['url'], $uid);
$contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
$importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid));
if ($contacts AND $importers)
if(!diaspora_post_allow($importers[0],$contacts[0], false)) {
logger('Ignoring author '.$person['url'].' for uid '.$uid);
return false;
} else
logger('Author '.$person['url'].' is allowed for uid '.$uid);
$datarray = array();
$datarray['uid'] = $uid;
$datarray['contact-id'] = get_contact($person['url'], $uid);
$datarray['contact-id'] = $contact_id;
$datarray['wall'] = 0;
$datarray['network'] = NETWORK_DIASPORA;
$datarray['guid'] = $guid;
@ -1096,15 +1126,14 @@ function diaspora_reshare($importer,$xml,$msg) {
if(! $contact)
return;
if(! diaspora_post_allow($importer,$contact)) {
if(! diaspora_post_allow($importer,$contact, false)) {
logger('diaspora_reshare: Ignoring this author: ' . $diaspora_handle . ' ' . print_r($xml,true));
return 202;
}
$message_id = $diaspora_handle . ':' . $guid;
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1",
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
intval($importer['uid']),
dbesc($message_id),
dbesc($guid)
);
if(count($r)) {
@ -1282,15 +1311,14 @@ function diaspora_asphoto($importer,$xml,$msg) {
if(! $contact)
return;
if(! diaspora_post_allow($importer,$contact)) {
if(! diaspora_post_allow($importer,$contact, false)) {
logger('diaspora_asphoto: Ignoring this author.');
return 202;
}
$message_id = $diaspora_handle . ':' . $guid;
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `guid` = '%s' LIMIT 1",
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
intval($importer['uid']),
dbesc($message_id),
dbesc($guid)
);
if(count($r)) {
@ -1378,7 +1406,7 @@ function diaspora_comment($importer,$xml,$msg) {
return;
}
if(! diaspora_post_allow($importer,$contact)) {
if(! diaspora_post_allow($importer,$contact, true)) {
logger('diaspora_comment: Ignoring this author.');
return 202;
}
@ -1770,7 +1798,7 @@ function diaspora_message($importer,$xml,$msg) {
$msg_diaspora_handle = notags(unxmlify($xml->diaspora_handle));
$msg_conversation_guid = notags(unxmlify($xml->conversation_guid));
$parent_uri = $diaspora_handle . ':' . $msg_parent_guid;
$parent_uri = $msg_diaspora_handle . ':' . $msg_parent_guid;
$contact = diaspora_get_contact_by_handle($importer['uid'],$msg_diaspora_handle);
if(! $contact) {
@ -1882,7 +1910,7 @@ function diaspora_photo($importer,$xml,$msg,$attempt=1) {
return;
}
if(! diaspora_post_allow($importer,$contact)) {
if(! diaspora_post_allow($importer,$contact, false)) {
logger('diaspora_photo: Ignoring this author.');
return 202;
}
@ -1969,7 +1997,7 @@ function diaspora_like($importer,$xml,$msg) {
return;
}
if(! diaspora_post_allow($importer,$contact)) {
if(! diaspora_post_allow($importer,$contact, false)) {
logger('diaspora_like: Ignoring this author.');
return 202;
}
@ -2978,7 +3006,7 @@ function diaspora_send_mail($item,$owner,$contact) {
$msg = array(
'guid' => xmlify($item['guid']),
'parent_guid' => xmlify($cnv['guid']),
'parent_author_signature' => (($item['reply']) ? null : xmlify($sig)),
'parent_author_signature' => xmlify($sig),
'author_signature' => xmlify($sig),
'text' => xmlify($body),
'created_at' => xmlify($created),
@ -3059,3 +3087,47 @@ function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false)
return(($return_code) ? $return_code : (-1));
}
function diaspora_fetch_relay() {
$serverdata = get_config("system", "relay_server");
if ($serverdata == "")
return array();
$relay = array();
$servers = explode(",", $serverdata);
foreach($servers AS $server) {
$server = trim($server);
$batch = $server."/receive/public";
$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
if (!$relais) {
$addr = "relay@".str_replace("http://", "", normalise_link($server));
$r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
datetime_convert(),
dbesc($addr),
dbesc($addr),
dbesc($server),
dbesc(normalise_link($server)),
dbesc($batch),
dbesc(NETWORK_DIASPORA),
intval(CONTACT_IS_FOLLOWER),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert())
);
$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
if ($relais)
$relay[] = $relais[0];
} else
$relay[] = $relais[0];
}
return $relay;
}

View file

@ -29,11 +29,13 @@ function directory_run(&$argv, &$argc){
$a->set_baseurl(get_config('system','url'));
$dir = get_config('system','directory_submit_url');
$dir = get_config('system','directory');
if(! strlen($dir))
return;
$dir .= "/submit";
$arr = array('url' => $argv[1]);
call_hooks('globaldir_update', $arr);

192
include/discover_poco.php Normal file
View file

@ -0,0 +1,192 @@
<?php
require_once("boot.php");
require_once("include/socgraph.php");
function discover_poco_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);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('include/pidfile.php');
load_config('config');
load_config('system');
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load[0] . ' too high. discover_poco deferred to next scheduled run.');
return;
}
}
if(($argc > 2) && ($argv[1] == "dirsearch")) {
$search = urldecode($argv[2]);
$mode = 1;
} elseif(($argc == 2) && ($argv[1] == "checkcontact")) {
$mode = 2;
} elseif ($argc == 1) {
$search = "";
$mode = 0;
} else
die("Unknown or missing parameter ".$argv[1]."\n");
$lockpath = get_lockpath();
if ($lockpath != '') {
$pidfile = new pidfile($lockpath, 'discover_poco'.$mode.urlencode($search));
if($pidfile->is_already_running()) {
logger("discover_poco: Already running");
if ($pidfile->running_time() > 19*60) {
$pidfile->kill();
logger("discover_poco: killed stale process");
// Calling a new instance
if ($mode == 0)
proc_run('php','include/discover_poco.php');
}
exit;
}
}
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('start '.$search);
if (($mode == 2) AND get_config('system','poco_completion'))
discover_users();
elseif (($mode == 1) AND ($search != "") and get_config('system','poco_local_search'))
discover_directory($search);
elseif (($mode == 0) AND ($search == "") and (get_config('system','poco_discovery') > 0))
poco_discover();
logger('end '.$search);
return;
}
function discover_users() {
logger("Discover users", LOGGER_DEBUG);
$users = q("SELECT `url`, `created`, `updated`, `last_failure`, `last_contact`, `server_url` FROM `gcontact`
WHERE `last_contact` < UTC_TIMESTAMP - INTERVAL 1 MONTH AND
`last_failure` < UTC_TIMESTAMP - INTERVAL 1 MONTH AND
`network` IN ('%s', '%s', '%s', '%s', '') ORDER BY rand()",
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_FEED));
if (!$users)
return;
$checked = 0;
foreach ($users AS $user) {
$urlparts = parse_url($user["url"]);
if (!isset($urlparts["scheme"])) {
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
dbesc(NETWORK_PHANTOM), dbesc(normalise_link($user["url"])));
continue;
}
if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com",
"identi.ca", "alpha.app.net"))) {
$networks = array("www.facebook.com" => NETWORK_FACEBOOK,
"facebook.com" => NETWORK_FACEBOOK,
"twitter.com" => NETWORK_TWITTER,
"identi.ca" => NETWORK_PUMPIO,
"alpha.app.net" => NETWORK_APPNET);
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
dbesc($networks[$urlparts["host"]]), dbesc(normalise_link($user["url"])));
continue;
}
if ($user["server_url"] != "")
$server_url = $user["server_url"];
else
$server_url = poco_detect_server($user["url"]);
if (poco_check_server($server_url, $gcontacts[0]["network"])) {
logger('Check user '.$user["url"]);
poco_last_updated($user["url"], true);
if (++$checked > 100)
return;
} else
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($user["url"])));
}
}
function discover_directory($search) {
$data = Cache::get("dirsearch:".$search);
if (!is_null($data)){
// Only search for the same item every 24 hours
if (time() < $data + (60 * 60 * 24)) {
logger("Already searched for ".$search." in the last 24 hours", LOGGER_DEBUG);
return;
}
}
$x = fetch_url(get_server()."/lsearch?p=1&n=500&search=".urlencode($search));
$j = json_decode($x);
if(count($j->results))
foreach($j->results as $jj) {
// Check if the contact already exists
$exists = q("SELECT `id`, `last_contact`, `last_failure`, `updated` FROM `gcontact` WHERE `nurl` = '%s'", normalise_link($jj->url));
if ($exists) {
logger("Profile ".$jj->url." already exists (".$search.")", LOGGER_DEBUG);
if (($exists[0]["last_contact"] < $exists[0]["last_failure"]) AND
($exists[0]["updated"] < $exists[0]["last_failure"]))
continue;
// Update the contact
poco_last_updated($jj->url);
continue;
}
// Harcoded paths aren't so good. But in this case it is okay.
// First: We only will get Friendica contacts (which always are using this url schema)
// Second: There will be no further problems if we are doing a mistake
$server_url = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $jj->url);
if ($server_url != $jj->url)
if (!poco_check_server($server_url)) {
logger("Friendica server ".$server_url." doesn't answer.", LOGGER_DEBUG);
continue;
}
logger("Friendica server ".$server_url." seems to be okay.", LOGGER_DEBUG);
logger("Check if profile ".$jj->url." is reachable (".$search.")", LOGGER_DEBUG);
$data = probe_url($jj->url);
if ($data["network"] == NETWORK_DFRN) {
logger("Add profile ".$jj->url." to local directory (".$search.")", LOGGER_DEBUG);
poco_check($data["url"], $data["name"], $data["network"], $data["photo"], "", "", "", $jj->tags, $data["addr"], "", 0);
}
}
Cache::set("dirsearch:".$search, time(), CACHE_DAY);
}
if (array_search(__file__,get_included_files())===0){
discover_poco_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -28,9 +28,14 @@ function dsprphotoq_run($argv, $argc){
foreach($dphotos as $dphoto) {
$r = array();
if ($dphoto['uid'] == 0)
$r[0] = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
else
$r = q("SELECT * FROM user WHERE uid = %d",
intval($dphoto['uid'])
);
intval($dphoto['uid']));
if(!$r) {
logger("diaspora photo queue: user " . $dphoto['uid'] . " not found");
return;

View file

@ -1,5 +1,48 @@
<?php
require_once("include/Scrape.php");
function update_contact($id) {
/*
Warning: Never ever fetch the public key via probe_url and write it into the contacts.
This will reliably kill your communication with Friendica contacts.
*/
$r = q("SELECT `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `network` FROM `contact` WHERE `id` = %d", intval($id));
if (!$r)
return;
$ret = probe_url($r[0]["url"]);
// If probe_url fails the network code will be different
if ($ret["network"] != $r[0]["network"])
return;
$update = false;
// make sure to not overwrite existing values with blank entries
foreach ($ret AS $key => $val) {
if (isset($r[0][$key]) AND ($r[0][$key] != "") AND ($val == ""))
$ret[$key] = $r[0][$key];
if (isset($r[0][$key]) AND ($ret[$key] != $r[0][$key]))
$update = true;
}
if (!$update)
return;
q("UPDATE `contact` SET `url` = '%s', `nurl` = '%s', `addr` = '%s', `alias` = '%s', `batch` = '%s', `notify` = '%s', `poll` = '%s', `poco` = '%s' WHERE `id` = %d",
dbesc($ret['url']),
dbesc(normalise_link($ret['url'])),
dbesc($ret['addr']),
dbesc($ret['alias']),
dbesc($ret['batch']),
dbesc($ret['notify']),
dbesc($ret['poll']),
dbesc($ret['poco']),
intval($id)
);
}
//
// Takes a $uid and a url/handle and adds a new contact
@ -120,12 +163,18 @@ function new_contact($uid,$url,$interactive = false) {
// the poll url is more reliable than the profile url, as we may have
// indirect links or webfinger links
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` = '%s' AND `network` = '%s' LIMIT 1",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `poll` IN ('%s', '%s') AND `network` = '%s' LIMIT 1",
intval($uid),
dbesc($ret['poll']),
dbesc(normalise_link($ret['poll'])),
dbesc($ret['network'])
);
if(!count($r))
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` = '%s' LIMIT 1",
intval($uid), dbesc(normalise_link($url)), dbesc($ret['network'])
);
if(count($r)) {
// update contact
if($r[0]['rel'] == CONTACT_IS_FOLLOWER || ($network === NETWORK_DIASPORA && $r[0]['rel'] == CONTACT_IS_SHARING)) {
@ -136,8 +185,7 @@ function new_contact($uid,$url,$interactive = false) {
intval($uid)
);
}
}
else {
} else {
// check service class limits
@ -241,7 +289,7 @@ function new_contact($uid,$url,$interactive = false) {
// pull feed and consume it, which should subscribe to the hub.
proc_run('php',"include/poller.php","$contact_id");
proc_run('php',"include/onepoll.php","$contact_id", "force");
// create a follow slap
@ -252,7 +300,7 @@ function new_contact($uid,$url,$interactive = false) {
'$photo' => $a->contact['photo'],
'$thumb' => $a->contact['thumb'],
'$published' => datetime_convert('UTC','UTC', 'now', ATOM_TIME),
'$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . random_string(),
'$item_id' => 'urn:X-dfrn:' . $a->get_hostname() . ':follow:' . get_guid(32),
'$title' => '',
'$type' => 'text',
'$content' => t('following'),

View file

@ -90,12 +90,18 @@ function html2bbcode($message)
$message = str_replace("\r", "", $message);
$message = preg_replace_callback("|<pre><code>([^<]*)</code></pre>|ism", function($m) {
return "<code>".str_replace("\n","<br>\n",$m[1]). "</code>";
}, $message);
$message = str_replace(array(
"<li><p>",
"</p></li>"),
"</p></li>",
),
array(
"<li>",
"</li>"),
"</li>",
),
$message);
// remove namespaces
@ -187,6 +193,7 @@ function html2bbcode($message)
node2bbcode($doc, 'span', array(), "", "");
node2bbcode($doc, 'pre', array(), "", "");
node2bbcode($doc, 'div', array(), "\r", "\r");
node2bbcode($doc, 'p', array(), "\n", "\n");
@ -230,6 +237,7 @@ function html2bbcode($message)
node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), '[iframe]$1', '[/iframe]');
node2bbcode($doc, 'code', array(), '[code]', '[/code]');
node2bbcode($doc, 'key', array(), '[code]', '[/code]');
$message = $doc->saveHTML();

View file

@ -175,7 +175,7 @@ if(! function_exists('profile_sidebar')) {
if (($profile['network'] != "") AND ($profile['network'] != NETWORK_DFRN)) {
require_once('include/contact_selectors.php');
if ($profile['url'] != "")
$profile['network_name'] = '<a href="'.$profile['url'].'">'.network_to_name($profile['network'])."</a>";
$profile['network_name'] = '<a href="'.$profile['url'].'">'.network_to_name($profile['network'], $profile['url'])."</a>";
else
$profile['network_name'] = network_to_name($profile['network']);
} else
@ -285,6 +285,7 @@ if(! function_exists('profile_sidebar')) {
$lastname = (($firstname === $profile['name']) ? '' : trim(substr($profile['name'],strlen($firstname))));
$diaspora = array(
'guid' => $profile['guid'],
'podloc' => $a->get_baseurl(),
'searchable' => (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false' ),
'nickname' => $profile['nickname'],
@ -634,6 +635,7 @@ if(! function_exists('profile_tabs')){
'sel' => ((!isset($tab)&&$a->argv[0]=='profile')?'active':''),
'title' => t('Status Messages and Posts'),
'id' => 'status-tab',
'accesskey' => 'm',
),
array(
'label' => t('Profile'),
@ -641,6 +643,7 @@ if(! function_exists('profile_tabs')){
'sel' => ((isset($tab) && $tab=='profile')?'active':''),
'title' => t('Profile Details'),
'id' => 'profile-tab',
'accesskey' => 'r',
),
array(
'label' => t('Photos'),
@ -648,6 +651,7 @@ if(! function_exists('profile_tabs')){
'sel' => ((!isset($tab)&&$a->argv[0]=='photos')?'active':''),
'title' => t('Photo Albums'),
'id' => 'photo-tab',
'accesskey' => 'h',
),
array(
'label' => t('Videos'),
@ -655,6 +659,7 @@ if(! function_exists('profile_tabs')){
'sel' => ((!isset($tab)&&$a->argv[0]=='videos')?'active':''),
'title' => t('Videos'),
'id' => 'video-tab',
'accesskey' => 'v',
),
);
@ -665,6 +670,7 @@ if(! function_exists('profile_tabs')){
'sel' =>((!isset($tab)&&$a->argv[0]=='events')?'active':''),
'title' => t('Events and Calendar'),
'id' => 'events-tab',
'accesskey' => 'e',
);
$tabs[] = array(
'label' => t('Personal Notes'),
@ -672,6 +678,7 @@ if(! function_exists('profile_tabs')){
'sel' =>((!isset($tab)&&$a->argv[0]=='notes')?'active':''),
'title' => t('Only You Can See This'),
'id' => 'notes-tab',
'accesskey' => 't',
);
}

View file

@ -969,7 +969,7 @@ function query_page_info($url, $no_photos = false, $photo = "", $keywords = fals
$data = Cache::get("parse_url:".$url);
if (is_null($data)){
$data = parseurl_getsiteinfo($url, true);
Cache::set("parse_url:".$url,serialize($data));
Cache::set("parse_url:".$url,serialize($data), CACHE_DAY);
} else
$data = unserialize($data);
@ -1209,8 +1209,14 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
}
}
if ($notify)
$guid_prefix = "";
else
$guid_prefix = $arr['network'];
$arr['wall'] = ((x($arr,'wall')) ? intval($arr['wall']) : 0);
$arr['uri'] = ((x($arr,'uri')) ? notags(trim($arr['uri'])) : random_string());
$arr['guid'] = ((x($arr,'guid')) ? notags(trim($arr['guid'])) : get_guid(32, $guid_prefix));
$arr['uri'] = ((x($arr,'uri')) ? notags(trim($arr['uri'])) : $arr['guid']);
$arr['extid'] = ((x($arr,'extid')) ? notags(trim($arr['extid'])) : '');
$arr['author-name'] = ((x($arr,'author-name')) ? notags(trim($arr['author-name'])) : '');
$arr['author-link'] = ((x($arr,'author-link')) ? notags(trim($arr['author-link'])) : '');
@ -1248,7 +1254,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
$arr['app'] = ((x($arr,'app')) ? notags(trim($arr['app'])) : '');
$arr['origin'] = ((x($arr,'origin')) ? intval($arr['origin']) : 0 );
$arr['network'] = ((x($arr,'network')) ? trim($arr['network']) : '');
$arr['guid'] = ((x($arr,'guid')) ? notags(trim($arr['guid'])) : get_guid(32, $arr['network']));
$arr['postopts'] = ((x($arr,'postopts')) ? trim($arr['postopts']) : '');
$arr['resource-id'] = ((x($arr,'resource-id')) ? trim($arr['resource-id']) : '');
$arr['event-id'] = ((x($arr,'event-id')) ? intval($arr['event-id']) : 0 );
@ -1423,6 +1428,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
// Fill the cache field
put_item_in_cache($arr);
if ($notify)
call_hooks('post_local',$arr);
else
call_hooks('post_remote',$arr);
if(x($arr,'cancel')) {
@ -1569,6 +1577,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
$r = q('SELECT * FROM `item` WHERE id = %d', intval($current_post));
if (count($r) == 1) {
if ($notify)
call_hooks('post_local_end', $r[0]);
else
call_hooks('post_remote_end', $r[0]);
} else
logger('item_store: new item not found in DB, id ' . $current_post);
@ -1989,9 +2000,10 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
$rino = get_config('system','rino_encrypt');
$rino = intval($rino);
// use RINO1 if mcrypt isn't installed and RINO2 was selected
if ($rino==2 and !function_exists('mcrypt_create_iv')) $rino=1;
logger("Local rino version: ". $rino, LOGGER_DEBUG);
$ssl_val = intval(get_config('system','ssl_policy'));
$ssl_policy = '';
@ -2043,6 +2055,8 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) {
$rino_remote_version = intval($res->rino);
$page = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0);
logger("Remote rino version: ".$rino_remote_version." for ".$contact["url"], LOGGER_DEBUG);
if($owner['page-flags'] == PAGE_PRVGROUP)
$page = 2;
@ -2968,7 +2982,7 @@ function item_is_remote_self($contact, &$datarray) {
if ($contact['network'] != NETWORK_FEED) {
$datarray["guid"] = get_guid(32);
unset($datarray["plink"]);
$datarray["uri"] = item_new_uri($a->get_hostname(),$contact['uid']);
$datarray["uri"] = item_new_uri($a->get_hostname(),$contact['uid'], $datarray["guid"]);
$datarray["parent-uri"] = $datarray["uri"];
$datarray["extid"] = $contact['network'];
$urlpart = parse_url($datarray2['author-link']);
@ -2977,9 +2991,6 @@ function item_is_remote_self($contact, &$datarray) {
$datarray['private'] = 0;
}
//if (!isset($datarray["app"]) OR ($datarray["app"] == ""))
// $datarray["app"] = network_to_name($contact['network']);
if ($contact['network'] != NETWORK_FEED) {
// Store the original post
$r = item_store($datarray2, false, false);
@ -4159,9 +4170,12 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
$name = notags(trim($datarray['author-name']));
$photo = notags(trim($datarray['author-avatar']));
if (is_object($item)) {
$rawtag = $item->get_item_tags(NAMESPACE_ACTIVITY,'actor');
if($rawtag && $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'])
$nick = $rawtag[0]['child'][NAMESPACE_POCO]['preferredUsername'][0]['data'];
} else
$nick = $item;
if(is_array($contact)) {
if(($contact['network'] == NETWORK_OSTATUS && $contact['rel'] == CONTACT_IS_SHARING)
@ -4299,7 +4313,7 @@ function subscribe_to_hub($url,$importer,$contact,$hubmode = 'subscribe') {
logger('subscribe_to_hub: ' . $hubmode . ' ' . $contact['name'] . ' to hub ' . $url . ' endpoint: ' . $push_url . ' with verifier ' . $verify_token);
if(! strlen($contact['hub-verify'])) {
if(!strlen($contact['hub-verify']) OR ($contact['hub-verify'] != $verify_token)) {
$r = q("UPDATE `contact` SET `hub-verify` = '%s' WHERE `id` = %d",
dbesc($verify_token),
intval($contact['id'])

View file

@ -26,8 +26,8 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
return -2;
}
$hash = random_string();
$uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $hash ;
$guid = get_guid(32);
$uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $guid;
$convid = 0;
$reply = false;
@ -49,14 +49,15 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
// create a new conversation
$conv_guid = get_guid();
$recip_host = substr($contact[0]['url'],strpos($contact[0]['url'],'://')+3);
$recip_host = substr($recip_host,0,strpos($recip_host,'/'));
$recip_handle = (($contact[0]['addr']) ? $contact[0]['addr'] : $contact[0]['nick'] . '@' . $recip_host);
$sender_handle = $a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
$conv_guid = get_guid(32);
$convuri = $recip_handle.':'.$conv_guid;
$handles = $recip_handle . ';' . $sender_handle;
$r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
@ -83,7 +84,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
}
if(! strlen($replyto)) {
$replyto = $uri;
$replyto = $convuri;
}
@ -91,7 +92,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){
`contact-id`, `title`, `body`, `seen`, `reply`, `replied`, `uri`, `parent-uri`, `created`)
VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, %d, '%s', '%s', '%s' )",
intval(local_user()),
dbesc(get_guid()),
dbesc($guid),
intval($convid),
dbesc($me[0]['name']),
dbesc($me[0]['thumb']),
@ -171,8 +172,8 @@ function send_wallmessage($recipient='', $body='', $subject='', $replyto=''){
if(! strlen($subject))
$subject = t('[no subject]');
$hash = random_string();
$uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $hash ;
$guid = get_guid(32);
$uri = 'urn:X-dfrn:' . $a->get_baseurl() . ':' . local_user() . ':' . $guid;
$convid = 0;
$reply = false;
@ -184,7 +185,7 @@ function send_wallmessage($recipient='', $body='', $subject='', $replyto=''){
if(! $me['name'])
return -2;
$conv_guid = get_guid();
$conv_guid = get_guid(32);
$recip_handle = $recipient['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
@ -221,7 +222,7 @@ function send_wallmessage($recipient='', $body='', $subject='', $replyto=''){
`contact-id`, `title`, `body`, `seen`, `reply`, `replied`, `uri`, `parent-uri`, `created`, `unknown`)
VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, %d, '%s', '%s', '%s', %d )",
intval($recipient['uid']),
dbesc(get_guid()),
dbesc($guid),
intval($convid),
dbesc($me['name']),
dbesc($me['photo']),

View file

@ -118,10 +118,18 @@ function nav_info(&$a) {
$nav['search'] = array('search', t('Search'), "", t('Search site content'));
$nav['searchoption'] = array(
t("Full Text"),
t("Tags"),
t("Contacts"));
if (get_config('system','poco_local_search'))
$nav['searchoption'][] = t("Forums");
$gdirpath = 'directory';
if(strlen(get_config('system','singleuser'))) {
$gdir = dirname(get_config('system','directory_submit_url'));
$gdir = get_config('system','directory');
if(strlen($gdir))
$gdirpath = $gdir;
}

View file

@ -3,6 +3,7 @@ require_once("boot.php");
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once("include/Scrape.php");
require_once('include/diaspora.php');
/*
* This file was at one time responsible for doing all deliveries, but this caused
@ -294,7 +295,7 @@ function notifier_run(&$argv, &$argc){
$relay_to_owner = false;
if($relay_to_owner) {
logger('notifier: followup', LOGGER_DEBUG);
logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG);
// local followup to remote post
$followup = true;
$public_message = false; // not public
@ -330,6 +331,8 @@ function notifier_run(&$argv, &$argc){
} else {
$followup = false;
logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG);
// don't send deletions onward for other people's stuff
if($target_item['deleted'] && (! intval($target_item['wall']))) {
@ -377,7 +380,7 @@ function notifier_run(&$argv, &$argc){
}
if (count($url_recipients))
logger('notifier: url_recipients ' . print_r($url_recipients,true));
logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true));
$conversants = array_unique($conversants);
@ -393,6 +396,8 @@ function notifier_run(&$argv, &$argc){
// We have not only to look at the parent, since it could be a Friendica thread.
if (($thr_parent AND ($thr_parent[0]['network'] == NETWORK_OSTATUS)) OR ($parent['network'] == NETWORK_OSTATUS)) {
logger('Some parent is OStatus for '.$target_item["guid"], LOGGER_DEBUG);
// Send a salmon notification to every person we mentioned in the post
$arr = explode(',',$target_item['tag']);
foreach($arr as $x) {
@ -406,9 +411,13 @@ function notifier_run(&$argv, &$argc){
}
}
}
}
$r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0");
// It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
$sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')";
} else
$sql_extra = "";
$r = q("SELECT * FROM `contact` WHERE `id` IN ($conversant_str) AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0".$sql_extra);
if(count($r))
$contacts = $r;
@ -645,7 +654,7 @@ function notifier_run(&$argv, &$argc){
if($contact['self'])
continue;
logger("Deliver to ".$contact['url'], LOGGER_DEBUG);
logger("Deliver ".$target_item["guid"]." to ".$contact['url'], LOGGER_DEBUG);
// potentially more than one recipient. Start a new process and space them out a bit.
// we will deliver single recipient types of message and email recipients here.
@ -870,8 +879,6 @@ function notifier_run(&$argv, &$argc){
}
break;
case NETWORK_DIASPORA:
require_once('include/diaspora.php');
if(get_config('system','dfrn_only') || (! get_config('system','diaspora_enabled')))
break;
@ -954,6 +961,11 @@ function notifier_run(&$argv, &$argc){
if($public_message) {
if (!$followup)
$r0 = diaspora_fetch_relay();
else
$r0 = array();
$r1 = q("SELECT DISTINCT(`batch`), `id`, `name`,`network` FROM `contact` WHERE `network` = '%s'
AND `uid` = %d AND `rel` != %d group by `batch` ORDER BY rand() ",
dbesc(NETWORK_DIASPORA),
@ -970,7 +982,7 @@ function notifier_run(&$argv, &$argc){
intval(CONTACT_IS_SHARING)
);
$r = array_merge($r2,$r1);
$r = array_merge($r2,$r1,$r0);
if(count($r)) {
logger('pubdeliver: ' . print_r($r,true), LOGGER_DEBUG);

View file

@ -56,25 +56,21 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
if ($txt==false || $txt==""){
$embedly = get_config("system", "embedly");
if ($embedly == "") {
// try oohembed service
$ourl = "http://oohembed.com/oohembed/?url=".urlencode($embedurl).'&maxwidth=' . $a->videowidth;
$txt = fetch_url($ourl);
} else {
if ($embedly != "") {
// try embedly service
$ourl = "https://api.embed.ly/1/oembed?key=".$embedly."&url=".urlencode($embedurl);
$txt = fetch_url($ourl);
}
logger("oembed_fetch_url: ".$txt, LOGGER_DEBUG);
}
}
$txt=trim($txt);
if ($txt[0]!="{") $txt='{"type":"error"}';
//save in cache
Cache::set($a->videowidth . $embedurl,$txt);
if ($txt[0]!="{")
$txt='{"type":"error"}';
else //save in cache
Cache::set($a->videowidth . $embedurl,$txt, CACHE_DAY);
}
$j = json_decode($txt);

View file

@ -1,6 +1,7 @@
<?php
require_once("boot.php");
require_once("include/follow.php");
function RemoveReply($subject) {
while (in_array(strtolower(substr($subject, 0, 3)), array("re:", "aw:")))
@ -52,6 +53,9 @@ function onepoll_run(&$argv, &$argc){
if(($argc > 1) && (intval($argv[1])))
$contact_id = intval($argv[1]);
if(($argc > 2) && ($argv[2] == "force"))
$force = true;
if(! $contact_id) {
logger('onepoll: no contact');
return;
@ -78,24 +82,58 @@ function onepoll_run(&$argv, &$argc){
$contacts = q("SELECT `contact`.* FROM `contact`
WHERE ( `rel` = %d OR `rel` = %d ) AND `poll` != ''
AND NOT `network` IN ( '%s', '%s', '%s' )
AND NOT `network` IN ( '%s', '%s' )
AND `contact`.`id` = %d
AND `self` = 0 AND `contact`.`blocked` = 0 AND `contact`.`readonly` = 0
AND `contact`.`archive` = 0 LIMIT 1",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_FACEBOOK),
dbesc(NETWORK_PUMPIO),
intval($contact_id)
);
if(! count($contacts)) {
if(! count($contacts))
return;
}
$contact = $contacts[0];
// load current friends if possible.
if (($contact['poco'] != "") AND ($contact['success_update'] > $contact['failure_update'])) {
$r = q("SELECT count(*) as total from glink
where `cid` = %d and updated > UTC_TIMESTAMP() - INTERVAL 1 DAY",
intval($contact['id'])
);
if (count($r))
if (!$r[0]['total'])
poco_load($contact['id'],$importer_uid,0,$contact['poco']);
}
// To-Do:
// - Check why we don't poll the Diaspora feed at the moment (some guid problem in the items?)
// - Check whether this is possible with Redmatrix
if ($contact["network"] == NETWORK_DIASPORA) {
if (poco_do_update($contact["created"], $contact["last-item"], $contact["failure_update"], $contact["success_update"])) {
$last_updated = poco_last_updated($contact["url"]);
$updated = datetime_convert();
if ($last_updated) {
q("UPDATE `contact` SET `last-item` = '%s', `last-update` = '%s', `success_update` = '%s' WHERE `id` = %d",
dbesc($last_updated),
dbesc($updated),
dbesc($updated),
intval($contact['id'])
);
} else {
q("UPDATE `contact` SET `last-update` = '%s', `failure_update` = '%s' WHERE `id` = %d",
dbesc($updated),
dbesc($updated),
intval($contact['id'])
);
}
}
return;
}
$xml = false;
$t = $contact['last-update'];
@ -129,6 +167,10 @@ function onepoll_run(&$argv, &$argc){
: datetime_convert('UTC','UTC',$contact['last-update'], ATOM_TIME)
);
// Update the contact entry
if(($contact['network'] === NETWORK_OSTATUS) || ($contact['network'] === NETWORK_DIASPORA) || ($contact['network'] === NETWORK_DFRN))
update_contact($contact["id"]);
if($contact['network'] === NETWORK_DFRN) {
@ -168,7 +210,8 @@ function onepoll_run(&$argv, &$argc){
mark_for_death($contact);
// set the last-update so we don't keep polling
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d",
$r = q("UPDATE `contact` SET `last-update` = '%s', `failure_update` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($contact['id'])
);
@ -181,7 +224,8 @@ function onepoll_run(&$argv, &$argc){
mark_for_death($contact);
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d",
$r = q("UPDATE `contact` SET `last-update` = '%s', `failure_update` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($contact['id'])
);
@ -198,7 +242,8 @@ function onepoll_run(&$argv, &$argc){
// set the last-update so we don't keep polling
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d",
$r = q("UPDATE `contact` SET `last-update` = '%s', `failure_update` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($contact['id'])
);
@ -265,7 +310,8 @@ function onepoll_run(&$argv, &$argc){
$stat_writeable = ((($contact['notify']) && ($contact['rel'] == CONTACT_IS_FOLLOWER || $contact['rel'] == CONTACT_IS_FRIEND)) ? 1 : 0);
if($contact['network'] === NETWORK_OSTATUS && get_pconfig($importer_uid,'system','ostatus_autofriend'))
// Contacts from OStatus are always writable
if($contact['network'] === NETWORK_OSTATUS)
$stat_writeable = 1;
if($stat_writeable != $contact['writable']) {
@ -544,7 +590,8 @@ function onepoll_run(&$argv, &$argc){
logger('poller: received xml : ' . $xml, LOGGER_DATA);
if(! strstr($xml,'<')) {
logger('poller: post_handshake: response from ' . $url . ' did not contain XML.');
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d",
$r = q("UPDATE `contact` SET `last-update` = '%s', `failure_update` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()),
dbesc(datetime_convert()),
intval($contact['id'])
);
@ -552,8 +599,9 @@ function onepoll_run(&$argv, &$argc){
}
consume_feed($xml,$importer,$contact,$hub,1,1);
logger("Consume feed of contact ".$contact['id']);
consume_feed($xml,$importer,$contact,$hub,1,1);
// do it twice. Ensures that children of parents which may be later in the stream aren't tossed
@ -566,6 +614,11 @@ function onepoll_run(&$argv, &$argc){
if(($contact['network'] === NETWORK_OSTATUS || $contact['network'] == NETWORK_FEED) && (! $contact['hub-verify']))
$hub_update = true;
if ($force)
$hub_update = true;
logger("Contact ".$contact['id']." returned hub: ".$hub." Network: ".$contact['network']." Relation: ".$contact['rel']." Update: ".$hub_update);
if((strlen($hub)) && ($hub_update) && (($contact['rel'] != CONTACT_IS_FOLLOWER) || $contact['network'] == NETWORK_FEED) ) {
logger('poller: hub ' . $hubmode . ' : ' . $hub . ' contact name : ' . $contact['name'] . ' local user : ' . $importer['name']);
$hubs = explode(',', $hub);
@ -578,7 +631,6 @@ function onepoll_run(&$argv, &$argc){
}
}
}
}
$updated = datetime_convert();
@ -588,19 +640,29 @@ function onepoll_run(&$argv, &$argc){
intval($contact['id'])
);
q("UPDATE `gcontact` SET `last_contact` = '%s' WHERE `nurl` = '%s'",
dbesc($updated),
dbesc($contact['nurl'])
);
// load current friends if possible.
} elseif (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_FEED))) {
$updated = datetime_convert();
if($contact['poco']) {
$r = q("SELECT count(*) as total from glink
where `cid` = %d and updated > UTC_TIMESTAMP() - INTERVAL 1 DAY",
$r = q("UPDATE `contact` SET `last-update` = '%s', `failure_update` = '%s' WHERE `id` = %d",
dbesc($updated),
dbesc($updated),
intval($contact['id'])
);
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc($updated),
dbesc($contact['nurl'])
);
} else {
$r = q("UPDATE `contact` SET `last-update` = '%s' WHERE `id` = %d",
dbesc($updated),
intval($contact['id'])
);
}
if(count($r)) {
if(! $r[0]['total']) {
poco_load($contact['id'],$importer_uid,0,$contact['poco']);
}
}
return;

View file

@ -7,12 +7,64 @@ require_once("mod/share.php");
require_once("include/enotify.php");
require_once("include/socgraph.php");
require_once("include/Photo.php");
require_once("include/Scrape.php");
require_once("include/follow.php");
define('OSTATUS_DEFAULT_POLL_INTERVAL', 30); // given in minutes
define('OSTATUS_DEFAULT_POLL_TIMEFRAME', 1440); // given in minutes
define('OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS', 14400); // given in minutes
function ostatus_fetchauthor($xpath, $context, $importer, &$contact) {
function ostatus_check_follow_friends() {
$r = q("SELECT `uid`,`v` FROM `pconfig` WHERE `cat`='system' AND `k`='ostatus_legacy_contact' AND `v` != ''");
if (!$r)
return;
foreach ($r AS $contact) {
ostatus_follow_friends($contact["uid"], $contact["v"]);
set_pconfig($contact["uid"], "system", "ostatus_legacy_contact", "");
}
}
// This function doesn't work reliable by now.
function ostatus_follow_friends($uid, $url) {
$contact = probe_url($url);
if (!$contact)
return;
$api = $contact["baseurl"]."/api/";
// Fetching friends
$data = z_fetch_url($api."statuses/friends.json?screen_name=".$contact["nick"]);
if (!$data["success"])
return;
$friends = json_decode($data["body"]);
foreach ($friends AS $friend) {
$url = $friend->statusnet_profile_url;
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND
(`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND
`network` != '%s' LIMIT 1",
intval($uid), dbesc(normalise_link($url)),
dbesc(normalise_link($url)), dbesc($url), dbesc(NETWORK_STATUSNET));
if (!$r) {
$data = probe_url($friend->statusnet_profile_url);
if ($data["network"] == NETWORK_OSTATUS) {
$result = new_contact($uid,$friend->statusnet_profile_url);
if ($result["success"])
logger($friend->name." ".$url." - success", LOGGER_DEBUG);
else
logger($friend->name." ".$url." - failed", LOGGER_DEBUG);
} else
logger($friend->name." ".$url." - not OStatus", LOGGER_DEBUG);
}
}
}
function ostatus_fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
$author = array();
$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
@ -63,7 +115,7 @@ function ostatus_fetchauthor($xpath, $context, $importer, &$contact) {
$author["owner-link"] = $author["author-link"];
$author["owner-avatar"] = $author["author-avatar"];
if ($r) {
if ($r AND !$onlyfetch) {
// Update contact data
$update_contact = ($r[0]['name-date'] < datetime_convert('','','now -12 hours'));
if ($update_contact) {
@ -109,6 +161,34 @@ function ostatus_fetchauthor($xpath, $context, $importer, &$contact) {
return($author);
}
function ostatus_salmon_author($xml, $importer) {
$a = get_app();
if ($xml == "")
return;
$doc = new DOMDocument();
@$doc->loadXML($xml);
$xpath = new DomXPath($doc);
$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
$xpath->registerNamespace('thr', "http://purl.org/syndication/thread/1.0");
$xpath->registerNamespace('georss', "http://www.georss.org/georss");
$xpath->registerNamespace('activity', "http://activitystrea.ms/spec/1.0/");
$xpath->registerNamespace('media', "http://purl.org/syndication/atommedia");
$xpath->registerNamespace('poco', "http://portablecontacts.net/spec/1.0");
$xpath->registerNamespace('ostatus', "http://ostatus.org/schema/1.0");
$xpath->registerNamespace('statusnet', "http://status.net/schema/api/1/");
$entries = $xpath->query('/atom:entry');
foreach ($entries AS $entry) {
// fetch the author
$author = ostatus_fetchauthor($xpath, $entry, $importer, $contact, true);
return $author;
}
}
function ostatus_import($xml,$importer,&$contact, &$hub) {
$a = get_app();
@ -173,9 +253,15 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
// fetch the author
if ($first_child == "feed")
$author = ostatus_fetchauthor($xpath, $doc->firstChild, $importer, $contact);
$author = ostatus_fetchauthor($xpath, $doc->firstChild, $importer, $contact, false);
else
$author = ostatus_fetchauthor($xpath, $entry, $importer, $contact);
$author = ostatus_fetchauthor($xpath, $entry, $importer, $contact, false);
$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
if ($value != "")
$nickname = $value;
else
$nickname = $author["author-name"];
$item = array_merge($header, $author);
@ -205,24 +291,45 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
// Delete a message
if ($item["verb"] == "qvitter-delete-notice") {
// ignore "Delete" messages (by now)
logger("Ignore delete message ".print_r($item, true));
continue;
}
if ($item["verb"] == ACTIVITY_JOIN) {
// ignore "Join" messages
logger("Ignore join message ".print_r($item, true));
continue;
}
if ($item["verb"] == ACTIVITY_FOLLOW) {
// ignore "Follow" messages
new_follower($importer, $contact, $item, $nickname);
continue;
}
if ($item["verb"] == NAMESPACE_OSTATUS."/unfollow") {
lose_follower($importer, $contact, $item, $dummy);
continue;
}
if ($item["verb"] == ACTIVITY_FAVORITE) {
// ignore "Favorite" messages
$orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue;
logger("Favorite ".$orig_uri." ".print_r($item, true));
$item["verb"] = ACTIVITY_LIKE;
$item["parent-uri"] = $orig_uri;
$item["gravity"] = GRAVITY_LIKE;
}
if ($item["verb"] == NAMESPACE_OSTATUS."/unfavorite") {
// Ignore "Unfavorite" message
logger("Ignore unfavorite message ".print_r($item, true));
continue;
}
// http://activitystrea.ms/schema/1.0/rsvp-yes
if (!in_array($item["verb"], array(ACTIVITY_POST, ACTIVITY_LIKE, ACTIVITY_SHARE)))
logger("Unhandled verb ".$item["verb"]." ".print_r($item, true));
$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
$conversation = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue;
@ -366,7 +473,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
$orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue;
$orig_contact = $contact;
$orig_author = ostatus_fetchauthor($xpath, $activityobjects, $importer, $orig_contact);
$orig_author = ostatus_fetchauthor($xpath, $activityobjects, $importer, $orig_contact, false);
//if (!intval(get_config('system','wall-to-wall_share'))) {
// $prefix = share_header($orig_author['author-name'], $orig_author['author-link'], $orig_author['author-avatar'], "", $orig_created, $orig_link);

View file

@ -52,7 +52,7 @@ function get_attached_data($body) {
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($pictures[0][1], true);
$data = parseurl_getsiteinfo_cached($pictures[0][1], true);
if ($data["type"] == "photo") {
$post["type"] = "photo";
if (isset($data["images"][0]))
@ -95,7 +95,7 @@ function get_attached_data($body) {
}
} elseif (isset($post["url"]) AND ($post["type"] == "video")) {
require_once("mod/parse_url.php");
$data = parseurl_getsiteinfo($post["url"], true);
$data = parseurl_getsiteinfo_cached($post["url"], true);
if (isset($data["images"][0]))
$post["image"] = $data["images"][0]["src"];

View file

@ -162,6 +162,8 @@ function call_hooks($name, &$data = null) {
$a = get_app();
#logger($name, LOGGER_ALL);
if((is_array($a->hooks)) && (array_key_exists($name,$a->hooks))) {
foreach($a->hooks[$name] as $hook) {
// Don't run a theme's hook if the user isn't using the theme
@ -171,6 +173,7 @@ function call_hooks($name, &$data = null) {
@include_once($hook[0]);
if(function_exists($hook[1])) {
$func = $hook[1];
//logger($name." => ".$hook[0].":".$func."()", LOGGER_DEBUG);
$func($a,$data);
}
else {

View file

@ -36,6 +36,7 @@ function poller_run(&$argv, &$argc){
require_once('include/email.php');
require_once('include/socgraph.php');
require_once('include/pidfile.php');
require_once('mod/nodeinfo.php');
load_config('config');
load_config('system');
@ -82,6 +83,14 @@ function poller_run(&$argv, &$argc){
proc_run('php',"include/dsprphotoq.php");
// run the process to discover global contacts in the background
proc_run('php',"include/discover_poco.php");
// run the process to update locally stored global contacts in the background
proc_run('php',"include/discover_poco.php", "checkcontact");
// expire any expired accounts
q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
@ -109,6 +118,12 @@ function poller_run(&$argv, &$argc){
// Check every conversation
check_conversations(false);
// Follow your friends from your legacy OStatus account
ostatus_check_follow_friends();
// update nodeinfo data
nodeinfo_cron();
// To-Do: Regenerate usage statistics
// q("ANALYZE TABLE `item`");

View file

@ -12,7 +12,7 @@ function profile_change() {
return;
// $url = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
// if($url && strlen(get_config('system','directory_submit_url')))
// if($url && strlen(get_config('system','directory')))
// proc_run('php',"include/directory.php","$url");
$recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'

View file

@ -1,6 +1,15 @@
<?php
require_once('include/datetime.php');
require_once("include/Scrape.php");
require_once("include/html2bbcode.php");
/*
To-Do:
- Move GNU Social URL schemata (http://server.tld/user/number) to http://server.tld/username
- Fetch profile data from profile page for Redmatrix users
- Detect if it is a forum
*/
/*
* poco_load
@ -21,8 +30,6 @@ require_once('include/datetime.php');
function poco_load($cid,$uid = 0,$zcid = 0,$url = null) {
require_once("include/html2bbcode.php");
$a = get_app();
if($cid) {
@ -124,8 +131,9 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) {
$keywords = implode(", ", $tag);
// If you query a Friendica server for its profiles, the network has to be Friendica
if ($uid == 0)
$network = NETWORK_DFRN;
// To-Do: It could also be a Redmatrix server
//if ($uid == 0)
// $network = NETWORK_DFRN;
poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid, $uid, $zcid);
@ -163,9 +171,21 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$gcid = "";
$alternate = poco_alternate_ostatus_url($profile_url);
if ($profile_url == "")
return $gcid;
$urlparts = parse_url($profile_url);
if (!isset($urlparts["scheme"]))
return $gcid;
if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com",
"identi.ca", "alpha.app.net")))
return $gcid;
$orig_updated = $updated;
// Don't store the statusnet connector as network
// We can't simply set this to NETWORK_OSTATUS since the connector could have fetched posts from friendica as well
if ($network == NETWORK_STATUSNET)
@ -187,26 +207,61 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
);
if(count($r)) {
$network = $r[0]["network"];
$profile_url = $r[0]["url"];
//$profile_url = $r[0]["url"];
}
}
$x = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link($profile_url))
);
if(count($x) AND ($network == "") AND ($x[0]["network"] != NETWORK_STATUSNET))
if (count($x)) {
if (($network == "") AND ($x[0]["network"] != NETWORK_STATUSNET))
$network = $x[0]["network"];
if (($network == "") OR ($name == "") OR ($profile_photo == "")) {
require_once("include/Scrape.php");
if ($updated == "0000-00-00 00:00:00")
$updated = $x[0]["updated"];
$created = $x[0]["created"];
$server_url = $x[0]["server_url"];
$nick = $x[0]["nick"];
} else {
$created = "0000-00-00 00:00:00";
$server_url = "";
$urlparts = parse_url($profile_url);
$nick = end(explode("/", $urlparts["path"]));
}
if ((($network == "") OR ($name == "") OR ($profile_photo == "") OR ($server_url == "") OR $alternate)
AND poco_reachable($profile_url, $server_url, $network, false)) {
$data = probe_url($profile_url);
$orig_profile = $profile_url;
$network = $data["network"];
$name = $data["name"];
$nick = $data["nick"];
$profile_url = $data["url"];
$profile_photo = $data["photo"];
$server_url = $data["baseurl"];
if ($alternate AND ($network == NETWORK_OSTATUS)) {
// Delete the old entry - if it exists
$r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile)));
if ($r) {
q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile)));
q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"]));
}
// possibly create a new entry
poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid, $uid, $zcid);
}
}
if ($alternate AND ($network == NETWORK_OSTATUS))
return $gcid;
if (count($x) AND ($x[0]["network"] == "") AND ($network != "")) {
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
dbesc($network),
@ -222,6 +277,8 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
logger("profile-check generation: ".$generation." Network: ".$network." URL: ".$profile_url." name: ".$name." avatar: ".$profile_photo, LOGGER_DEBUG);
poco_check_server($server_url, $network);
if(count($x)) {
$gcid = $x[0]['id'];
@ -241,7 +298,7 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$generation = $x[0]['generation'];
if($x[0]['name'] != $name || $x[0]['photo'] != $profile_photo || $x[0]['updated'] < $updated) {
q("UPDATE `gcontact` SET `name` = '%s', `network` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s',
q("UPDATE `gcontact` SET `name` = '%s', `network` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s', `server_url` = '%s',
`updated` = '%s', `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s', `generation` = %d
WHERE (`generation` >= %d OR `generation` = 0) AND `nurl` = '%s'",
dbesc($name),
@ -249,6 +306,7 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
dbesc($profile_photo),
dbesc($connect_url),
dbesc($profile_url),
dbesc($server_url),
dbesc($updated),
dbesc($location),
dbesc($about),
@ -260,14 +318,17 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
);
}
} else {
q("INSERT INTO `gcontact` (`name`,`network`, `url`,`nurl`,`photo`,`connect`, `updated`, `location`, `about`, `keywords`, `gender`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s', '%s', '%s', %d)",
q("INSERT INTO `gcontact` (`name`, `nick`, `network`, `url`, `nurl`, `photo`, `connect`, `server_url`, `created`, `updated`, `location`, `about`, `keywords`, `gender`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
dbesc($name),
dbesc($nick),
dbesc($network),
dbesc($profile_url),
dbesc(normalise_link($profile_url)),
dbesc($profile_photo),
dbesc($connect_url),
dbesc($server_url),
dbesc(datetime_convert()),
dbesc($updated),
dbesc($location),
dbesc($about),
@ -319,6 +380,576 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
return $gcid;
}
function poco_reachable($profile, $server = "", $network = "", $force = false) {
if ($server == "")
$server = poco_detect_server($profile);
if ($server == "")
return true;
return poco_check_server($server, $network, $force);
}
function poco_detect_server($profile) {
// Try to detect the server path based upon some known standard paths
$server_url = "";
if ($server_url == "") {
$friendica = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $profile);
if ($friendica != $profile) {
$server_url = $friendica;
$network = NETWORK_DFRN;
}
}
if ($server_url == "") {
$diaspora = preg_replace("=(https?://)(.*)/u/(.*)=ism", "$1$2", $profile);
if ($diaspora != $profile) {
$server_url = $diaspora;
$network = NETWORK_DIASPORA;
}
}
if ($server_url == "") {
$red = preg_replace("=(https?://)(.*)/channel/(.*)=ism", "$1$2", $profile);
if ($red != $profile) {
$server_url = $red;
$network = NETWORK_DIASPORA;
}
}
return $server_url;
}
function poco_alternate_ostatus_url($url) {
return(preg_match("=https?://.+/user/\d+=ism", $url, $matches));
}
function poco_last_updated($profile, $force = false) {
$gcontacts = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
if ($gcontacts[0]["created"] == "0000-00-00 00:00:00")
q("UPDATE `gcontact` SET `created` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
if ($gcontacts[0]["server_url"] != "")
$server_url = $gcontacts[0]["server_url"];
else
$server_url = poco_detect_server($profile);
if ($server_url != "") {
if (!poco_check_server($server_url, $gcontacts[0]["network"], $force)) {
if ($force)
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
return false;
}
q("UPDATE `gcontact` SET `server_url` = '%s' WHERE `nurl` = '%s'",
dbesc($server_url), dbesc(normalise_link($profile)));
}
if (in_array($gcontacts[0]["network"], array("", NETWORK_FEED))) {
$server = q("SELECT `network` FROM `gserver` WHERE `nurl` = '%s' AND `network` != ''",
dbesc(normalise_link($server_url)));
if ($server)
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
dbesc($server[0]["network"]), dbesc(normalise_link($profile)));
else
return;
}
// noscrape is really fast so we don't cache the call.
if (($gcontacts[0]["server_url"] != "") AND ($gcontacts[0]["nick"] != "")) {
// Use noscrape if possible
$server = q("SELECT `noscrape` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($gcontacts[0]["server_url"])));
if ($server) {
$noscraperet = z_fetch_url($server[0]["noscrape"]."/".$gcontacts[0]["nick"]);
if ($noscraperet["success"] AND ($noscraperet["body"] != "")) {
$noscrape = json_decode($noscraperet["body"], true);
if (($noscrape["fn"] != "") AND ($noscrape["fn"] != $gcontacts[0]["name"]))
q("UPDATE `gcontact` SET `name` = '%s' WHERE `nurl` = '%s'",
dbesc($noscrape["fn"]), dbesc(normalise_link($profile)));
if (($noscrape["photo"] != "") AND ($noscrape["photo"] != $gcontacts[0]["photo"]))
q("UPDATE `gcontact` SET `photo` = '%s' WHERE `nurl` = '%s'",
dbesc($noscrape["photo"]), dbesc(normalise_link($profile)));
if (($noscrape["updated"] != "") AND ($noscrape["updated"] != $gcontacts[0]["updated"]))
q("UPDATE `gcontact` SET `updated` = '%s' WHERE `nurl` = '%s'",
dbesc($noscrape["updated"]), dbesc(normalise_link($profile)));
if (($noscrape["gender"] != "") AND ($noscrape["gender"] != $gcontacts[0]["gender"]))
q("UPDATE `gcontact` SET `gender` = '%s' WHERE `nurl` = '%s'",
dbesc($noscrape["gender"]), dbesc(normalise_link($profile)));
if (($noscrape["pdesc"] != "") AND ($noscrape["pdesc"] != $gcontacts[0]["about"]))
q("UPDATE `gcontact` SET `about` = '%s' WHERE `nurl` = '%s'",
dbesc($noscrape["pdesc"]), dbesc(normalise_link($profile)));
if (($noscrape["about"] != "") AND ($noscrape["about"] != $gcontacts[0]["about"]))
q("UPDATE `gcontact` SET `about` = '%s' WHERE `nurl` = '%s'",
dbesc($noscrape["about"]), dbesc(normalise_link($profile)));
if (isset($noscrape["comm"]) AND ($noscrape["comm"] != $gcontacts[0]["community"]))
q("UPDATE `gcontact` SET `community` = %d WHERE `nurl` = '%s'",
intval($noscrape["comm"]), dbesc(normalise_link($profile)));
if (isset($noscrape["tags"]))
$keywords = implode(" ", $noscrape["tags"]);
else
$keywords = "";
if (($keywords != "") AND ($keywords != $gcontacts[0]["keywords"]))
q("UPDATE `gcontact` SET `keywords` = '%s' WHERE `nurl` = '%s'",
dbesc($keywords), dbesc(normalise_link($profile)));
$location = $noscrape["locality"];
if ($noscrape["region"] != "") {
if ($location != "")
$location .= ", ";
$location .= $noscrape["region"];
}
if ($noscrape["country-name"] != "") {
if ($location != "")
$location .= ", ";
$location .= $noscrape["country-name"];
}
if (($location != "") AND ($location != $gcontacts[0]["location"]))
q("UPDATE `gcontact` SET `location` = '%s' WHERE `nurl` = '%s'",
dbesc($location), dbesc(normalise_link($profile)));
// If we got data from noscrape then mark the contact as reachable
if (is_array($noscrape) AND count($noscrape))
q("UPDATE `gcontact` SET `last_contact` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
return $noscrape["updated"];
}
}
}
// If we only can poll the feed, then we only do this once a while
if (!$force AND !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"]))
return $gcontacts[0]["updated"];
$data = probe_url($profile);
// Is the profile link the alternate OStatus link notation? (http://domain.tld/user/4711)
// Then check the other link and delete this one
if (($data["network"] == NETWORK_OSTATUS) AND poco_alternate_ostatus_url($profile) AND
(normalise_link($profile) == normalise_link($data["alias"])) AND
(normalise_link($profile) != normalise_link($data["url"]))) {
// Delete the old entry
q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($profile)));
q("DELETE FROM `glink` WHERE `gcid` = %d", intval($gcontacts[0]["id"]));
poco_check($data["url"], $data["name"], $data["network"], $data["photo"], $gcontacts[0]["about"], $gcontacts[0]["location"],
$gcontacts[0]["gender"], $gcontacts[0]["keywords"], $data["addr"], $gcontacts[0]["updated"], $gcontacts[0]["generation"]);
poco_last_updated($data["url"], $force);
return false;
}
if (($data["poll"] == "") OR ($data["network"] == NETWORK_FEED)) {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
return false;
}
if (($data["name"] != "") AND ($data["name"] != $gcontacts[0]["name"]))
q("UPDATE `gcontact` SET `name` = '%s' WHERE `nurl` = '%s'",
dbesc($data["name"]), dbesc(normalise_link($profile)));
if (($data["nick"] != "") AND ($data["nick"] != $gcontacts[0]["nick"]))
q("UPDATE `gcontact` SET `nick` = '%s' WHERE `nurl` = '%s'",
dbesc($data["nick"]), dbesc(normalise_link($profile)));
if (($data["addr"] != "") AND ($data["addr"] != $gcontacts[0]["connect"]))
q("UPDATE `gcontact` SET `connect` = '%s' WHERE `nurl` = '%s'",
dbesc($data["addr"]), dbesc(normalise_link($profile)));
if (($data["photo"] != "") AND ($data["photo"] != $gcontacts[0]["photo"]))
q("UPDATE `gcontact` SET `photo` = '%s' WHERE `nurl` = '%s'",
dbesc($data["photo"]), dbesc(normalise_link($profile)));
if (($data["baseurl"] != "") AND ($data["baseurl"] != $gcontacts[0]["server_url"]))
q("UPDATE `gcontact` SET `server_url` = '%s' WHERE `nurl` = '%s'",
dbesc($data["baseurl"]), dbesc(normalise_link($profile)));
$feedret = z_fetch_url($data["poll"]);
if (!$feedret["success"]) {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
return false;
}
$doc = new DOMDocument();
@$doc->loadXML($feedret["body"]);
$xpath = new DomXPath($doc);
$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
$entries = $xpath->query('/atom:feed/atom:entry');
$last_updated = "";
foreach ($entries AS $entry) {
$published = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
$updated = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
if ($last_updated < $published)
$last_updated = $published;
if ($last_updated < $updated)
$last_updated = $updated;
}
// Maybe there aren't any entries. Then check if it is a valid feed
if ($last_updated == "")
if ($xpath->query('/atom:feed')->length > 0)
$last_updated = "0000-00-00 00:00:00";
q("UPDATE `gcontact` SET `updated` = '%s', `last_contact` = '%s' WHERE `nurl` = '%s'",
dbesc($last_updated), dbesc(datetime_convert()), dbesc(normalise_link($profile)));
if (($gcontacts[0]["generation"] == 0))
q("UPDATE `gcontact` SET `generation` = 9 WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
return($last_updated);
}
function poco_do_update($created, $updated, $last_failure, $last_contact) {
$now = strtotime(datetime_convert());
if ($updated > $last_contact)
$contact_time = strtotime($updated);
else
$contact_time = strtotime($last_contact);
$failure_time = strtotime($last_failure);
$created_time = strtotime($created);
// If there is no "created" time then use the current time
if ($created_time <= 0)
$created_time = $now;
// If the last contact was less than 24 hours then don't update
if (($now - $contact_time) < (60 * 60 * 24))
return false;
// If the last failure was less than 24 hours then don't update
if (($now - $failure_time) < (60 * 60 * 24))
return false;
// If the last contact was less than a week ago and the last failure is older than a week then don't update
//if ((($now - $contact_time) < (60 * 60 * 24 * 7)) AND ($contact_time > $failure_time))
// return false;
// If the last contact time was more than a week ago and the contact was created more than a week ago, then only try once a week
if ((($now - $contact_time) > (60 * 60 * 24 * 7)) AND (($now - $created_time) > (60 * 60 * 24 * 7)) AND (($now - $failure_time) < (60 * 60 * 24 * 7)))
return false;
// If the last contact time was more than a month ago and the contact was created more than a month ago, then only try once a month
if ((($now - $contact_time) > (60 * 60 * 24 * 30)) AND (($now - $created_time) > (60 * 60 * 24 * 30)) AND (($now - $failure_time) < (60 * 60 * 24 * 30)))
return false;
return true;
}
function poco_to_boolean($val) {
if (($val == "true") OR ($val == 1))
return(true);
if (($val == "false") OR ($val == 0))
return(false);
return ($val);
}
function poco_check_server($server_url, $network = "", $force = false) {
if ($server_url == "")
return false;
$servers = q("SELECT * FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url)));
if ($servers) {
if ($servers[0]["created"] == "0000-00-00 00:00:00")
q("UPDATE `gserver` SET `created` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($server_url)));
$poco = $servers[0]["poco"];
$noscrape = $servers[0]["noscrape"];
if ($network == "")
$network = $servers[0]["network"];
$last_contact = $servers[0]["last_contact"];
$last_failure = $servers[0]["last_failure"];
$version = $servers[0]["version"];
$platform = $servers[0]["platform"];
$site_name = $servers[0]["site_name"];
$info = $servers[0]["info"];
$register_policy = $servers[0]["register_policy"];
if (!$force AND !poco_do_update($servers[0]["created"], "", $last_failure, $last_contact)) {
logger("Use cached data for server ".$server_url, LOGGER_DEBUG);
return ($last_contact >= $last_failure);
}
} else {
$poco = "";
$noscrape = "";
$version = "";
$platform = "";
$site_name = "";
$info = "";
$register_policy = -1;
$last_contact = "0000-00-00 00:00:00";
$last_failure = "0000-00-00 00:00:00";
}
logger("Server ".$server_url." is outdated or unknown. Start discovery. Force: ".$force." Created: ".$servers[0]["created"]." Failure: ".$last_failure." Contact: ".$last_contact, LOGGER_DEBUG);
$failure = false;
$orig_last_failure = $last_failure;
// Check if the page is accessible via SSL.
$server_url = str_replace("http://", "https://", $server_url);
$serverret = z_fetch_url($server_url."/.well-known/host-meta");
// Maybe the page is unencrypted only?
$xmlobj = @simplexml_load_string($serverret["body"],'SimpleXMLElement',0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
if (!$serverret["success"] OR ($serverret["body"] == "") OR (@sizeof($xmlobj) == 0) OR !is_object($xmlobj)) {
$server_url = str_replace("https://", "http://", $server_url);
$serverret = z_fetch_url($server_url."/.well-known/host-meta");
$xmlobj = @simplexml_load_string($serverret["body"],'SimpleXMLElement',0, "http://docs.oasis-open.org/ns/xri/xrd-1.0");
}
if (!$serverret["success"] OR ($serverret["body"] == "") OR (sizeof($xmlobj) == 0) OR !is_object($xmlobj)) {
$last_failure = datetime_convert();
$failure = true;
} elseif ($network == NETWORK_DIASPORA)
$last_contact = datetime_convert();
if (!$failure) {
// Test for Diaspora
$serverret = z_fetch_url($server_url);
$lines = explode("\n",$serverret["header"]);
if(count($lines))
foreach($lines as $line) {
$line = trim($line);
if(stristr($line,'X-Diaspora-Version:')) {
$platform = "Diaspora";
$version = trim(str_replace("X-Diaspora-Version:", "", $line));
$version = trim(str_replace("x-diaspora-version:", "", $version));
$network = NETWORK_DIASPORA;
}
}
}
if (!$failure) {
// Test for Statusnet
// Will also return data for Friendica and GNU Social - but it will be overwritten later
// The "not implemented" is a special treatment for really, really old Friendica versions
$serverret = z_fetch_url($server_url."/api/statusnet/version.json");
if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND ($serverret["body"] != '') AND (strlen($serverret["body"]) < 250)) {
$platform = "StatusNet";
$version = trim($serverret["body"], '"');
$network = NETWORK_OSTATUS;
}
// Test for GNU Social
$serverret = z_fetch_url($server_url."/api/gnusocial/version.json");
if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND ($serverret["body"] != '') AND (strlen($serverret["body"]) < 250)) {
$platform = "GNU Social";
$version = trim($serverret["body"], '"');
$network = NETWORK_OSTATUS;
}
$serverret = z_fetch_url($server_url."/api/statusnet/config.json");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->site->server)) {
$last_contact = datetime_convert();
if (isset($data->site->hubzilla)) {
$platform = $data->site->hubzilla->PLATFORM_NAME;
$version = $data->site->hubzilla->RED_VERSION;
$network = NETWORK_DIASPORA;
}
if (isset($data->site->redmatrix)) {
if (isset($data->site->redmatrix->PLATFORM_NAME))
$platform = $data->site->redmatrix->PLATFORM_NAME;
elseif (isset($data->site->redmatrix->RED_PLATFORM))
$platform = $data->site->redmatrix->RED_PLATFORM;
$version = $data->site->redmatrix->RED_VERSION;
$network = NETWORK_DIASPORA;
}
if (isset($data->site->friendica)) {
$platform = $data->site->friendica->FRIENDICA_PLATFORM;
$version = $data->site->friendica->FRIENDICA_VERSION;
$network = NETWORK_DFRN;
}
$site_name = $data->site->name;
$data->site->closed = poco_to_boolean($data->site->closed);
$data->site->private = poco_to_boolean($data->site->private);
$data->site->inviteonly = poco_to_boolean($data->site->inviteonly);
if (!$data->site->closed AND !$data->site->private and $data->site->inviteonly)
$register_policy = REGISTER_APPROVE;
elseif (!$data->site->closed AND !$data->site->private)
$register_policy = REGISTER_OPEN;
else
$register_policy = REGISTER_CLOSED;
}
}
}
// Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix
if (!$failure) {
$serverret = z_fetch_url($server_url."/statistics.json");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if ($version == "")
$version = $data->version;
$site_name = $data->name;
if (isset($data->network) AND ($platform == ""))
$platform = $data->network;
if ($platform == "Diaspora")
$network = NETWORK_DIASPORA;
if ($data->registrations_open)
$register_policy = REGISTER_OPEN;
else
$register_policy = REGISTER_CLOSED;
if (isset($data->version))
$last_contact = datetime_convert();
}
}
// Check for noscrape
// Friendica servers could be detected as OStatus servers
if (!$failure AND in_array($network, array(NETWORK_DFRN, NETWORK_OSTATUS))) {
$serverret = z_fetch_url($server_url."/friendica/json");
if (!$serverret["success"])
$serverret = z_fetch_url($server_url."/friendika/json");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->version)) {
$last_contact = datetime_convert();
$network = NETWORK_DFRN;
$noscrape = $data->no_scrape_url;
$version = $data->version;
$site_name = $data->site_name;
$info = $data->info;
$register_policy_str = $data->register_policy;
$platform = $data->platform;
switch ($register_policy_str) {
case "REGISTER_CLOSED":
$register_policy = REGISTER_CLOSED;
break;
case "REGISTER_APPROVE":
$register_policy = REGISTER_APPROVE;
break;
case "REGISTER_OPEN":
$register_policy = REGISTER_OPEN;
break;
}
}
}
}
// Look for poco
if (!$failure) {
$serverret = z_fetch_url($server_url."/poco");
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->totalResults)) {
$poco = $server_url."/poco";
$last_contact = datetime_convert();
}
}
}
// Check again if the server exists
$servers = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url)));
if ($servers)
q("UPDATE `gserver` SET `url` = '%s', `version` = '%s', `site_name` = '%s', `info` = '%s', `register_policy` = %d, `poco` = '%s', `noscrape` = '%s',
`network` = '%s', `platform` = '%s', `last_contact` = '%s', `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc($server_url),
dbesc($version),
dbesc($site_name),
dbesc($info),
intval($register_policy),
dbesc($poco),
dbesc($noscrape),
dbesc($network),
dbesc($platform),
dbesc($last_contact),
dbesc($last_failure),
dbesc(normalise_link($server_url))
);
else
q("INSERT INTO `gserver` (`url`, `nurl`, `version`, `site_name`, `info`, `register_policy`, `poco`, `noscrape`, `network`, `platform`, `created`, `last_contact`, `last_failure`)
VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s')",
dbesc($server_url),
dbesc(normalise_link($server_url)),
dbesc($version),
dbesc($site_name),
dbesc($info),
intval($register_policy),
dbesc($poco),
dbesc($noscrape),
dbesc($network),
dbesc($platform),
dbesc(datetime_convert()),
dbesc($last_contact),
dbesc($last_failure),
dbesc(datetime_convert())
);
logger("End discovery for server ".$server_url, LOGGER_DEBUG);
return !$failure;
}
function poco_contact_from_body($body, $created, $cid, $uid) {
preg_replace_callback("/\[share(.*?)\].*?\[\/share\]/ism",
function ($match) use ($created, $cid, $uid){
@ -541,6 +1172,7 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
and not gcontact.name in ( select name from contact where uid = %d )
and not gcontact.id in ( select gcid from gcign where uid = %d )
AND `gcontact`.`updated` != '0000-00-00 00:00:00'
AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
AND `gcontact`.`network` IN (%s)
group by glink.gcid order by gcontact.updated desc,total desc limit %d, %d ",
intval($uid),
@ -587,16 +1219,20 @@ function update_suggestions() {
$done = array();
// To-Do: Check if it is really neccessary to poll the own server
poco_load(0,0,0,$a->get_baseurl() . '/poco');
$done[] = $a->get_baseurl() . '/poco';
if(strlen(get_config('system','directory_submit_url'))) {
$x = fetch_url('http://dir.friendica.com/pubsites');
if(strlen(get_config('system','directory'))) {
$x = fetch_url(get_server()."/pubsites");
if($x) {
$j = json_decode($x);
if($j->entries) {
foreach($j->entries as $entry) {
poco_check_server($entry->url);
$url = $entry->url . '/poco';
if(! in_array($url,$done))
poco_load(0,0,0,$entry->url . '/poco');
@ -605,8 +1241,9 @@ function update_suggestions() {
}
}
$r = q("select distinct(poco) as poco from contact where network = '%s'",
dbesc(NETWORK_DFRN)
// Query your contacts from Friendica and Redmatrix/Hubzilla for their contacts
$r = q("SELECT DISTINCT(`poco`) AS `poco` FROM `contact` WHERE `network` IN ('%s', '%s')",
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA)
);
if(count($r)) {
@ -617,3 +1254,205 @@ function update_suggestions() {
}
}
}
function poco_discover_federation() {
$last = get_config('poco','last_federation_discovery');
if($last) {
$next = $last + (24 * 60 * 60);
if($next > time())
return;
}
$serverdata = fetch_url("http://the-federation.info/pods.json");
if (!$serverdata)
return;
$servers = json_decode($serverdata);
foreach($servers->pods AS $server)
poco_check_server("https://".$server->host);
set_config('poco','last_federation_discovery', time());
}
function poco_discover($complete = false) {
// Update the server list
poco_discover_federation();
$no_of_queries = 5;
$requery_days = intval(get_config("system", "poco_requery_days"));
if ($requery_days == 0)
$requery_days = 7;
$last_update = date("c", time() - (60 * 60 * 24 * $requery_days));
$r = q("SELECT `poco`, `nurl`, `url`, `network` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `poco` != '' AND `last_poco_query` < '%s' ORDER BY RAND()", dbesc($last_update));
if ($r)
foreach ($r AS $server) {
if (!poco_check_server($server["url"], $server["network"])) {
// The server is not reachable? Okay, then we will try it later
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
continue;
}
// Fetch all users from the other server
$url = $server["poco"]."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,generation";
logger("Fetch all users from the server ".$server["nurl"], LOGGER_DEBUG);
$retdata = z_fetch_url($url);
if ($retdata["success"]) {
$data = json_decode($retdata["body"]);
poco_discover_server($data, 2);
if (get_config('system','poco_discovery') > 1) {
$timeframe = get_config('system','poco_discovery_since');
if ($timeframe == 0)
$timeframe = 30;
$updatedSince = date("Y-m-d H:i:s", time() - $timeframe * 86400);
// Fetch all global contacts from the other server (Not working with Redmatrix and Friendica versions before 3.3)
$url = $server["poco"]."/@global?updatedSince=".$updatedSince."&fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,generation";
$success = false;
$retdata = z_fetch_url($url);
if ($retdata["success"]) {
logger("Fetch all global contacts from the server ".$server["nurl"], LOGGER_DEBUG);
$success = poco_discover_server(json_decode($retdata["body"]));
}
if (!$success AND (get_config('system','poco_discovery') > 2)) {
logger("Fetch contacts from users of the server ".$server["nurl"], LOGGER_DEBUG);
poco_discover_server_users($data, $server);
}
}
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
if (!$complete AND (--$no_of_queries == 0))
break;
} else {
// If the server hadn't replied correctly, then force a sanity check
poco_check_server($server["url"], $server["network"], true);
// If we couldn't reach the server, we will try it some time later
q("UPDATE `gserver` SET `last_poco_query` = '%s' WHERE `nurl` = '%s'", dbesc(datetime_convert()), dbesc($server["nurl"]));
}
}
}
function poco_discover_server_users($data, $server) {
if (!isset($data->entry))
return;
foreach ($data->entry AS $entry) {
$username = "";
if (isset($entry->urls)) {
foreach($entry->urls as $url)
if($url->type == 'profile') {
$profile_url = $url->value;
$urlparts = parse_url($profile_url);
$username = end(explode("/", $urlparts["path"]));
}
}
if ($username != "") {
logger("Fetch contacts for the user ".$username." from the server ".$server["nurl"], LOGGER_DEBUG);
// Fetch all contacts from a given user from the other server
$url = $server["poco"]."/".$username."/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,gender,generation";
$retdata = z_fetch_url($url);
if ($retdata["success"])
poco_discover_server(json_decode($retdata["body"]), 3);
}
}
}
function poco_discover_server($data, $default_generation = 0) {
if (!isset($data->entry) OR !count($data->entry))
return false;
$success = false;
foreach ($data->entry AS $entry) {
$profile_url = '';
$profile_photo = '';
$connect_url = '';
$name = '';
$network = '';
$updated = '0000-00-00 00:00:00';
$location = '';
$about = '';
$keywords = '';
$gender = '';
$generation = $default_generation;
$name = $entry->displayName;
if(isset($entry->urls)) {
foreach($entry->urls as $url) {
if($url->type == 'profile') {
$profile_url = $url->value;
continue;
}
if($url->type == 'webfinger') {
$connect_url = str_replace('acct:' , '', $url->value);
continue;
}
}
}
if(isset($entry->photos)) {
foreach($entry->photos as $photo) {
if($photo->type == 'profile') {
$profile_photo = $photo->value;
continue;
}
}
}
if(isset($entry->updated))
$updated = date("Y-m-d H:i:s", strtotime($entry->updated));
if(isset($entry->network))
$network = $entry->network;
if(isset($entry->currentLocation))
$location = $entry->currentLocation;
if(isset($entry->aboutMe))
$about = html2bbcode($entry->aboutMe);
if(isset($entry->gender))
$gender = $entry->gender;
if(isset($entry->generation) AND ($entry->generation > 0))
$generation = ++$entry->generation;
if(isset($entry->tags))
foreach($entry->tags as $tag)
$keywords = implode(", ", $tag);
if ($generation > 0) {
$success = true;
logger("Store profile ".$profile_url, LOGGER_DEBUG);
poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, 0, 0, 0);
logger("Done for profile ".$profile_url, LOGGER_DEBUG);
}
}
return $success;
}
?>

View file

@ -470,11 +470,17 @@ if(! function_exists('item_new_uri')) {
* @param int $uid
* @return string
*/
function item_new_uri($hostname,$uid) {
function item_new_uri($hostname,$uid, $guid = "") {
do {
$dups = false;
$hash = random_string();
if ($guid == "")
$hash = get_guid(32);
else {
$hash = $guid;
$guid = "";
}
$uri = "urn:X-dfrn:" . $hostname . ':' . $uid . ':' . $hash;
@ -868,8 +874,14 @@ 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",
intval($a->profile['uid'])
$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
AND `network` IN ('%s', '%s', '%s')",
intval($a->profile['uid']),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_OSTATUS),
dbesc(NETWORK_DIASPORA)
);
if(count($r)) {
$total = intval($r[0]['total']);
@ -879,8 +891,14 @@ function contact_block() {
$micropro = Null;
} else {
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 AND `hidden` = 0 AND `archive` = 0 ORDER BY RAND() LIMIT %d",
$r = q("SELECT * FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0
AND `hidden` = 0 AND `archive` = 0
AND `network` IN ('%s', '%s', '%s') ORDER BY RAND() LIMIT %d",
intval($a->profile['uid']),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_OSTATUS),
dbesc(NETWORK_DIASPORA),
intval($shown)
);
if(count($r)) {
@ -968,16 +986,29 @@ if(! function_exists('search')) {
* @param string $url search url
* @param boolean $savedsearch show save search button
*/
function search($s,$id='search-box',$url='/search',$save = false) {
function search($s,$id='search-box',$url='/search',$save = false, $aside = true) {
$a = get_app();
return replace_macros(get_markup_template('searchbox.tpl'), array(
$values = array(
'$s' => $s,
'$id' => $id,
'$action_url' => $a->get_baseurl((stristr($url,'network')) ? true : false) . $url,
'$search_label' => t('Search'),
'$save_label' => t('Save'),
'$savedsearch' => feature_enabled(local_user(),'savedsearch'),
));
);
if (!$aside) {
$values['$searchoption'] = array(
t("Full Text"),
t("Tags"),
t("Contacts"));
if (get_config('system','poco_local_search'))
$values['$searchoption'][] = t("Forums");
}
return replace_macros(get_markup_template('searchbox.tpl'), $values);
}}
if(! function_exists('valid_email')) {
@ -1676,11 +1707,14 @@ function get_plink($item) {
//'href' => $a->get_baseurl()."/display/".$a->user['nickname']."/".$item['id'],
'href' => $a->get_baseurl()."/display/".$item['guid'],
'orig' => $a->get_baseurl()."/display/".$item['guid'],
'title' => t('link to source'),
'title' => t('View on separate page'),
'orig_title' => t('view on separate page'),
);
if (x($item,'plink'))
if (x($item,'plink')) {
$ret["href"] = $item['plink'];
$ret["title"] = t('link to source');
}
} elseif (x($item,'plink') && ($item['private'] != 1))
$ret = array(
@ -1773,7 +1807,7 @@ function return_bytes ($size_str) {
function generate_user_guid() {
$found = true;
do {
$guid = random_string(16);
$guid = get_guid(32);
$x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1",
dbesc($guid)
);

View file

@ -156,7 +156,9 @@ function import_account(&$a, $file) {
$newuid = last_insert_id();
//~ $newuid = 1;
// Generate a new guid for the account. Otherwise there will be problems with diaspora
q("UPDATE `user` SET `guid` = '%s' WHERE `uid` = %d",
dbesc(generate_user_guid()), intval($newuid));
foreach ($account['profile'] as &$profile) {
foreach ($profile as $k => &$v) {

View file

@ -27,11 +27,19 @@ function create_user($arr) {
$openid_url = ((x($arr,'openid_url')) ? notags(trim($arr['openid_url'])) : '');
$photo = ((x($arr,'photo')) ? notags(trim($arr['photo'])) : '');
$password = ((x($arr,'password')) ? trim($arr['password']) : '');
$password1 = ((x($arr,'password1')) ? trim($arr['password1']) : '');
$confirm = ((x($arr,'confirm')) ? trim($arr['confirm']) : '');
$blocked = ((x($arr,'blocked')) ? intval($arr['blocked']) : 0);
$verified = ((x($arr,'verified')) ? intval($arr['verified']) : 0);
$publish = ((x($arr,'profile_publish_reg') && intval($arr['profile_publish_reg'])) ? 1 : 0);
$netpublish = ((strlen(get_config('system','directory_submit_url'))) ? $publish : 0);
$netpublish = ((strlen(get_config('system','directory'))) ? $publish : 0);
if ($password1 != $confirm) {
$result['message'] .= t('Passwords do not match. Password unchanged.') . EOL;
return $result;
} elseif ($password1 != "")
$password = $password1;
$tmp_str = $openid_url;
@ -128,8 +136,8 @@ function create_user($arr) {
$nickname = $arr['nickname'] = strtolower($nickname);
if(! preg_match("/^[a-z][a-z0-9\-\_]*$/",$nickname))
$result['message'] .= t('Your "nickname" can only contain "a-z", "0-9", "-", and "_", and must also begin with a letter.') . EOL;
if(! preg_match("/^[a-z0-9][a-z0-9\_]*$/",$nickname))
$result['message'] .= t('Your "nickname" can only contain "a-z", "0-9" and "_".') . EOL;
$r = q("SELECT `uid` FROM `user`
WHERE `nickname` = '%s' LIMIT 1",
dbesc($nickname)

142
js/filebrowser.js Normal file
View file

@ -0,0 +1,142 @@
/**
* Filebrowser - Friendica Communications Server
*
* Copyright (c) 2010-2013 the Friendica Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This code handle user interaction for image/file upload/browser dialog.
* Is loaded from filebrowser_plain.tpl
*
* To load filebrowser in colorbox, call
*
* $.colorbox({href: ulr, iframe:true,innerWidth:'500px',innerHeight:'400px'})
*
* where url is:
*
* <baseurl>/fbrowser/<type>/?mode=minimal[#<eventname>-<id>]
*
* baseurl: baseurl from friendica
* type: one of "image", "file"
* eventname: event name to catch return value
* id: id returned to event handler
*
* When user select an item, an event in fired in parent page, on body element
* The event is named
*
* fbrowser.<type>.[<eventname>]
*
* with params:
*
* filemane: filename of item choosed by user
* embed: bbcode to embed element into posts
* id: id from url
*
* example:
*
* // open dialog for select an image for a textarea with id "myeditor"
* var id="myeditor";
* $.colorbox({href: baseurl + "/fbrowser/image/?mode=minimal#example-"+id, iframe:true,innerWidth:'500px',innerHeight:'400px'})
*
* // setup event handler to get user selection
* $("body").on("fbrowser.image.example", function(event, filename, bbcode, id) {
* // close colorbox
* $.colorbox.close();
* // replace textxarea text with bbcode
* $(id).value = bbcode;
* });
**/
var FileBrowser = {
nickname : "",
type : "",
event: "",
id : null,
init: function(nickname, type) {
FileBrowser.nickname = nickname;
FileBrowser.type = type;
FileBrowser.event = "fbrowser."+type;
if (location['hash']!=="") {
var h = location['hash'].replace("#","");
FileBrowser.event = FileBrowser.event + "." + h.split("-")[0];
FileBrowser.id = h.split("-")[1];
}
console.log("FileBrowser:", nickname, type,FileBrowser.event, FileBrowser.id );
$(".error a.close").on("click", function(e) {
e.preventDefault();
$(".error").addClass("hidden");
});
$(".folders a, .path a").on("click", function(e){
e.preventDefault();
var url = baseurl + "/fbrowser/" + FileBrowser.type + "/" + this.dataset.folder + "?mode=minimal" + location['hash'];
location.href = url;
});
$(".photo-album-photo-link").on('click', function(e){
e.preventDefault();
var embed = "";
if (FileBrowser.type == "image") {
embed = "[url="+this.dataset.link+"][img]"+this.dataset.img+"[/img][/url]";
}
if (FileBrowser.type=="file") {
// attachment links are "baseurl/attach/id"; we need id
embed = "[attachment]"+this.dataset.link.split("/").pop()+"[/attachment]";
}
console.log(FileBrowser.event, this.dataset.filename, embed, FileBrowser.id);
parent.$("body").trigger(FileBrowser.event, [
this.dataset.filename,
embed,
FileBrowser.id
]);
});
if ($("#upload-image").length)
var image_uploader = new window.AjaxUpload(
'upload-image',
{ action: 'wall_upload/'+FileBrowser.nickname+'?response=json',
name: 'userfile',
responseType: 'json',
onSubmit: function(file,ext) { $('#profile-rotator').show(); $(".error").addClass('hidden'); },
onComplete: function(file,response) {
if (response['error']!= undefined) {
$(".error span").html(response['error']);
$(".error").removeClass('hidden');
$('#profile-rotator').hide();
return;
}
location = baseurl + "/fbrowser/image/?mode=minimal"+location['hash'];
location.reload(true);
}
}
);
if ($("#upload-file").length)
var file_uploader = new window.AjaxUpload(
'upload-file',
{ action: 'wall_attach/'+FileBrowser.nickname+'?response=json',
name: 'userfile',
onSubmit: function(file,ext) { $('#profile-rotator').show(); $(".error").addClass('hidden'); },
onComplete: function(file,response) {
if (response['error']!= undefined) {
$(".error span").html(response['error']);
$(".error").removeClass('hidden');
$('#profile-rotator').hide();
return;
}
location = baseurl + "/fbrowser/file/?mode=minimal"+location['hash'];
location.reload(true);
}
}
);
}
};

View file

@ -51,6 +51,38 @@
e.tipTip({defaultPosition: pos, edgeOffset: 8});
});*/
/* setup comment textarea buttons */
/* comment textarea buttons needs some "data-*" attributes to work:
* data-role="insert-formatting" : to mark the element as a formatting button
* data-comment="<string>" : string for "Comment", used by insertFormatting() function
* data-bbcode="<string>" : name of the bbcode element to insert. insertFormatting() will insert it as "[name][/name]"
* data-id="<string>" : id of the comment, used to find other comment-related element, like the textarea
* */
$('body').on('click','[data-role="insert-formatting"]', function(e) {
e.preventDefault();
var o = $(this);
var comment = o.data('comment');
var bbcode = o.data('bbcode');
var id = o.data('id');
if (bbcode=="img") {
$.colorbox({href: baseurl + "/fbrowser/image/?mode=minimal#comment-"+id, iframe:true,innerWidth:'500px',innerHeight:'400px'})
return;
}
insertFormatting(comment, bbcode, id);
});
/* 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;
var end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start) + bbcode + textarea.value.substring(end, textarea.value.length);
});
/* setup onoff widgets */

View file

@ -1,5 +1,6 @@
<?php
require_once("mod/hostxrd.php");
require_once("mod/nodeinfo.php");
function _well_known_init(&$a){
if ($a->argc > 1) {
@ -7,8 +8,59 @@ function _well_known_init(&$a){
case "host-meta":
hostxrd_init($a);
break;
case "x-social-relay":
wk_social_relay($a);
break;
case "nodeinfo":
nodeinfo_wellknown($a);
break;
}
}
http_status_exit(404);
killme();
}
function wk_social_relay(&$a) {
define('SR_SCOPE_ALL', 'all');
define('SR_SCOPE_TAGS', 'tags');
$subscribe = (bool)get_config('system', 'relay_subscribe');
if ($subscribe)
$scope = get_config('system', 'relay_scope');
else
$scope = "";
$tags = array();
if ($scope == SR_SCOPE_TAGS) {
$server_tags = get_config('system', 'relay_server_tags');
$tagitems = explode(",", $server_tags);
foreach($tagitems AS $tag)
$tags[trim($tag, "# ")] = trim($tag, "# ");
if (get_config('system', 'relay_user_tags')) {
$terms = q("SELECT DISTINCT(`term`) FROM `search`");
foreach($terms AS $term) {
$tag = trim($term["term"], "#");
$tags[$tag] = $tag;
}
}
}
$taglist = array();
foreach($tags AS $tag)
$taglist[] = $tag;
$relay = array("subscribe" => $subscribe,
"scope" => $scope,
"tags" => $taglist);
header('Content-type: application/json; charset=utf-8');
echo json_encode($relay, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
exit;
}

View file

@ -106,6 +106,7 @@ function admin_content(&$a) {
'plugins'=> Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"),
'themes' => Array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"),
'dbsync' => Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync"),
'queue' => Array($a->get_baseurl(true)."/admin/queue/", t('Inspect Queue'), "queue"),
//'update' => Array($a->get_baseurl(true)."/admin/update/", t("Software Update") , "update")
);
@ -165,6 +166,9 @@ function admin_content(&$a) {
case 'update':
$o = admin_page_remoteupdate($a);
break;
case 'queue':
$o = admin_page_queue($a);
break;
default:
notice( t("Item not found.") );
}
@ -181,7 +185,30 @@ function admin_content(&$a) {
}
}
/**
* Admin Inspect Queue Page
* @param App $a
* return string
*/
function admin_page_queue(&$a) {
// get content from the queue table
$r = q("SELECT c.name,c.nurl,q.id,q.network,q.created,q.last from queue as q, contact as c where c.id=q.cid order by q.cid, q.created;");
$t = get_markup_template("admin_queue.tpl");
return replace_macros($t, array(
'$title' => t('Administration'),
'$page' => t('Inspect Queue'),
'$count' => sizeof($r),
'id_header' => t('ID'),
'$to_header' => t('Recipient Name'),
'$url_header' => t('Recipient Profile'),
'$network_header' => t('Network'),
'$created_header' => t('Created'),
'$last_header' => t('Last Tried'),
'$info' => t('This page lists the content of the queue for outgoing postings. These are postings the initial delivery failed for. They will be resend later and eventually deleted if the delivery fails permanently.'),
'$entries' => $r,
));
}
/**
* Admin Summary Page
* @param App $a
@ -226,6 +253,7 @@ function admin_page_summary(&$a) {
'$accounts' => $accounts,
'$pending' => Array( t('Pending registrations'), $pending),
'$version' => Array( t('Version'), FRIENDICA_VERSION),
'$baseurl' => $a->get_baseurl(),
'$platform' => FRIENDICA_PLATFORM,
'$codename' => FRIENDICA_CODENAME,
'$build' => get_config('system','build'),
@ -335,7 +363,7 @@ function admin_page_site_post(&$a){
$allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
$block_public = ((x($_POST,'block_public')) ? True : False);
$force_publish = ((x($_POST,'publish_all')) ? True : False);
$global_directory = ((x($_POST,'directory_submit_url')) ? notags(trim($_POST['directory_submit_url'])) : '');
$global_directory = ((x($_POST,'directory')) ? notags(trim($_POST['directory'])) : '');
$thread_allow = ((x($_POST,'thread_allow')) ? True : False);
$newuser_private = ((x($_POST,'newuser_private')) ? True : False);
$enotify_no_content = ((x($_POST,'enotify_no_content')) ? True : False);
@ -358,6 +386,12 @@ function admin_page_site_post(&$a){
$poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
$maxloadavg_frontend = ((x($_POST,'maxloadavg_frontend')) ? intval(trim($_POST['maxloadavg_frontend'])) : 50);
$poco_completion = ((x($_POST,'poco_completion')) ? intval(trim($_POST['poco_completion'])) : false);
$poco_requery_days = ((x($_POST,'poco_requery_days')) ? intval(trim($_POST['poco_requery_days'])) : 7);
$poco_discovery = ((x($_POST,'poco_discovery')) ? intval(trim($_POST['poco_discovery'])) : 0);
$poco_discovery_since = ((x($_POST,'poco_discovery_since')) ? intval(trim($_POST['poco_discovery_since'])) : 30);
$poco_local_search = ((x($_POST,'poco_local_search')) ? intval(trim($_POST['poco_local_search'])) : false);
$nodeinfo = ((x($_POST,'nodeinfo')) ? intval(trim($_POST['nodeinfo'])) : false);
$dfrn_only = ((x($_POST,'dfrn_only')) ? True : False);
$ostatus_disabled = !((x($_POST,'ostatus_disabled')) ? True : False);
$ostatus_poll_interval = ((x($_POST,'ostatus_poll_interval')) ? intval(trim($_POST['ostatus_poll_interval'])) : 0);
@ -380,6 +414,7 @@ function admin_page_site_post(&$a){
$old_pager = ((x($_POST,'old_pager')) ? True : False);
$only_tag_search = ((x($_POST,'only_tag_search')) ? True : False);
$rino = ((x($_POST,'rino')) ? intval($_POST['rino']) : 0);
$embedly = ((x($_POST,'embedly')) ? notags(trim($_POST['embedly'])) : '');
if($ssl_policy != intval(get_config('system','ssl_policy'))) {
@ -427,6 +462,12 @@ function admin_page_site_post(&$a){
set_config('system','poll_interval',$poll_interval);
set_config('system','maxloadavg',$maxloadavg);
set_config('system','maxloadavg_frontend',$maxloadavg_frontend);
set_config('system','poco_completion',$poco_completion);
set_config('system','poco_requery_days',$poco_requery_days);
set_config('system','poco_discovery',$poco_discovery);
set_config('system','poco_discovery_since',$poco_discovery_since);
set_config('system','poco_local_search',$poco_local_search);
set_config('system','nodeinfo',$nodeinfo);
set_config('config','sitename',$sitename);
set_config('config','hostname',$hostname);
set_config('config','sender_email', $sender_email);
@ -473,15 +514,7 @@ function admin_page_site_post(&$a){
set_config('system','allowed_email', $allowed_email);
set_config('system','block_public', $block_public);
set_config('system','publish_all', $force_publish);
if ($global_directory==""){
// don't know why, but del_config doesn't work...
q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc("system"),
dbesc("directory_submit_url")
);
} else {
set_config('system','directory_submit_url', $global_directory);
}
set_config('system','directory', $global_directory);
set_config('system','thread_allow', $thread_allow);
set_config('system','newuser_private', $newuser_private);
set_config('system','enotify_no_content', $enotify_no_content);
@ -518,7 +551,14 @@ function admin_page_site_post(&$a){
set_config('system','old_pager', $old_pager);
set_config('system','only_tag_search', $only_tag_search);
if ($rino==2 and !function_exists('mcrypt_create_iv')){
notice(t("RINO2 needs mcrypt php extension to work."));
} else {
set_config('system','rino_encrypt', $rino);
}
set_config('system','embedly', $embedly);
info( t('Site settings updated.') . EOL);
@ -535,7 +575,7 @@ function admin_page_site(&$a) {
/* Installed langs */
$lang_choices = array();
$langs = glob('view/*/strings.php');
$langs = glob('view/*/strings.php'); /**/
if(is_array($langs) && count($langs)) {
if(! in_array('view/en/strings.php',$langs))
@ -547,6 +587,12 @@ function admin_page_site(&$a) {
}
}
if (strlen(get_config('system','directory_submit_url')) AND
!strlen(get_config('system','directory'))) {
set_config('system','directory', dirname(get_config('system','directory_submit_url')));
del_config('system','directory_submit_url');
}
/* Installed themes */
$theme_choices = array();
$theme_choices_mobile = array();
@ -582,6 +628,20 @@ function admin_page_site(&$a) {
"1440" => t("Daily")
);
$poco_discovery_choices = array(
"0" => t("Disabled"),
"1" => t("Users"),
"2" => t("Users, Global Contacts"),
"3" => t("Users, Global Contacts/fallback"),
);
$poco_discovery_since_choices = array(
"30" => t("One month"),
"91" => t("Three months"),
"182" => t("Half a year"),
"365" => t("One year"),
);
/* get user names to make the install a personal install of X */
$user_names = array();
$user_names['---'] = t('Multi user instance');
@ -630,17 +690,18 @@ function admin_page_site(&$a) {
'$upload' => t('File upload'),
'$corporate' => t('Policies'),
'$advanced' => t('Advanced'),
'$portable_contacts' => t('Auto Discovered Contact Directory'),
'$performance' => t('Performance'),
'$relocate'=> t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
'$baseurl' => $a->get_baseurl(true),
// name, label, value, help string, extra data...
'$sitename' => array('sitename', t("Site name"), $a->config['sitename'],'UTF-8'),
'$sitename' => array('sitename', t("Site name"), $a->config['sitename'],''),
'$hostname' => array('hostname', t("Host name"), $a->config['hostname'], ""),
'$sender_email' => array('sender_email', t("Sender Email"), $a->config['sender_email'], "The email address your server shall use to send notification emails from.", "", "", "email"),
'$sender_email' => array('sender_email', t("Sender Email"), $a->config['sender_email'], t("The email address your server shall use to send notification emails from."), "", "", "email"),
'$banner' => array('banner', t("Banner/Logo"), $banner, ""),
'$shortcut_icon' => array('shortcut_icon', t("Shortcut icon"), get_config('system','shortcut_icon'), "Link to an icon that will be used for browsers."),
'$touch_icon' => array('touch_icon', t("Touch icon"), get_config('system','touch_icon'), "Link to an icon that will be used for tablets and mobiles."),
'$info' => array('info',t('Additional Info'), $info, t('For public servers: you can add additional information here that will be listed at dir.friendica.com/siteinfo.')),
'$shortcut_icon' => array('shortcut_icon', t("Shortcut icon"), get_config('system','shortcut_icon'), t("Link to an icon that will be used for browsers.")),
'$touch_icon' => array('touch_icon', t("Touch icon"), get_config('system','touch_icon'), t("Link to an icon that will be used for tablets and mobiles.")),
'$info' => array('info',t('Additional Info'), $info, sprintf(t('For public servers: you can add additional information here that will be listed at %s/siteinfo.'), get_server())),
'$language' => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
'$theme' => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
'$theme_mobile' => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile-theme'), t("Theme for mobile devices"), $theme_choices_mobile),
@ -661,7 +722,7 @@ function admin_page_site(&$a) {
'$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")),
'$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")),
'$force_publish' => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
'$global_directory' => array('directory_submit_url', t("Global directory update URL"), get_config('system','directory_submit_url'), t("URL to update the global directory. If this is not set, the global directory is completely unavailable to the application.")),
'$global_directory' => array('directory', t("Global directory URL"), get_config('system','directory'), t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")),
'$thread_allow' => array('thread_allow', t("Allow threaded items"), get_config('system','thread_allow'), t("Allow infinite level threading for items on this site.")),
'$newuser_private' => array('newuser_private', t("Private posts by default for new users"), get_config('system','newuser_private'), t("Set default post permissions for all new members to the default privacy group rather than public.")),
'$enotify_no_content' => array('enotify_no_content', t("Don't include post content in email notifications"), get_config('system','enotify_no_content'), t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")),
@ -687,22 +748,31 @@ function admin_page_site(&$a) {
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
'$maxloadavg_frontend' => array('maxloadavg_frontend', t("Maximum Load Average (Frontend)"), ((intval(get_config('system','maxloadavg_frontend')) > 0)?get_config('system','maxloadavg_frontend'):50), t("Maximum system load before the frontend quits service - default 50.")),
'$poco_completion' => array('poco_completion', t("Periodical check of global contacts"), get_config('system','poco_completion'), t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")),
'$poco_requery_days' => array('poco_requery_days', t("Days between requery"), get_config('system','poco_requery_days'), t("Number of days after which a server is requeried for his contacts.")),
'$poco_discovery' => array('poco_discovery', t("Discover contacts from other servers"), (string) intval(get_config('system','poco_discovery')), t("Periodically query other servers for contacts. You can choose between 'users': the users on the remote system, 'Global Contacts': active contacts that are known on the system. The fallback is meant for Redmatrix servers and older friendica servers, where global contacts weren't available. The fallback increases the server load, so the recommened setting is 'Users, Global Contacts'."), $poco_discovery_choices),
'$poco_discovery_since' => array('poco_discovery_since', t("Timeframe for fetching global contacts"), (string) intval(get_config('system','poco_discovery_since')), t("When the discovery is activated, this value defines the timeframe for the activity of the global contacts that are fetched from other servers."), $poco_discovery_since_choices),
'$poco_local_search' => array('poco_local_search', t("Search the local directory"), get_config('system','poco_local_search'), t("Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated.")),
'$nodeinfo' => array('nodeinfo', t("Publish server information"), get_config('system','nodeinfo'), t("If enabled, general server and usage data will be published. The data contains the name and version of the server, number of users with public profiles, number of posts and the activated protocols and connectors. See <a href='http://the-federation.info/'>the-federation.info</a> for details.")),
'$use_fulltext_engine' => array('use_fulltext_engine', t("Use MySQL full text engine"), get_config('system','use_fulltext_engine'), t("Activates the full text engine. Speeds up search - but can only search for four and more characters.")),
'$suppress_language' => array('suppress_language', t("Suppress Language"), get_config('system','suppress_language'), t("Suppress language information in meta information about a posting.")),
'$suppress_tags' => array('suppress_tags', t("Suppress Tags"), get_config('system','suppress_tags'), t("Suppress showing a list of hashtags at the end of the posting.")),
'$itemcache' => array('itemcache', t("Path to item cache"), get_config('system','itemcache'), "The item caches buffers generated bbcode and external images."),
'$itemcache' => array('itemcache', t("Path to item cache"), get_config('system','itemcache'), t("The item caches buffers generated bbcode and external images.")),
'$itemcache_duration' => array('itemcache_duration', t("Cache duration in seconds"), get_config('system','itemcache_duration'), t("How long should the cache files be hold? Default value is 86400 seconds (One day). To disable the item cache, set the value to -1.")),
'$max_comments' => array('max_comments', t("Maximum numbers of comments per post"), get_config('system','max_comments'), t("How much comments should be shown for each post? Default value is 100.")),
'$lockpath' => array('lockpath', t("Path for lock file"), get_config('system','lockpath'), "The lock file is used to avoid multiple pollers at one time. Only define a folder here."),
'$temppath' => array('temppath', t("Temp path"), get_config('system','temppath'), "If you have a restricted system where the webserver can't access the system temp path, enter another path here."),
'$basepath' => array('basepath', t("Base path to installation"), get_config('system','basepath'), "If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot."),
'$lockpath' => array('lockpath', t("Path for lock file"), get_config('system','lockpath'), t("The lock file is used to avoid multiple pollers at one time. Only define a folder here.")),
'$temppath' => array('temppath', t("Temp path"), get_config('system','temppath'), t("If you have a restricted system where the webserver can't access the system temp path, enter another path here.")),
'$basepath' => array('basepath', t("Base path to installation"), get_config('system','basepath'), t("If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot.")),
'$proxy_disabled' => array('proxy_disabled', t("Disable picture proxy"), get_config('system','proxy_disabled'), t("The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwith.")),
'$old_pager' => array('old_pager', t("Enable old style pager"), get_config('system','old_pager'), t("The old style pager has page numbers but slows down massively the page speed.")),
'$only_tag_search' => array('only_tag_search', t("Only search in tags"), get_config('system','only_tag_search'), t("On large systems the text search can slow down the system extremely.")),
'$relocate_url' => array('relocate_url', t("New base url"), $a->get_baseurl(), "Change base url for this server. Sends relocate message to all DFRN contacts of all users."),
'$relocate_url' => array('relocate_url', t("New base url"), $a->get_baseurl(), t("Change base url for this server. Sends relocate message to all DFRN contacts of all users.")),
'$rino' => array('rino', t("RINO Encryption"), intval(get_config('system','rino_encrypt')), t("Encryption layer between nodes."), array("Disabled", "RINO1 (deprecated)", "RINO2")),
'$embedly' => array('embedly', t("Embedly API key"), get_config('system','embedly'), t("<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for web pages. This is an optional parameter.")),
'$form_security_token' => get_form_security_token("admin_site")
@ -801,7 +871,7 @@ function admin_page_users_post(&$a){
$nu_nickname = ( x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : '');
$nu_email = ( x($_POST, 'new_user_email') ? $_POST['new_user_email'] : '');
check_form_security_token_redirectOnErr($a->get_baseurl().'/admin/users', 'admin_users');
check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
if (!($nu_name==="") && !($nu_email==="") && !($nu_nickname==="")) {
require_once('include/user.php');
@ -1136,6 +1206,13 @@ function admin_page_plugins(&$a){
* List plugins
*/
if (x($_GET,"a") && $_GET['a']=="r"){
check_form_security_token_redirectOnErr($a->get_baseurl().'/admin/plugins', 'admin_themes', 't');
reload_plugins();
info("Plugins reloaded");
goaway($a->get_baseurl().'/admin/plugins');
}
$plugins = array();
$files = glob("addon/*/"); /* */
if($files) {

View file

@ -114,6 +114,3 @@ function api_content(&$a) {
echo api_call($a);
killme();
}

View file

@ -206,15 +206,36 @@ function contacts_post(&$a) {
/*contact actions*/
function _contact_update($contact_id) {
$r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
if (!$r)
return;
$uid = $r[0]["uid"];
if ($uid != local_user())
return;
if ($r[0]["network"] == NETWORK_OSTATUS) {
$result = new_contact($uid, $r[0]["url"], false);
if ($result['success'])
$r = q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d",
intval($contact_id));
} else
// pull feed and consume it, which should subscribe to the hub.
proc_run('php',"include/poller.php","$contact_id");
proc_run('php',"include/onepoll.php","$contact_id", "force");
}
function _contact_update_profile($contact_id) {
$r = q("SELECT `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
$r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
if (!$r)
return;
$uid = $r[0]["uid"];
if ($uid != local_user())
return;
$data = probe_url($r[0]["url"]);
// "Feed" is mostly a sign of communication problems
@ -225,6 +246,13 @@ function _contact_update_profile($contact_id) {
"poco", "network", "alias", "pubkey");
$update = array();
if ($data["network"] == NETWORK_OSTATUS) {
$result = new_contact($uid, $data["url"], false);
if ($result['success'])
$update["subhub"] = true;
}
foreach($updatefields AS $field)
if (isset($data[$field]) AND ($data[$field] != ""))
$update[$field] = $data[$field];
@ -505,7 +533,7 @@ function contacts_content(&$a) {
$poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
$nettype = sprintf( t('Network type: %s'),network_to_name($contact['network']));
$nettype = sprintf( t('Network type: %s'),network_to_name($contact['network'], $contact["url"]));
$common = count_common_friends(local_user(),$contact['id']);
$common_text = (($common) ? sprintf( tt('%d contact in common','%d contacts in common', $common),$common) : '');
@ -522,12 +550,14 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/block',
'sel' => '',
'title' => t('Toggle Blocked status'),
'accesskey' => 'b',
),
array(
'label' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/ignore',
'sel' => '',
'title' => t('Toggle Ignored status'),
'accesskey' => 'i',
),
array(
@ -535,12 +565,14 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/archive',
'sel' => '',
'title' => t('Toggle Archive status'),
'accesskey' => 'v',
),
array(
'label' => t('Repair'),
'url' => $a->get_baseurl(true) . '/crepair/' . $contact_id,
'sel' => '',
'title' => t('Advanced Contact Settings'),
'accesskey' => 'r',
)
);
$tab_tpl = get_markup_template('common_tabs.tpl');
@ -605,6 +637,8 @@ function contacts_content(&$a) {
'$alt_text' => $alt_text,
'$sparkle' => $sparkle,
'$url' => $url,
'$profileurllabel' => t('Profile URL'),
'$profileurl' => $contact['url'],
));
@ -653,18 +687,21 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/suggest',
'sel' => '',
'title' => t('Suggest potential friends'),
'accesskey' => 'g',
),
array(
'label' => t('All Contacts'),
'url' => $a->get_baseurl(true) . '/contacts/all',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all contacts'),
'accesskey' => 'l',
),
array(
'label' => t('Unblocked'),
'url' => $a->get_baseurl(true) . '/contacts',
'sel' => ((! $all) && (! $blocked) && (! $hidden) && (! $search) && (! $nets) && (! $ignored) && (! $archived)) ? 'active' : '',
'title' => t('Only show unblocked contacts'),
'accesskey' => 'o',
),
array(
@ -672,6 +709,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked contacts'),
'accesskey' => 'b',
),
array(
@ -679,6 +717,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored contacts'),
'accesskey' => 'i',
),
array(
@ -686,6 +725,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived contacts'),
'accesskey' => 'y',
),
array(
@ -693,6 +733,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/hidden',
'sel' => ($hidden) ? 'active' : '',
'title' => t('Only show hidden contacts'),
'accesskey' => 'h',
),
);
@ -806,7 +847,7 @@ function _contact_detail_for_template($rr){
'sparkle' => $sparkle,
'itemurl' => $rr['url'],
'url' => $url,
'network' => network_to_name($rr['network']),
'network' => network_to_name($rr['network'], $rr['url']),
);
}

View file

@ -93,6 +93,8 @@ function dfrn_notify_post(&$a) {
$importer = $r[0];
logger("Remote rino version: ".$rino_remote." for ".$importer["url"], LOGGER_DEBUG);
if((($writable != (-1)) && ($writable != $importer['writable'])) || ($importer['forum'] != $forum) || ($importer['prv'] != $prv)) {
q("UPDATE `contact` SET `writable` = %d, forum = %d, prv = %d WHERE `id` = %d",
intval(($writable == (-1)) ? $importer['writable'] : $writable),
@ -128,10 +130,17 @@ function dfrn_notify_post(&$a) {
// If we are setup as a soapbox we aren't accepting input from this person
// This behaviour is deactivated since it really doesn't make sense to even disallow comments
// The check if someone is a friend or simply a follower is done in a later place so it needn't to be done here
//if($importer['page-flags'] == PAGE_SOAPBOX)
// xml_status(0);
if($importer['page-flags'] == PAGE_SOAPBOX)
xml_status(0);
$rino = get_config('system','rino_encrypt');
$rino = intval($rino);
// use RINO1 if mcrypt isn't installed and RINO2 was selected
if ($rino==2 and !function_exists('mcrypt_create_iv')) $rino=1;
logger("Local rino version: ". $rino, LOGGER_DEBUG);
if(strlen($key)) {
@ -273,6 +282,8 @@ function dfrn_notify_content(&$a) {
if(! count($r))
$status = 1;
logger("Remote rino version: ".$rino_remote." for ".$r[0]["url"], LOGGER_DEBUG);
$challenge = '';
$encrypted_id = '';
$id_str = $my_id . '.' . mt_rand(1000,9999);
@ -298,6 +309,10 @@ function dfrn_notify_content(&$a) {
$rino = get_config('system','rino_encrypt');
$rino = intval($rino);
// use RINO1 if mcrypt isn't installed and RINO2 was selected
if ($rino==2 and !function_exists('mcrypt_create_iv')) $rino=1;
logger("Local rino version: ". $rino, LOGGER_DEBUG);
// if requested rino is lower than enabled local rino, lower local rino version
// if requested rino is higher than enabled local rino, reply with local rino

View file

@ -836,7 +836,10 @@ function dfrn_request_content(&$a) {
//$emailnet = (($mail_disabled) ? '' : t("<strike>Connect as an email follower</strike> \x28Coming soon\x29"));
$emailnet = "";
$invite_desc = t('If you are not yet a member of the free social web, <a href="http://dir.friendica.com/siteinfo">follow this link to find a public Friendica site and join us today</a>.');
$invite_desc = sprintf(
t('If you are not yet a member of the free social web, <a href="%s/siteinfo">follow this link to find a public Friendica site and join us today</a>.'),
get_server()
);
$o .= replace_macros($tpl,array(
'$header' => t('Friend/Connection Request'),

View file

@ -47,7 +47,7 @@ function directory_content(&$a) {
$tpl = get_markup_template('directory_header.tpl');
$globaldir = '';
$gdirpath = dirname(get_config('system','directory_submit_url'));
$gdirpath = get_config('system','directory');
if(strlen($gdirpath)) {
$globaldir = '<ul><li><div id="global-directory-link"><a href="'
. zrl($gdirpath,true) . '">' . t('Global Directory') . '</a></div></li></ul>';

View file

@ -1,9 +1,9 @@
<?php
require_once('include/contact_widgets.php');
require_once('include/socgraph.php');
function dirfind_init(&$a) {
require_once('include/contact_widgets.php');
if(! x($a->page,'aside'))
$a->page['aside'] = '';
@ -14,13 +14,22 @@ function dirfind_init(&$a) {
function dirfind_content(&$a) {
function dirfind_content(&$a, $prefix = "") {
$search = notags(trim($_REQUEST['search']));
$community = false;
$local = get_config('system','poco_local_search');
$search = $prefix.notags(trim($_REQUEST['search']));
if(strpos($search,'@') === 0)
$search = substr($search,1);
if(strpos($search,'!') === 0) {
$search = substr($search,1);
$community = true;
}
$o = '';
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
@ -29,16 +38,73 @@ function dirfind_content(&$a) {
if($search) {
if ($local) {
if ($community)
$extra_sql = " AND `community`";
else
$extra_sql = "";
$perpage = 80;
$startrec = (($a->pager['page']) * $perpage) - $perpage;
$count = q("SELECT count(*) AS `total` FROM `gcontact` WHERE `network` IN ('%s', '%s', '%s') AND
(`url` REGEXP '%s' OR `name` REGEXP '%s' OR `location` REGEXP '%s' OR
`about` REGEXP '%s' OR `keywords` REGEXP '%s')".$extra_sql,
dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA),
dbesc(escape_tags($search)), dbesc(escape_tags($search)), dbesc(escape_tags($search)),
dbesc(escape_tags($search)), dbesc(escape_tags($search)));
$results = q("SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`photo`, `gcontact`.`keywords`
FROM `gcontact`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
WHERE `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)) AND
(`gcontact`.`url` REGEXP '%s' OR `gcontact`.`name` REGEXP '%s' OR `gcontact`.`location` REGEXP '%s' OR
`gcontact`.`about` REGEXP '%s' OR `gcontact`.`keywords` REGEXP '%s') $extra_sql
GROUP BY `gcontact`.`nurl`
ORDER BY `gcontact`.`updated` DESC LIMIT %d, %d",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA),
dbesc(escape_tags($search)), dbesc(escape_tags($search)), dbesc(escape_tags($search)),
dbesc(escape_tags($search)), dbesc(escape_tags($search)),
intval($startrec), intval($perpage));
$j = new stdClass();
$j->total = $count[0]["total"];
$j->items_page = $perpage;
$j->page = $a->pager['page'];
foreach ($results AS $result) {
if (poco_alternate_ostatus_url($result["url"]))
continue;
if ($result["name"] == "") {
$urlparts = parse_url($result["url"]);
$result["name"] = end(explode("/", $urlparts["path"]));
}
$objresult = new stdClass();
$objresult->cid = $result["cid"];
$objresult->name = $result["name"];
$objresult->url = $result["url"];
$objresult->photo = $result["photo"];
$objresult->tags = $result["keywords"];
$j->results[] = $objresult;
}
// Add found profiles from the global directory to the local directory
proc_run('php','include/discover_poco.php', "dirsearch", urlencode($search));
} else {
$p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : '');
if(strlen(get_config('system','directory_submit_url')))
$x = fetch_url('http://dir.friendica.com/lsearch?f=' . $p . '&search=' . urlencode($search));
//TODO fallback local search if global dir not available.
// else
// $x = post_url($a->get_baseurl() . '/lsearch', $params);
if(strlen(get_config('system','directory')))
$x = fetch_url(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search));
$j = json_decode($x);
}
if($j->total) {
$a->set_pager_total($j->total);
@ -50,11 +116,24 @@ function dirfind_content(&$a) {
$tpl = get_markup_template('match.tpl');
foreach($j->results as $jj) {
// If We already know this contact then don't show the "connect" button
if ($jj->cid > 0) {
$connlnk = "";
$conntxt = "";
} else {
$connlnk = $a->get_baseurl().'/follow/?url='.(($jj->connect) ? $jj->connect : $jj->url);
$conntxt = t('Connect');
}
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
$o .= replace_macros($tpl,array(
'$url' => zrl($jj->url),
'$name' => $jj->name,
'$photo' => $jj->photo,
'$tags' => $jj->tags
'$photo' => proxy_url($jj->photo),
'$tags' => $jj->tags,
'$conntxt' => $conntxt,
'$connlnk' => $connlnk,
));
}
}

View file

@ -18,7 +18,7 @@ function display_init(&$a) {
if (local_user()) {
$r = q("SELECT `id`, `parent`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid` FROM `item`
WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
AND `guid` = '%s' AND `uid` = %d", $a->argv[1], local_user());
AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
if (count($r)) {
$nick = $a->user["nickname"];
$itemuid = local_user();
@ -34,7 +34,7 @@ function display_init(&$a) {
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND `item`.`private` = 0 AND NOT `user`.`hidewall`
AND `item`.`guid` = '%s'", $a->argv[1]);
AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
// AND `item`.`private` = 0 AND `item`.`wall` = 1
if (count($r)) {
$nick = $r[0]["nickname"];
@ -50,7 +50,7 @@ function display_init(&$a) {
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND `item`.`private` = 0 AND `item`.`uid` = 0
AND `item`.`guid` = '%s'", $a->argv[1]);
AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
// AND `item`.`private` = 0 AND `item`.`wall` = 1
}
if (count($r)) {
@ -255,7 +255,7 @@ function display_content(&$a, $update = 0) {
if (local_user()) {
$r = q("SELECT `id` FROM `item`
WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
AND `guid` = '%s' AND `uid` = %d", $a->argv[1], local_user());
AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
if (count($r)) {
$item_id = $r[0]["id"];
$nick = $a->user["nickname"];
@ -268,7 +268,7 @@ function display_content(&$a, $update = 0) {
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND `item`.`private` = 0 AND NOT `user`.`hidewall`
AND `item`.`guid` = '%s'", $a->argv[1]);
AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
// AND `item`.`private` = 0 AND `item`.`wall` = 1
if (count($r)) {
$item_id = $r[0]["id"];
@ -281,7 +281,7 @@ function display_content(&$a, $update = 0) {
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND `item`.`private` = 0 AND `item`.`uid` = 0
AND `item`.`guid` = '%s'", $a->argv[1]);
AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
// AND `item`.`private` = 0 AND `item`.`wall` = 1
if (count($r)) {
$item_id = $r[0]["id"];
@ -351,7 +351,7 @@ function display_content(&$a, $update = 0) {
'default_location' => $a->user['default-location'],
'nickname' => $a->user['nickname'],
'lockstate' => ( (is_array($a->user)) && ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))) ? 'lock' : 'unlock'),
'acl' => populate_acl($a->user),
'acl' => populate_acl($a->user, true),
'bang' => '',
'visitor' => 'block',
'profile_uid' => local_user(),

View file

@ -18,11 +18,18 @@ function fbrowser_content($a){
if ($a->argc==1)
killme();
$template_file = "filebrowser.tpl";
$mode = "";
if (x($_GET,'mode')) {
$template_file = "filebrowser_plain.tpl";
$mode = "?mode=".$_GET['mode'];
}
//echo "<pre>"; var_dump($a->argv); killme();
switch($a->argv[1]){
case "image":
$path = array( array($a->get_baseurl()."/fbrowser/image/", t("Photos")));
$path = array( array("", t("Photos")));
$albums = false;
$sql_extra = "";
$sql_extra2 = " ORDER BY created DESC LIMIT 0, 10";
@ -32,8 +39,8 @@ function fbrowser_content($a){
intval(local_user())
);
// anon functions only from 5.3.0... meglio tardi che mai..
function folder1($el){return array(bin2hex($el['album']),$el['album']);}
$albums = array_map( "folder1" , $albums);
$folder1 = function($el) use ($mode) {return array(bin2hex($el['album']),$el['album']);};
$albums = array_map( $folder1 , $albums);
}
@ -42,11 +49,11 @@ function fbrowser_content($a){
$album = hex2bin($a->argv[2]);
$sql_extra = sprintf("AND `album` = '%s' ",dbesc($album));
$sql_extra2 = "";
$path[]=array($a->get_baseurl()."/fbrowser/image/".$a->argv[2]."/", $album);
$path[]=array($a->argv[2], $album);
}
$r = q("SELECT `resource-id`, `id`, `filename`, type, min(`scale`) AS `hiq`,max(`scale`) AS `loq`, `desc`
FROM `photo` WHERE `uid` = %d AND (height <= 320 AND width <= 320) $sql_extra
FROM `photo` WHERE `uid` = %d $sql_extra
GROUP BY `resource-id` $sql_extra2",
intval(local_user())
);
@ -64,21 +71,23 @@ function fbrowser_content($a){
}
return array(
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['hiq'] . '.' .$ext,
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '.' .$ext,
$filename_e,
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['loq'] . '.'. $ext
);
}
$files = array_map("files1", $r);
$tpl = get_markup_template("filebrowser.tpl");
echo replace_macros($tpl, array(
$tpl = get_markup_template($template_file);
$o = replace_macros($tpl, array(
'$type' => 'image',
'$baseurl' => $a->get_baseurl(),
'$path' => $path,
'$folders' => $albums,
'$files' =>$files,
'$cancel' => t('Cancel'),
'$nickname' => $a->user['nickname'],
));
@ -106,14 +115,15 @@ function fbrowser_content($a){
//echo "<pre>"; var_dump($files); killme();
$tpl = get_markup_template("filebrowser.tpl");
echo replace_macros($tpl, array(
$tpl = get_markup_template($template_file);
$o = replace_macros($tpl, array(
'$type' => 'file',
'$baseurl' => $a->get_baseurl(),
'$path' => array( array($a->get_baseurl()."/fbrowser/image/", t("Files")) ),
'$path' => array( array( "", t("Files")) ),
'$folders' => false,
'$files' =>$files,
'$cancel' => t('Cancel'),
'$nickname' => $a->user['nickname'],
));
}
@ -121,7 +131,12 @@ function fbrowser_content($a){
break;
}
if (x($_GET,'mode')) {
return $o;
} else {
echo $o;
killme();
}
}

View file

@ -2,6 +2,7 @@
require_once('include/Scrape.php');
require_once('include/follow.php');
require_once('include/contact_selectors.php');
function follow_content(&$a) {
@ -14,10 +15,12 @@ function follow_content(&$a) {
$uid = local_user();
$url = notags(trim($_REQUEST['url']));
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND
// There is a current issue. It seems as if you can't start following a Friendica that is following you
// With Diaspora this works - but Friendica is special, it seems ...
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND ((`rel` != %d) OR (`network` = '%s')) AND
(`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND
`network` != '%s' LIMIT 1",
intval(local_user()), dbesc(normalise_link($url)),
intval(local_user()), dbesc(CONTACT_IS_FOLLOWER), dbesc(NETWORK_DFRN), dbesc(normalise_link($url)),
dbesc(normalise_link($url)), dbesc($url), dbesc(NETWORK_STATUSNET));
if ($r) {
@ -28,6 +31,9 @@ function follow_content(&$a) {
$ret = probe_url($url);
if ($ret["network"] == NETWORK_MAIL)
$ret["url"] = $ret["addr"];
if($ret['network'] === NETWORK_DFRN) {
$request = $ret["request"];
$tpl = get_markup_template('dfrn_request.tpl');
@ -49,8 +55,15 @@ function follow_content(&$a) {
// Makes the connection request for friendica contacts easier
$_SESSION["fastlane"] = $ret["url"];
$header = $ret["name"];
if ($ret["addr"] != "")
$header .= " <".$ret["addr"].">";
$header .= " (".network_to_name($ret['network']).")";
$o = replace_macros($tpl,array(
'$header' => $ret["name"]." (".$ret["addr"].")",
'$header' => htmlentities($header),
'$photo' => $ret["photo"],
'$desc' => "",
'$pls_answer' => t('Please answer the following:'),

View file

@ -61,7 +61,7 @@ function friendica_content(&$a) {
$o .= t('Please visit <a href="http://friendica.com">Friendica.com</a> to learn more about the Friendica project.') . '</p><p>';
$o .= t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">the bucktracker at github</a></p><p>';
$o .= t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">'.t('the bugtracker at github').'</a></p><p>';
$o .= t('Suggestions, praise, donations, etc. - please email "Info" at Friendica - dot com') . '</p>';
$o .= '<p></p>';

View file

@ -392,6 +392,7 @@ function check_funcs(&$checks) {
check_add($ck_funcs, t('OpenSSL PHP module'), true, true, "");
check_add($ck_funcs, t('mysqli PHP module'), true, true, "");
check_add($ck_funcs, t('mb_string PHP module'), true, true, "");
check_add($ck_funcs, t('mcrypt PHP module'), true, true, "");
if(function_exists('apache_get_modules')){
@ -422,6 +423,12 @@ function check_funcs(&$checks) {
$ck_funcs[4]['status']= false;
$ck_funcs[4]['help']= t('Error: mb_string PHP module required but not installed.');
}
if(! function_exists('mcrypt_create_iv')){
$ck_funcs[5]['status']= false;
$ck_funcs[5]['help']= t('Error: mcrypt PHP module required but not installed.');
}
$checks = array_merge($checks, $ck_funcs);

View file

@ -114,13 +114,13 @@ function invite_content(&$a) {
}
}
$dirloc = get_config('system','directory_submit_url');
$dirloc = get_config('system','directory');
if(strlen($dirloc)) {
if($a->config['register_policy'] == REGISTER_CLOSED)
$linktxt = sprintf( t('Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks.'), dirname($dirloc) . '/siteinfo');
$linktxt = sprintf( t('Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks.'), $dirloc . '/siteinfo');
elseif($a->config['register_policy'] != REGISTER_CLOSED)
$linktxt = sprintf( t('To accept this invitation, please visit and register at %s or any other public Friendica website.'), $a->get_baseurl())
. "\r\n" . "\r\n" . sprintf( t('Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join.'),dirname($dirloc) . '/siteinfo');
. "\r\n" . "\r\n" . sprintf( t('Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join.'),$dirloc . '/siteinfo');
}
else {
$o = t('Our apologies. This system is not currently configured to connect with other public sites or invite members.');

View file

@ -674,7 +674,7 @@ function item_post(&$a) {
$notify_type = (($parent) ? 'comment-new' : 'wall-new' );
$uri = (($message_id) ? $message_id : item_new_uri($a->get_hostname(),$profile_uid));
$uri = (($message_id) ? $message_id : item_new_uri($a->get_hostname(),$profile_uid, $guid));
// Fallback so that we alway have a thr-parent
if(!$thr_parent)

View file

@ -1,5 +1,7 @@
<?php
include_once('include/text.php');
require_once('include/socgraph.php');
require_once('include/contact_widgets.php');
function match_content(&$a) {
@ -7,6 +9,9 @@ function match_content(&$a) {
if(! local_user())
return;
$a->page['aside'] .= follow_widget();
$a->page['aside'] .= findpeople_widget();
$_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd;
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
@ -32,8 +37,8 @@ function match_content(&$a) {
if($a->pager['page'] != 1)
$params['p'] = $a->pager['page'];
if(strlen(get_config('system','directory_submit_url')))
$x = post_url('http://dir.friendica.com/msearch', $params);
if(strlen(get_config('system','directory')))
$x = post_url(get_server().'/msearch', $params);
else
$x = post_url($a->get_baseurl() . '/msearch', $params);
@ -55,7 +60,7 @@ function match_content(&$a) {
intval(local_user()),
dbesc($match_nurl));
if (!count($match)) {
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
$connlnk = $a->get_baseurl() . '/follow/?url=' . $jj->url;
$o .= replace_macros($tpl,array(
'$url' => zrl($jj->url),
@ -68,8 +73,7 @@ function match_content(&$a) {
));
}
}
}
else {
} else {
info( t('No matches') . EOL);
}

View file

@ -9,6 +9,7 @@ function message_init(&$a) {
'label' => t('New Message'),
'url' => $a->get_baseurl(true) . '/message/new',
'sel'=> ($a->argv[1] == 'new'),
'accesskey' => 'm',
);
$tpl = get_markup_template('message_side.tpl');

View file

@ -359,12 +359,14 @@ function network_content(&$a, $update = 0) {
'url'=>$a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
'sel'=>$all_active,
'title'=> t('Sort by Comment Date'),
'accesskey' => "e",
),
array(
'label' => t('Posted Order'),
'url'=>$a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
'sel'=>$postord_active,
'title' => t('Sort by Post Date'),
'accesskey' => "t",
),
);
@ -374,6 +376,7 @@ function network_content(&$a, $update = 0) {
'url' => $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
'sel' => $conv_active,
'title' => t('Posts that mention or involve you'),
'accesskey' => "r",
);
}
@ -383,6 +386,7 @@ function network_content(&$a, $update = 0) {
'url' => $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ($len_naked_cmd ? '/' : '') . 'new' . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : ''),
'sel' => $new_active,
'title' => t('Activity Stream - by date'),
'accesskey' => "w",
);
}
@ -392,6 +396,7 @@ function network_content(&$a, $update = 0) {
'url'=>$a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&bmark=1',
'sel'=>$bookmarked_active,
'title'=> t('Interesting Links'),
'accesskey' => "b",
);
}
@ -401,6 +406,7 @@ function network_content(&$a, $update = 0) {
'url'=>$a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&star=1',
'sel'=>$starred_active,
'title' => t('Favourite Posts'),
'accesskey' => "m",
);
}

265
mod/nodeinfo.php Normal file
View file

@ -0,0 +1,265 @@
<?php
/*
Documentation: http://nodeinfo.diaspora.software/schema.html
*/
require_once("include/plugin.php");
function nodeinfo_wellknown(&$a) {
if (!get_config("system", "nodeinfo")) {
http_status_exit(404);
killme();
}
$nodeinfo = array("links" => array(array("rel" => "http://nodeinfo.diaspora.software/ns/schema/1.0",
"href" => $a->get_baseurl()."/nodeinfo/1.0")));
header('Content-type: application/json; charset=utf-8');
echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
exit;
}
function nodeinfo_init(&$a){
if (!get_config("system", "nodeinfo")) {
http_status_exit(404);
killme();
}
if (($a->argc != 2) OR ($a->argv[1] != "1.0")) {
http_status_exit(404);
killme();
}
$smtp = (function_exists("imap_open") AND !get_config("system","imap_disabled") AND !get_config("system","dfrn_only"));
$nodeinfo = array();
$nodeinfo["version"] = "1.0";
$nodeinfo["software"] = array("name" => "friendica", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
$nodeinfo["protocols"] = array();
$nodeinfo["protocols"]["inbound"] = array();
$nodeinfo["protocols"]["outbound"] = array();
if (get_config("system","diaspora_enabled")) {
$nodeinfo["protocols"]["inbound"][] = "diaspora";
$nodeinfo["protocols"]["outbound"][] = "diaspora";
}
$nodeinfo["protocols"]["inbound"][] = "friendica";
$nodeinfo["protocols"]["outbound"][] = "friendica";
if (!get_config("system","ostatus_disabled")) {
$nodeinfo["protocols"]["inbound"][] = "gnusocial";
$nodeinfo["protocols"]["outbound"][] = "gnusocial";
}
$nodeinfo["services"] = array();
$nodeinfo["services"]["inbound"] = array();
$nodeinfo["services"]["outbound"] = array();
$nodeinfo["openRegistrations"] = ($a->config['register_policy'] != 0);
$nodeinfo["usage"] = array();
$nodeinfo["usage"]["users"] = array("total" => (int)get_config("nodeinfo","total_users"),
"activeHalfyear" => (int)get_config("nodeinfo","active_users_halfyear"),
"activeMonth" => (int)get_config("nodeinfo","active_users_monthly"));
$nodeinfo["usage"]["localPosts"] = (int)get_config("nodeinfo","local_posts");
$nodeinfo["usage"]["localComments"] = (int)get_config("nodeinfo","local_comments");
$nodeinfo["metadata"] = array("nodeName" => $a->config["sitename"]);
if (nodeinfo_plugin_enabled("appnet"))
$nodeinfo["services"]["inbound"][] = "appnet";
if (nodeinfo_plugin_enabled("appnet") OR nodeinfo_plugin_enabled("buffer"))
$nodeinfo["services"]["outbound"][] = "appnet";
if (nodeinfo_plugin_enabled("blogger"))
$nodeinfo["services"]["outbound"][] = "blogger";
if (nodeinfo_plugin_enabled("dwpost"))
$nodeinfo["services"]["outbound"][] = "dreamwidth";
if (nodeinfo_plugin_enabled("fbpost") OR nodeinfo_plugin_enabled("buffer"))
$nodeinfo["services"]["outbound"][] = "facebook";
if (nodeinfo_plugin_enabled("statusnet")) {
$nodeinfo["services"]["inbound"][] = "gnusocial";
$nodeinfo["services"]["outbound"][] = "gnusocial";
}
if (nodeinfo_plugin_enabled("gpluspost") OR nodeinfo_plugin_enabled("buffer"))
$nodeinfo["services"]["outbound"][] = "google";
if (nodeinfo_plugin_enabled("ijpost"))
$nodeinfo["services"]["outbound"][] = "insanejournal";
if (nodeinfo_plugin_enabled("libertree"))
$nodeinfo["services"]["outbound"][] = "libertree";
if (nodeinfo_plugin_enabled("buffer"))
$nodeinfo["services"]["outbound"][] = "linkedin";
if (nodeinfo_plugin_enabled("ljpost"))
$nodeinfo["services"]["outbound"][] = "livejournal";
if (nodeinfo_plugin_enabled("buffer"))
$nodeinfo["services"]["outbound"][] = "pinterest";
if (nodeinfo_plugin_enabled("posterous"))
$nodeinfo["services"]["outbound"][] = "posterous";
if (nodeinfo_plugin_enabled("pumpio")) {
$nodeinfo["services"]["inbound"][] = "pumpio";
$nodeinfo["services"]["outbound"][] = "pumpio";
}
// redmatrix
if ($smtp)
$nodeinfo["services"]["outbound"][] = "smtp";
if (nodeinfo_plugin_enabled("tumblr"))
$nodeinfo["services"]["outbound"][] = "tumblr";
if (nodeinfo_plugin_enabled("twitter") OR nodeinfo_plugin_enabled("buffer"))
$nodeinfo["services"]["outbound"][] = "twitter";
if (nodeinfo_plugin_enabled("wppost"))
$nodeinfo["services"]["outbound"][] = "wordpress";
$nodeinfo["metadata"]["protocols"] = $nodeinfo["protocols"];
$nodeinfo["metadata"]["protocols"]["outbound"][] = "atom1.0";
$nodeinfo["metadata"]["protocols"]["inbound"][] = "atom1.0";
$nodeinfo["metadata"]["protocols"]["inbound"][] = "rss2.0";
$nodeinfo["metadata"]["services"] = $nodeinfo["services"];
if (nodeinfo_plugin_enabled("twitter"))
$nodeinfo["metadata"]["services"]["inbound"][] = "twitter";
header('Content-type: application/json; charset=utf-8');
echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
exit;
}
function nodeinfo_plugin_enabled($plugin) {
$r = q("SELECT * FROM `addon` WHERE `installed` = 1 AND `name` = '%s'", $plugin);
return((bool)(count($r) > 0));
}
function nodeinfo_cron() {
$a = get_app();
// If the plugin "statistics_json" is enabled then disable it and actrivate nodeinfo.
if (nodeinfo_plugin_enabled("statistics_json")) {
set_config("system", "nodeinfo", true);
$plugin = "statistics_json";
$plugins = get_config("system","addon");
$plugins_arr = array();
if($plugins) {
$plugins_arr = explode(",",str_replace(" ", "",$plugins));
$idx = array_search($plugin, $plugins_arr);
if ($idx !== false){
unset($plugins_arr[$idx]);
uninstall_plugin($plugin);
set_config("system","addon", implode(", ",$plugins_arr));
}
}
}
if (!get_config("system", "nodeinfo"))
return;
$last = get_config('nodeinfo','last_calucation');
if($last) {
// Calculate every 24 hours
$next = $last + (24 * 60 * 60);
if($next > time()) {
logger("calculation intervall not reached");
return;
}
}
logger("cron_start");
$users = q("SELECT profile.*, `user`.`login_date`, `lastitem`.`lastitem_date`
FROM (SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid`
FROM `item`
WHERE `item`.`type` = 'wall'
GROUP BY `item`.`uid`) AS `lastitem`
RIGHT OUTER JOIN `user` ON `user`.`uid` = `lastitem`.`uid`, `contact`, `profile`
WHERE
`user`.`uid` = `contact`.`uid` AND `profile`.`uid` = `user`.`uid`
AND `profile`.`is-default` AND (`profile`.`publish` OR `profile`.`net-publish`)
AND `user`.`verified` AND `contact`.`self`
AND NOT `user`.`blocked`
AND NOT `user`.`account_removed`
AND NOT `user`.`account_expired`");
if (is_array($users)) {
$total_users = count($users);
$active_users_halfyear = 0;
$active_users_monthly = 0;
$halfyear = time() - (180 * 24 * 60 * 60);
$month = time() - (30 * 24 * 60 * 60);
foreach ($users AS $user) {
if ((strtotime($user['login_date']) > $halfyear) OR
(strtotime($user['lastitem_date']) > $halfyear))
++$active_users_halfyear;
if ((strtotime($user['login_date']) > $month) OR
(strtotime($user['lastitem_date']) > $month))
++$active_users_monthly;
}
set_config('nodeinfo','total_users', $total_users);
logger("total_users: ".$total_users, LOGGER_DEBUG);
set_config('nodeinfo','active_users_halfyear', $active_users_halfyear);
set_config('nodeinfo','active_users_monthly', $active_users_monthly);
}
//$posts = q("SELECT COUNT(*) AS local_posts FROM `item` WHERE `wall` AND `uid` != 0 AND `id` = `parent` AND left(body, 6) != '[share'");
$posts = q("SELECT COUNT(*) AS `local_posts` FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `contact`.`self` and `item`.`id` = `item`.`parent` AND left(body, 6) != '[share' AND `item`.`network` IN ('%s', '%s', '%s')",
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_DFRN));
if (!is_array($posts))
$local_posts = -1;
else
$local_posts = $posts[0]["local_posts"];
set_config('nodeinfo','local_posts', $local_posts);
logger("local_posts: ".$local_posts, LOGGER_DEBUG);
$posts = q("SELECT COUNT(*) AS `local_comments` FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `contact`.`self` and `item`.`id` != `item`.`parent` AND `item`.`network` IN ('%s', '%s', '%s')",
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_DFRN));
if (!is_array($posts))
$local_comments = -1;
else
$local_comments = $posts[0]["local_comments"];
set_config('nodeinfo','local_comments', $local_comments);
// Now trying to register
$url = "http://the-federation.info/register/".$a->get_hostname();
logger('registering url: '.$url, LOGGER_DEBUG);
$ret = fetch_url($url);
logger('registering answer: '.$ret, LOGGER_DEBUG);
logger("cron_end");
set_config('nodeinfo','last_calucation', time());
}
?>

View file

@ -49,7 +49,7 @@ function nogroup_content(&$a) {
'sparkle' => $sparkle,
'itemurl' => $rr['url'],
'url' => $url,
'network' => network_to_name($rr['network']),
'network' => network_to_name($rr['network'], $url),
);
}
}

View file

@ -1,4 +1,5 @@
<?php
include_once("include/bbcode.php");
function notifications_post(&$a) {
@ -78,26 +79,31 @@ function notifications_content(&$a) {
'label' => t('System'),
'url'=>$a->get_baseurl(true) . '/notifications/system',
'sel'=> (($a->argv[1] == 'system') ? 'active' : ''),
'accesskey' => 'y',
),
array(
'label' => t('Network'),
'url'=>$a->get_baseurl(true) . '/notifications/network',
'sel'=> (($a->argv[1] == 'network') ? 'active' : ''),
'accesskey' => 'w',
),
array(
'label' => t('Personal'),
'url'=>$a->get_baseurl(true) . '/notifications/personal',
'sel'=> (($a->argv[1] == 'personal') ? 'active' : ''),
'accesskey' => 'r',
),
array(
'label' => t('Home'),
'url' => $a->get_baseurl(true) . '/notifications/home',
'sel'=> (($a->argv[1] == 'home') ? 'active' : ''),
'accesskey' => 'h',
),
array(
'label' => t('Introductions'),
'url' => $a->get_baseurl(true) . '/notifications/intros',
'sel'=> (($a->argv[1] == 'intros') ? 'active' : ''),
'accesskey' => 'i',
),
/*array(
'label' => t('Messages'),
@ -130,8 +136,13 @@ function notifications_content(&$a) {
$a->set_pager_itemspage(20);
}
$r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*, `fcontact`.`name` AS `fname`,`fcontact`.`url` AS `furl`,`fcontact`.`photo` AS `fphoto`,`fcontact`.`request` AS `frequest`
FROM `intro` LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id` LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
$r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*, `fcontact`.`name` AS `fname`,`fcontact`.`url` AS `furl`,`fcontact`.`photo` AS `fphoto`,`fcontact`.`request` AS `frequest`,
`gcontact`.`location` AS `glocation`, `gcontact`.`about` AS `gabout`,
`gcontact`.`keywords` AS `gkeywords`, `gcontact`.`gender` AS `ggender`
FROM `intro`
LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id`
LEFT JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl`
LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 ",
intval($_SESSION['uid']));
@ -203,8 +214,17 @@ function notifications_content(&$a) {
'$uid' => $_SESSION['uid'],
'$intro_id' => $rr['intro_id'],
'$contact_id' => $rr['contact-id'],
'$photo' => ((x($rr,'photo')) ? $rr['photo'] : "images/person-175.jpg"),
'$photo' => ((x($rr,'photo')) ? proxy_url($rr['photo']) : "images/person-175.jpg"),
'$fullname' => $rr['name'],
'$location_label' => t('Location:'),
'$location' => $rr['glocation'],
'$location_label' => t('Location:'),
'$about' => proxy_parse_html(bbcode($rr['gabout'], false, false)),
'$about_label' => t('About:'),
'$keywords' => $rr['gkeywords'],
'$keywords_label' => t('Tags:'),
'$gender' => $rr['ggender'],
'$gender_label' => t('Gender:'),
'$hidden' => array('hidden', t('Hide this contact from others'), ($rr['hidden'] == 1), ''),
'$activity' => array('activity', t('Post a new friend activity'), (intval(get_pconfig(local_user(),'system','post_newfriend')) ? '1' : 0), t('if applicable')),
'$url' => zrl($rr['url']),

78
mod/ostatus_subscribe.php Normal file
View file

@ -0,0 +1,78 @@
<?php
require_once('include/Scrape.php');
require_once('include/follow.php');
function ostatus_subscribe_content(&$a) {
if(! local_user()) {
notice( t('Permission denied.') . EOL);
goaway($_SESSION['return_url']);
// NOTREACHED
}
$o = "<h2>".t("Subsribing to OStatus contacts")."</h2>";
$uid = local_user();
$a = get_app();
$counter = intval($_REQUEST['counter']);
if (get_pconfig($uid, "ostatus", "legacy_friends") == "") {
if ($_REQUEST["url"] == "")
return $o.t("No contact provided.");
$contact = probe_url($_REQUEST["url"]);
if (!$contact)
return $o.t("Couldn't fetch information for contact.");
$api = $contact["baseurl"]."/api/";
// Fetching friends
$data = z_fetch_url($api."statuses/friends.json?screen_name=".$contact["nick"]);
if (!$data["success"])
return $o.t("Couldn't fetch friends for contact.");
set_pconfig($uid, "ostatus", "legacy_friends", $data["body"]);
}
$friends = json_decode(get_pconfig($uid, "ostatus", "legacy_friends"));
$total = sizeof($friends);
if ($counter >= $total) {
$a->page['htmlhead'] = '<meta http-equiv="refresh" content="0; URL='.$a->get_baseurl().'/settings/connectors">';
del_pconfig($uid, "ostatus", "legacy_friends");
del_pconfig($uid, "ostatus", "legacy_contact");
$o .= t("Done");
return $o;
}
$friend = $friends[$counter++];
$url = $friend->statusnet_profile_url;
$o .= "<p>".$counter."/".$total.": ".$url;
$data = probe_url($url);
if ($data["network"] == NETWORK_OSTATUS) {
$result = new_contact($uid,$url,true);
if ($result["success"])
$o .= " - ".t("success");
else
$o .= " - ".t("failed");
} else
$o .= " - ".t("ignored");
$o .= "</p>";
$o .= "<p>".t("Keep this window open until done.")."</p>";
$a->page['htmlhead'] = '<meta http-equiv="refresh" content="0; URL='.$a->get_baseurl().'/ostatus_subscribe?counter='.$counter.'">';
return $o;
}

View file

@ -19,7 +19,7 @@ function p_init($a){
$guid = strtolower(substr($guid, 0, -4));
$item = q("SELECT `body`, `guid`, `contact-id`, `private`, `created`, `app` FROM `item` WHERE `uid` = 0 AND `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
$item = q("SELECT `title`, `body`, `guid`, `contact-id`, `private`, `created`, `app` FROM `item` WHERE `uid` = 0 AND `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
if (!$item) {
header($_SERVER["SERVER_PROTOCOL"].' 404 '.t('Not Found'));
@ -39,8 +39,14 @@ function p_init($a){
$post["public"] = (!$item[0]["private"] ? 'true':'false');
$post["created_at"] = datetime_convert('UTC','UTC',$item[0]["created"]);
} else {
$body = bb2diaspora($item[0]["body"]);
if(strlen($item[0]["title"]))
$body = "## ".html_entity_decode($item[0]["title"])."\n\n".$body;
$nodename = "status_message";
$post["raw_message"] = str_replace("&", "&amp;", bb2diaspora($item[0]["body"]));
$post["raw_message"] = str_replace("&", "&amp;", $body);
$post["guid"] = $item[0]["guid"];
$post["diaspora_handle"] = diaspora_handle_from_contact($item[0]["contact-id"]);
$post["public"] = (!$item[0]["private"] ? 'true':'false');

View file

@ -50,6 +50,21 @@ function completeurl($url, $scheme) {
return($complete);
}
function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
$data = Cache::get("parse_url:".$no_guessing.":".$do_oembed.":".$url);
if (!is_null($data)) {
$data = unserialize($data);
return $data;
}
$data = parseurl_getsiteinfo($url, $no_guessing, $do_oembed);
Cache::set("parse_url:".$no_guessing.":".$do_oembed.":".$url,serialize($data), CACHE_DAY);
return $data;
}
function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
require_once("include/network.php");

View file

@ -61,12 +61,16 @@ function poco_init(&$a) {
$update_limit = date("Y-m-d H:i:s",strtotime($_GET['updatedSince']));
if ($global) {
$r = q("SELECT count(*) AS `total` FROM `gcontact` WHERE `updated` >= '%s' AND `network` IN ('%s')",
//$r = q("SELECT count(*) AS `total` FROM `gcontact` WHERE `updated` >= '%s' AND ((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND `network` IN ('%s')",
$r = q("SELECT count(*) AS `total` FROM `gcontact` WHERE `updated` >= '%s' AND `updated` >= `last_failure` AND `network` IN ('%s', '%s', '%s')",
dbesc($update_limit),
dbesc(NETWORK_DFRN)
dbesc(NETWORK_DFRN),
dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_OSTATUS)
);
} elseif($system_mode) {
$r = q("SELECT count(*) AS `total` FROM `contact` WHERE `self` = 1 AND `network` IN ('%s', '%s', '%s', '%s', '')
$r = q("SELECT count(*) AS `total` FROM `contact` WHERE `self` = 1 AND `network` IN ('%s', '%s', '%s', '%s')
AND (`success_update` >= `failure_update` OR `last-item` >= `failure_update`)
AND `uid` IN (SELECT `uid` FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1) ",
dbesc(NETWORK_DFRN),
dbesc(NETWORK_DIASPORA),
@ -75,7 +79,8 @@ function poco_init(&$a) {
);
} else {
$r = q("SELECT count(*) AS `total` FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
AND `network` IN ('%s', '%s', '%s', '%s', '') $sql_extra",
AND (`success_update` >= `failure_update` OR `last-item` >= `failure_update`)
AND `network` IN ('%s', '%s', '%s', '%s') $sql_extra",
intval($user['uid']),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_DIASPORA),
@ -93,19 +98,25 @@ function poco_init(&$a) {
$startIndex = 0;
$itemsPerPage = ((x($_GET,'count') && intval($_GET['count'])) ? intval($_GET['count']) : $totalResults);
if ($global) {
$r = q("SELECT * FROM `gcontact` WHERE `updated` > '%s' AND `network` IN ('%s') LIMIT %d, %d",
logger("Start global query", LOGGER_DEBUG);
//$r = q("SELECT * FROM `gcontact` WHERE `updated` > '%s' AND `network` IN ('%s') AND ((`last_contact` >= `last_failure`) OR (`updated` > `last_failure`)) LIMIT %d, %d",
$r = q("SELECT * FROM `gcontact` WHERE `updated` > '%s' AND `network` IN ('%s', '%s', '%s') AND `updated` > `last_failure`
ORDER BY `updated` DESC LIMIT %d, %d",
dbesc($update_limit),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_OSTATUS),
intval($startIndex),
intval($itemsPerPage)
);
} elseif($system_mode) {
logger("Start system mode query", LOGGER_DEBUG);
$r = q("SELECT `contact`.*, `profile`.`about` AS `pabout`, `profile`.`locality` AS `plocation`, `profile`.`pub_keywords`, `profile`.`gender` AS `pgender`,
`profile`.`address` AS `paddress`, `profile`.`region` AS `pregion`, `profile`.`postal-code` AS `ppostalcode`, `profile`.`country-name` AS `pcountry`
FROM `contact` INNER JOIN `profile` ON `profile`.`uid` = `contact`.`uid`
WHERE `self` = 1 AND `network` IN ('%s', '%s', '%s', '%s', '') AND `profile`.`is-default`
WHERE `self` = 1 AND `network` IN ('%s', '%s', '%s', '%s') AND `profile`.`is-default`
AND ((`contact`.`success_update` >= `contact`.`failure_update`) OR (`contact`.`last-item` >= `contact`.`failure_update`))
AND `contact`.`uid` IN (SELECT `uid` FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1) LIMIT %d, %d",
dbesc(NETWORK_DFRN),
dbesc(NETWORK_DIASPORA),
@ -115,8 +126,10 @@ function poco_init(&$a) {
intval($itemsPerPage)
);
} else {
logger("Start query for user ".$user['nickname'], LOGGER_DEBUG);
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
AND `network` IN ('%s', '%s', '%s', '%s', '') $sql_extra LIMIT %d, %d",
AND (`success_update` >= `failure_update` OR `last-item` >= `failure_update`)
AND `network` IN ('%s', '%s', '%s', '%s') $sql_extra LIMIT %d, %d",
intval($user['uid']),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_DIASPORA),
@ -126,6 +139,7 @@ function poco_init(&$a) {
intval($itemsPerPage)
);
}
logger("Query done", LOGGER_DEBUG);
$ret = array();
if(x($_GET,'sorted'))
@ -206,13 +220,19 @@ function poco_init(&$a) {
if (($rr['keywords'] == "") AND isset($rr['pub_keywords']))
$rr['keywords'] = $rr['pub_keywords'];
$about = Cache::get("about:".$rr['updated'].":".$rr['nurl']);
if (is_null($about)) {
$about = bbcode($rr['about'], false, false);
Cache::set("about:".$rr['updated'].":".$rr['nurl'],$about);
}
$entry = array();
if($fields_ret['id'])
$entry['id'] = (int)$rr['id'];
if($fields_ret['displayName'])
$entry['displayName'] = $rr['name'];
if($fields_ret['aboutMe'])
$entry['aboutMe'] = bbcode($rr['about'], false, false);
$entry['aboutMe'] = $about;
if($fields_ret['currentLocation'])
$entry['currentLocation'] = $rr['location'];
if($fields_ret['gender'])
@ -295,6 +315,8 @@ function poco_init(&$a) {
else
http_status_exit(500);
logger("End of poco", LOGGER_DEBUG);
if($format === 'xml') {
header('Content-type: text/xml');
echo replace_macros(get_markup_template('poco_xml.tpl'),array_xmlify(array('$response' => $ret)));

View file

@ -118,7 +118,7 @@ function profile_photo_post(&$a) {
info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
// Update global directory in background
$url = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
if($url && strlen(get_config('system','directory_submit_url')))
if($url && strlen(get_config('system','directory')))
proc_run('php',"include/directory.php","$url");
require_once('include/profile_update.php');
@ -217,7 +217,7 @@ function profile_photo_content(&$a) {
// Update global directory in background
$url = $_SESSION['my_url'];
if($url && strlen(get_config('system','directory_submit_url')))
if($url && strlen(get_config('system','directory')))
proc_run('php',"include/directory.php","$url");
goaway($a->get_baseurl() . '/profiles');

View file

@ -470,7 +470,8 @@ function profiles_post(&$a) {
if($namechanged && $is_default) {
$r = q("UPDATE `contact` SET `name-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
$r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
dbesc($name),
dbesc(datetime_convert()),
intval(local_user())
);
@ -507,7 +508,7 @@ function profiles_post(&$a) {
// Update global directory in background
$url = $_SESSION['my_url'];
if($url && strlen(get_config('system','directory_submit_url')))
if($url && strlen(get_config('system','directory')))
proc_run('php',"include/directory.php","$url");
require_once('include/profile_update.php');

View file

@ -63,10 +63,11 @@ function pubsub_init(&$a) {
intval($owner['uid'])
);
if(! count($r)) {
logger('pubsub: contact not found.');
logger('pubsub: contact '.$contact_id.' not found.');
hub_return(false, '');
}
if ($hub_topic)
if(! link_compare($hub_topic,$r[0]['poll'])) {
logger('pubsub: hub topic ' . $hub_topic . ' != ' . $r[0]['poll']);
// should abort but let's humour them.
@ -85,6 +86,7 @@ function pubsub_init(&$a) {
logger('pubsub: unsubscribe success');
}
if ($hub_mode)
$r = q("UPDATE `contact` SET `subhub` = %d WHERE `id` = %d",
intval($subscribe),
intval($contact['id'])

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