Merge branch 'develop' of https://github.com/friendica/friendica into develop

This commit is contained in:
Silke Meyer 2016-06-17 18:36:38 +02:00
commit e2f8673076
574 changed files with 88327 additions and 29519 deletions

View file

@ -136,8 +136,25 @@ $a->config['system']['addon'] = 'js_upload,poormancron';
and save your changes.
9. (Optional) Reverse-proxying and HTTPS
Friendica looks for some well-known HTTP headers indicating a reverse-proxy
terminating an HTTPS connection. While the standard from RFC 7239 specifies
the use of the `Forwaded` header.
Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2
Friendica also supports a number on non-standard headers in common use.
X-Forwarded-Proto: https
Front-End-Https: on
X-Forwarded-Ssl: on
It is however preferable to use the standard approach if configuring a new server.
#####################################################################
If things don't work...

110
boot.php
View file

@ -6,11 +6,11 @@
/**
* Friendica
*
*
* Friendica is a communications platform for integrated social communications
* utilising decentralised communications and linkage to several indie social
* projects - as well as popular mainstream providers.
*
*
* Our mission is to free our friends and families from the clutches of
* data-harvesting corporations, and pave the way to a future where social
* communications are free and open and flow between alternate providers as
@ -18,7 +18,7 @@
*/
require_once('include/autoloader.php');
require_once('include/config.php');
require_once('include/network.php');
require_once('include/plugin.php');
@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Asparagus');
define ( 'FRIENDICA_VERSION', '3.5-dev' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1194 );
define ( 'DB_UPDATE_VERSION', 1196 );
/**
* @brief Constant with a HTML line break.
@ -387,6 +387,10 @@ define ( 'GRAVITY_COMMENT', 6);
/* @}*/
// Normally this constant is defined - but not if "pcntl" isn't installed
if (!defined("SIGTERM"))
define("SIGTERM", 15);
/**
*
* Reverse the effect of magic_quotes_gpc if it is enabled.
@ -583,10 +587,15 @@ class App {
$this->scheme = 'http';
if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
$this->scheme = 'https';
elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
if((x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) ||
(x($_SERVER['HTTP_FORWARDED']) && preg_match("/proto=https/", $_SERVER['HTTP_FORWARDED'])) ||
(x($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(x($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') ||
(x($_SERVER['FRONT_END_HTTPS']) && $_SERVER['FRONT_END_HTTPS'] == 'on') ||
(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) // XXX: reasonable assumption, but isn't this hardcoding too much?
) {
$this->scheme = 'https';
}
if(x($_SERVER,'SERVER_NAME')) {
$this->hostname = $_SERVER['SERVER_NAME'];
@ -862,6 +871,9 @@ class App {
if ($touch_icon == "")
$touch_icon = "images/friendica-128.png";
// get data wich is needed for infinite scroll on the network page
$invinite_scroll = infinite_scroll_data($this->module);
$tpl = get_markup_template('head.tpl');
$this->page['htmlhead'] = replace_macros($tpl,array(
'$baseurl' => $this->get_baseurl(), // FIXME for z_path!!!!
@ -874,7 +886,8 @@ class App {
'$update_interval' => $interval,
'$shortcut_icon' => $shortcut_icon,
'$touch_icon' => $touch_icon,
'$stylesheet' => $stylesheet
'$stylesheet' => $stylesheet,
'$infinite_scroll' => $invinite_scroll,
)) . $this->page['htmlhead'];
}
@ -1515,20 +1528,20 @@ function login($register = false, $hiddens=false) {
$o .= replace_macros($tpl, array(
'$dest_url' => $dest_url,
'$logout' => t('Logout'),
'$login' => t('Login'),
'$dest_url' => $dest_url,
'$logout' => t('Logout'),
'$login' => t('Login'),
'$lname' => array('username', t('Nickname or Email address: ') , '', ''),
'$lname' => array('username', t('Nickname or Email: ') , '', ''),
'$lpassword' => array('password', t('Password: '), '', ''),
'$lremember' => array('remember', t('Remember me'), 0, ''),
'$openid' => !$noid,
'$lopenid' => array('openid_url', t('Or login using OpenID: '),'',''),
'$openid' => !$noid,
'$lopenid' => array('openid_url', t('Or login using OpenID: '),'',''),
'$hiddens' => $hiddens,
'$hiddens' => $hiddens,
'$register' => $reg,
'$register' => $reg,
'$lostpass' => t('Forgot your password?'),
'$lostlink' => t('Password Reset'),
@ -1888,31 +1901,6 @@ function is_site_admin() {
return false;
}
function load_contact_links($uid) {
$a = get_app();
$ret = array();
if(! $uid || x($a->contacts,'empty'))
return;
$r = q("SELECT `id`,`network`,`url`,`thumb`, `rel` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `thumb` != ''",
intval($uid)
);
if(count($r)) {
foreach($r as $rr){
$url = normalise_link($rr['url']);
$ret[$url] = $rr;
}
} else
$ret['empty'] = true;
$a->contacts = $ret;
return;
}
/**
* @brief Returns querystring as string from a mapped array.
*
@ -2201,3 +2189,43 @@ function argv($x) {
return '';
}
/**
* @brief Get the data which is needed for infinite scroll
*
* For invinite scroll we need the page number of the actual page
* and the the URI where the content of the next page comes from.
* This data is needed for the js part in main.js.
* Note: infinite scroll does only work for the network page (module)
*
* @param string $module The name of the module (e.g. "network")
* @return array Of infinite scroll data
* 'pageno' => $pageno The number of the actual page
* 'reload_uri' => $reload_uri The URI of the content we have to load
*/
function infinite_scroll_data($module) {
if (get_pconfig(local_user(),'system','infinite_scroll')
AND ($module == "network") AND ($_GET["mode"] != "minimal")) {
// get the page number
if (is_string($_GET["page"]))
$pageno = $_GET["page"];
else
$pageno = 1;
$reload_uri = "";
// try to get the uri from which we load the content
foreach ($_GET AS $param => $value)
if (($param != "page") AND ($param != "q"))
$reload_uri .= "&".$param."=".urlencode($value);
if (($a->page_offset != "") AND !strstr($reload_uri, "&offset="))
$reload_uri .= "&offset=".urlencode($a->page_offset);
$arr = array("pageno" => $pageno, "reload_uri" => $reload_uri);
return $arr;
}
}

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 3.5-dev (Asparagus)
-- DB_UPDATE_VERSION 1194
-- DB_UPDATE_VERSION 1196
-- ------------------------------------------
@ -171,7 +171,8 @@ CREATE TABLE IF NOT EXISTS `contact` (
`fetch_further_information` tinyint(1) NOT NULL DEFAULT 0,
`ffi_keyword_blacklist` mediumtext NOT NULL,
PRIMARY KEY(`id`),
INDEX `uid` (`uid`)
INDEX `uid` (`uid`),
INDEX `nurl` (`nurl`)
) DEFAULT CHARSET=utf8;
--
@ -201,17 +202,6 @@ CREATE TABLE IF NOT EXISTS `deliverq` (
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
--
-- TABLE dsprphotoq
--
CREATE TABLE IF NOT EXISTS `dsprphotoq` (
`id` int(10) unsigned NOT NULL auto_increment,
`uid` int(11) NOT NULL DEFAULT 0,
`msg` mediumtext NOT NULL,
`attempt` tinyint(4) NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
) DEFAULT CHARSET=utf8;
--
-- TABLE event
--
@ -345,6 +335,9 @@ CREATE TABLE IF NOT EXISTS `gcontact` (
`server_url` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
INDEX `nurl` (`nurl`),
INDEX `name` (`name`),
INDEX `nick` (`nick`),
INDEX `addr` (`addr`),
INDEX `updated` (`updated`)
) DEFAULT CHARSET=utf8;
@ -518,7 +511,7 @@ CREATE TABLE IF NOT EXISTS `item` (
INDEX `extid` (`extid`),
INDEX `uid_id` (`uid`,`id`),
INDEX `uid_created` (`uid`,`created`),
INDEX `uid_unseen` (`uid`,`unseen`),
INDEX `uid_unseen_contactid` (`uid`,`unseen`,`contact-id`),
INDEX `uid_network_received` (`uid`,`network`,`received`),
INDEX `uid_received` (`uid`,`received`),
INDEX `uid_network_commented` (`uid`,`network`,`commented`),
@ -912,13 +905,11 @@ CREATE TABLE IF NOT EXISTS `session` (
CREATE TABLE IF NOT EXISTS `sign` (
`id` int(10) unsigned NOT NULL auto_increment,
`iid` int(10) unsigned NOT NULL DEFAULT 0,
`retract_iid` int(10) unsigned NOT NULL DEFAULT 0,
`signed_text` mediumtext NOT NULL,
`signature` text NOT NULL,
`signer` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY(`id`),
INDEX `iid` (`iid`),
INDEX `retract_iid` (`retract_iid`)
INDEX `iid` (`iid`)
) DEFAULT CHARSET=utf8;
--

View file

@ -281,6 +281,11 @@ $b is an array with:
'template' => filename of template
'vars' => array of vars passed to template
### ''acl_lookup_end'
is called after the other queries have passed.
The registered function can add, change or remove the acl_lookup() variables.
'results' => array of the acl_lookup() vars
Complete list of hook callbacks
@ -338,6 +343,8 @@ include/acl_selectors.php: call_hooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: call_hooks($a->module . '_post_' . $selname, $o);
include/acl_selectors.php call_hooks('acl_lookup_end', $results);
include/notifier.php: call_hooks('notifier_normal',$target_item);
include/notifier.php: call_hooks('notifier_end',$target_item);

View file

@ -1,176 +1,105 @@
Settings
===
Here are some of the built-in features which don't have an exposed interface or are otherwise undocumented.
Configuration settings are stored in the file ".htconfig.php".
Edit this file with a text editor to make the desired changes.
Several system settings are already documented in that file and will not be covered here.
# Settings
Hot Keys
---
If you are the admin of a Friendica node, you have access to the so called **Admin Panel** where you can configure your Friendica node.
Friendica traps the following keyboard events:
On the front page of the admin panel you will see a summary of information about your node.
These information include the amount of messages currently being processed in the queues.
The first number is the number of messages being actively sent.
This number should decrease quickly.
The second is the messages which could for various reasons not being delivered.
They will be resend later.
You can have a quick glance into that second queus in the "Inspect Queue" section of the admin panel.
If you have activated the background workers, there might be a third number representing the count of jobs queued for the workers.
* [Pause] - Pauses "Ajax" update activity. This is the process that provides updates without reloading the page. You may wish to pause it to reduce network usage and/or as a debugging aid for javascript developers. A pause indicator will appear at the lower right hand corner of the page. Hit the [pause] key once again to resume.
Then you get an overview of the accounts on your node, which can be moderated in the "Users" section of the panel.
As well as an overview of the currently active addons
The list is linked, so you can have quick access to the plugin settings.
And finally you are informed about the version of Friendica you have installed.
If you contact the devs with a bug or problem, please also mention the version of your node.
Birthday Notifications
---
The admin panel is seperated into subsections accessible from the side bar of the panel.
Birthday events are published on your Home page for any friends having a birthday in the coming 6 days.
In order for your birthday to be discoverable by all of your friends, you must set your birthday (at least the month and day) in your default profile.
You are not required to provide the year.
## Site
System settings
---
This section of the admin panel contains the main configuration of your Friendica node.
It is separated into several sub-section beginning with the basic settings at the top, advancing towards the bottom of the page.
**Settings should be done in the admin panel** (/admin).
Those settings found in the database, will always override the settings added to the ``.htconfig.php`` file.
Most configuration options have a help text in the admin panel.
Therefore this document does not yet cover all the options
###Language
### Basic Settings
Please see util/README for information on creating language translations.
Config:
$a->config['system']['language'] = 'name';
###System Theme
Choose a theme to be the default system theme. This can be over-ridden by user profiles.
Default theme is "default".
Config:
$a->config['system']['theme'] = 'theme-name';
###Proxy Configuration Settings
If your site uses a proxy to connect to the internet, you may use these settings to communicate with the outside world.
The outside world still needs to be able to see your website, or this will not be very useful.
Config:
$a->config['system']['proxy'] = "http://proxyserver.domain:port";
$a->config['system']['proxyuser'] = "username:password";
###Network Timeout
How long to wait on a network communication before timing out.
Value is in seconds.
Default is 60 seconds.
Set to 0 for unlimited (not recommended).
Config:
$a->config['system']['curl_timeout'] = 60;
###Banner/Logo
#### Banner/Logo
Set the content for the site banner.
The default logo is the Friendica logo and name.
You may wish to provide HTML/CSS to style and/or position this content, as it may not be themed by default.
Config:
#### Language
$a->config['system']['banner'] = '<span id="logo-text">My Great Website</span>';
This option will set the default language for the node.
It is used as fall back setting should Friendica fail to recognize the visitors preferences and can be overwritten by user settings.
###Maximum Image Size
The Friendica community offers some translations.
Some more compleate then others.
See [this help page](/help/translations) for more information about the translation process.
Maximum size in bytes of uploaded images.
The default is set to 0, which means no limits.
#### System Theme
Config:
Choose a theme to be the default system theme.
This can be over-ridden by user profiles.
Default theme is "duepunto zero" at the moment.
$a->config['system']['maximagesize'] = 1000000;
You may also want to set a special theme for mobile interfaces.
Which may or may not be neccessary depending of the mobile friendlyness of the desktop theme you have chosen.
The `vier` theme for instance is mobile friendly.
###UTF-8 Regular Expressions
### Registration
During registrations, full names are checked using UTF-8 regular expressions.
This requires PHP to have been compiled with a special setting to allow UTF-8 expressions.
If you are completely unable to register accounts, set no_utf to true.
The default is set to false (meaning UTF8 regular expressions are supported and working).
Config:
$a->config['system']['no_utf'] = true;
###Check Full Names
#### Check Full Names
You may find a lot of spammers trying to register on your site.
During testing we discovered that since these registrations were automatic, the "Full Name" field was often set to just an account name with no space between first and last name.
If you would like to support people with only one name as their full name, you may change this setting to true.
Default is false.
Config:
$a->config['system']['no_regfullname'] = true;
###OpenID
#### OpenID
By default, OpenID may be used for both registration and logins.
If you do not wish to make OpenID facilities available on your system (at all), set 'no_openid' to true.
Default is false.
Config:
$a->config['system']['no_openid'] = true;
###Multiple Registrations
#### Multiple Registrations
The ability to create "Pages" requires a person to register more than once.
Your site configuration can block registration (or require approval to register).
By default, logged in users can register additional accounts for use as pages.
These will still require approval if REGISTER_APPROVE is selected.
You may prohibit logged in users from creating additional accounts by setting 'block_extended_register' to true.
These will still require approval if the registration policy is set to *require approval*
You may prohibit logged in users from creating additional accounts by setting *block multible registrations* to true.
Default is false.
Config:
### File upload
$a->config['system']['block_extended_register'] = true;
#### Maximum Image Size
Security settings
---
Maximum size in bytes of uploaded images.
The default is set to 0, which means no limits.
###Verify SSL Certitificates
### Policies
By default Friendica allows SSL communication between websites that have "self-signed" SSL certificates.
For the widest compatibility with browsers and other networks we do not recommend using self-signed certificates, but we will not prevent you from using them.
SSL encrypts all the data transmitted between sites (and to your browser). This allows you to have completely encrypted communications, and also protect your login session from hijacking.
Self-signed certificates can be generated for free, without paying top-dollar for a website SSL certificate.
However these aren't looked upon favourably in the security community because they can be subject to so-called "man-in-the-middle" attacks.
If you wish, you can turn on strict certificate checking.
This will mean you cannot connect (at all) to self-signed SSL sites.
#### Global Directory
Config:
This configures the URL to update the global directory, and is supplied in the default configuration.
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 network.
$a->config['system']['verifyssl'] = true;
#### Force Publish
Corporate/Edu enhancements
---
By default, each user can choose on their Settings page whether or not to have their profile published in the site directory.
This setting forces all profiles on this site to be listed in the site directory and there is no option provided to the user to change it.
Default is false.
###Allowed Friend Domains
Comma separated list of domains which are allowed to establish friendships with this site.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) domain may establish friendships with this site.
Config:
$a->config['system']['allowed_sites'] = "sitea.com, *siteb.com";
###Allowed Email Domains
Comma separated list of domains which are allowed in email addresses for registrations to this site.
This can lockout those who are not part of this organisation from registering here.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) email address is allowed in registrations.
Config:
$a->config['system']['allowed_email'] = "sitea.com, *siteb.com";
###Block Public
#### Block Public
Set to true to block public access to all otherwise public personal pages on this site unless you are currently logged in.
This blocks the viewing of profiles, friends, photos, the site directory and search pages to unauthorised persons.
@ -180,51 +109,164 @@ Note: this is specifically for sites that desire to be "standalone" and do not w
Unauthorised persons will also not be able to request friendship with site members.
Default is false.
Available in version 2.2 or greater.
Config:
$a->config['system']['block_public'] = true;
#### Allowed Friend Domains
###Force Publish
Comma separated list of domains which are allowed to establish friendships with this site.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) domain may establish friendships with this site.
By default, each user can choose on their Settings page whether or not to have their profile published in the site directory.
This setting forces all profiles on this site to be listed in the site directory and there is no option provided to the user to change it.
Default is false.
Config:
This is useful if you want to setup a closed network for educational groups, cooperations and similar communities that don't want to commuicate with the rest of the network.
$a->config['system']['publish_all'] = true;
#### Allowed Email Domains
###Global Directory
Comma separated list of domains which are allowed in email addresses for registrations to this site.
This can lockout those who are not part of this organisation from registering here.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) email address is allowed in registrations.
This configures the URL to update the global directory, and is supplied in the default configuration.
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 network.
#### Allow Users to set remote_self
$a->config['system']['directory'] = 'http://dir.friendi.ca';
If you enable the `Allow Users to set remote_self` users can select Atom feeds from their contact list being their *remote self* in die advanced contact settings.
Which means that postings by the remote self are automatically reposted by Friendica in their names.
Developer Settings
---
As admin of the node you can also set this flag directly in the database.
Before doing so, you should be sure you know what you do and have a backup of the database.
### Debugging
Most useful when debugging protocol exchanges and tracking down other communications issues.
### Advanced
Config:
#### Proxy Configuration Settings
$a->config['system']['debugging'] = true;
$a->config['system']['logfile'] = 'logfile.out';
$a->config['system']['loglevel'] = LOGGER_DEBUG;
If your site uses a proxy to connect to the internet, you may use these settings to communicate with the outside world.
The outside world still needs to be able to see your website, or this will not be very useful.
Turns on detailed debugging logs which will be stored in 'logfile.out' (which must be writeable by the webserver).
LOGGER_DEBUG will show a good deal of information about system activity but will not include detailed data.
You may also select LOGGER_ALL but due to the volume of information we recommend only enabling this when you are tracking down a specific problem.
Other log levels are possible but are not being used at the present time.
#### Network Timeout
Please be aware that turning on the logging can fill up the disk space on your server relatively quick.
You should take preventions with e.g. [logrotate](https://en.wikipedia.org/wiki/Log_rotation) or similar tools.
How long to wait on a network communication before timing out.
Value is in seconds.
Default is 60 seconds.
Set to 0 for unlimited (not recommended).
###PHP error logging
#### UTF-8 Regular Expressions
During registrations, full names are checked using UTF-8 regular expressions.
This requires PHP to have been compiled with a special setting to allow UTF-8 expressions.
If you are completely unable to register accounts, set no_utf to true.
The default is set to false (meaning UTF8 regular expressions are supported and working).
#### Verify SSL Certitificates
By default Friendica allows SSL communication between websites that have "self-signed" SSL certificates.
For the widest compatibility with browsers and other networks we do not recommend using self-signed certificates, but we will not prevent you from using them.
SSL encrypts all the data transmitted between sites (and to your browser).
This allows you to have completely encrypted communications, and also protect your login session from hijacking.
Self-signed certificates can be generated for free, without paying top-dollar for a website SSL certificate.
However these aren't looked upon favourably in the security community because they can be subject to so-called "man-in-the-middle" attacks.
If you wish, you can turn on strict certificate checking.
This will mean you cannot connect (at all) to self-signed SSL sites.
### Auto Discovered Contact Directory
### Performance
### Worker
### Relocate
## Users
This section of the panel let the admin control the users registered on the node.
If you have selected "Requires approval" for the *Register policy* in the general nodes configuration, new registrations will be listed at the top of the page.
There the admin can then approve or disapprove the request.
Below the new registration block the current accounts on the Friendica node are listed.
You can sort the user list by name, email, registration date, date of last login, date of last posting and the account type.
Here the admin can also block/unblock users from accessing the node or delete the accounts entirely.
In the last section of the page admins can create new accounts on the node.
The password for the new account will be send by email to the choosen email address.
## Plugins
This page is for selecting and configuration of extensions for Friendica which have to be placed into the `/addon` subdirectory of your Friendica installation.
You are presented with a long list of available addons.
The name of each addon is linked to a separate page for that addon which offers more informations and configuration possibilities.
Also shown is the version of the addon and an indicator if the addon is currently active or not.
When you update your node and the addons they may have to be reloaded.
To simplify this process there is a button at the top of the page to reload all active plugins.
## Themes
The Themes section of the admin panel works similar to the Plugins section but let you control the themes on your Friendica node.
Each theme has a dedicated suppage showing the current status, some information about the theme and a screen-shot of the Friendica interface using the theme.
Should the theme offer special settings, admins can set a global default value here.
You can activate and deactivate themes on their dedicated sub-pages thus making them available for the users of the node.
To select a default theme for the Friendica node, see the *Site* section of the admin panel.
## Additional Features
There are several optional features in Friendica.
Like the *dislike* button or the usage of a *richtext editor* for composing new postings.
In this section of the admin panel you can select a default setting for your node and eventually fix it, so users cannot change the setting anymore.
## DB Updates
Should the database structure of Friendica change, it will apply the changes automatically.
In case you are suspecious that the update might not have worked, you can use this section of the admin panel to check the situation.
## Inspect Queue
In the admin panel summary there are two numbers for the message queues.
The second number represents messages which could not be delivered and are queued for later retry.
If this number goes sky-rocking you might ask yourself which receopiant is not receiving.
Behind the inspect queue section of the admin panel you will find a list of the messages that could not be delivered.
The listing is sorted by the receipiant name so identifying potential broken communication lines should be simple.
These lines might be broken for various reasons.
The receiving end might be off-line, there might be a high system load and so on.
Don't panic!
Friendica will not queue messages for all time but will sort out *dead* nodes automatically after a while and remove messages from the queue then.
## Federation Statistics
The federation statistics page gives you a short summery of the nodes/servers/pods of the decentralized social network federation your node knows.
These numbers are not compleate and only contain nodes from networks Friendica federates directly with.
## Plugin Features
Some of the addons you can install for your Friendica node have settings which have to be set by the admin.
All those addons will be listed in this area of the admin panels side bar with their names.
## Logs
The log section of the admin panel is seperated into two pages.
On the first, following the "log" link, you can configure how much Friendica shall log.
And on the second you can read the log.
You should not place your logs into any directory that is accessible from the web.
If you have to, and you are using the default configuration from Apache, you should choose a name for the logfile ending in ``.log`` or ``.out``.
Should you use another web server, please make sure that you have the correct accessrules in place so that your log files are not accessible.
There are five different log levels: Normal, Trace, Debug, Data and All.
Specifying different verbosities of information and data written out to the log file.
Normally you should not need to log at all.
The *DEBUG* level will show a good deal of information about system activity but will not include detailed data.
In the *ALL* level Friendica will log everything to the file.
But due to the volume of information we recommend only enabling this when you are tracking down a specific problem.
**The amount of data can grow the filesize of the logfile quickly**.
You should set up some kind of [log rotation](https://en.wikipedia.org/wiki/Log_rotation) to keep the log file from growing too big.
**Known Issues**: The filename ``friendica.log`` can cause problems depending on your server configuration (see [issue 2209](https://github.com/friendica/friendica/issues/2209)).
By default PHP warnings and error messages are supressed.
If you want to enable those, you have to activate them in the ``.htconfig.php`` file.
Use the following settings to redirect PHP errors to a file.
Config:
@ -235,11 +277,61 @@ Config:
ini_set('display_errors', '0');
This will put all PHP errors in the file php.out (which must be writeable by the webserver).
Undeclared variables are occasionally referenced in the program and therefore we do not recommend using E_NOTICE or E_ALL.
Undeclared variables are occasionally referenced in the program and therefore we do not recommend using `E_NOTICE` or `E_ALL`.
The vast majority of issues reported at these levels are completely harmless.
Please report to the developers any errors you encounter in the logs using the recommended settings above.
They generally indicate issues which need to be resolved.
If you encounter a blank (white) page when using the application, view the PHP logs - as this almost always indicates an error has occurred.
*Note*: PHP logging cannot be activated from the admin panel but has to be configured from the ``.htconfig.php`` file.
## Diagnostics
In this section of the admin panel you find two tools to investigate what Friendica sees for certain ressources.
These tools can help to clarify communication problems.
For the *probe address* Friendica will display information for the address provided.
With the second tool *check webfinger* you can request information about the thing identified by a webfinger (`someone@example.com`).
# Exceptions to the rule
There are four exceptions to the rule, that all the config will be read from the data base.
These are the data base settings, the admin account settings, the path of PHP and information about an eventual installation of the node in a sub-directory of the (sub)domain.
## DB Settings
With the following settings, you specify the data base server, the username and passwort for Friendica and the database to use.
$db_host = 'your.db.host';
$db_user = 'db_username';
$db_pass = 'db_password';
$db_data = 'database_name';
## Admin users
You can set one, or more, accounts to be *Admin*.
By default this will be the one account you create during the installation process.
But you can expand the list of email addresses by any used email address you want.
Registration of new accounts with a listed email address is not possible.
$a->config['admin_email'] = 'you@example.com, buddy@example.com';
## PHP Path
Some of Friendicas processes are running in the background.
For this you need to specify the path to the PHP binary to be used.
$a->config['php_path'] = '{{$phpath}}';
## Subdirectory configuration
It is possible to install Friendica into a subdirectory of your webserver.
We strongly discurage you from doing so, as this will break federation to other networks (e.g. Diaspora, GNU Socia, Hubzilla)
Say you have a subdirectory for tests and put Friendica into a further subdirectory, the config would be:
$a->path = 'tests/friendica';
## Other exceptions
Furthermore there are some experimental settings, you can read-up in the [Config values that can only be set in .htconfig.php](help/htconfig) section of the documentation.

View file

@ -388,6 +388,18 @@ Friendica doesn't allow showing friends of other users.
---
### statusnet/config (*)
---
### statusnet/conversation (*; AUTH)
It shows all direct answers (excluding the original post) to a given id.
#### Parameter
* 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)
---
### statusnet/version (*)

View file

@ -15,7 +15,6 @@ Database Tables
| [contact](help/database/db_contact) | contact table |
| [conv](help/database/db_conv) | private messages |
| [deliverq](help/database/db_deliverq) | |
| [dsprphotoq](help/database/db_dsprphotoq) | |
| [event](help/database/db_event) | Events |
| [fcontact](help/database/db_fcontact) | friend suggestion stuff |
| [ffinder](help/database/db_ffinder) | friend suggestion stuff |

View file

@ -1,11 +0,0 @@
Table dsprphotoq
================
| Field | Description | Type | Null | Key | Default | Extra |
|---------|------------------|------------------|------|-----|---------|----------------|
| id | sequential ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| uid | | int(11) | NO | | 0 | |
| msg | | mediumtext | NO | | NULL | |
| attempt | | tinyint(4) | NO | | 0 | |
Return to [database documentation](help/database)

View file

@ -5,7 +5,6 @@ Table sign
| ------------ | ------------- | ---------------- | ---- | --- | ------- | --------------- |
| id | sequential ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| iid | item.id | int(10) unsigned | NO | MUL | 0 | |
| retract_iid | | int(10) unsigned | NO | MUL | 0 | |
| signed_text | | mediumtext | NO | | NULL | |
| signature | | text | NO | | NULL | |
| signer | | varchar(255) | NO | | | |

View file

@ -1,231 +1,73 @@
Konfigurationen
==============
# Settings
* [Zur Startseite der Hilfe](help)
Wenn du der Administrator einer Friendica Instanz bist, hast du Zugriff auf das so genannte **Admin Panel** in dem du die Friendica Instanz konfigurieren kannst,
Hier findest du einige eingebaute Features, welche kein graphisches Interface haben oder nicht dokumentiert sind.
Konfigurationseinstellungen sind in der Datei ".htconfig.php" gespeichert.
Bearbeite diese Datei, indem du sie z.B. mit einem Texteditor öffnest.
Verschiedene Systemeinstellungen sind bereits in dieser Datei dokumentiert und werden hier nicht weiter erklärt.
Auf der Startseite des Admin Panels werden die Informationen zu der Instanz zusammengefasst.
Diese Informationen beinhalten die Anzahl der Nachrichten, die sich aktuell in den Warteschlangen befinden.
Hierbei ist die erste Zahl die Zahl der Nachrichten die gerade aktiv verteilt werden.
Diese Zahl sollte sich relativ schnell sinken.
Die zweite Zahl gibt die Anzahl von Nachrichten an, die nicht zugestellt werden konnten.
Die Zustellung wird zu einem späteren Zeitpunkt noch einmal versucht.
Unter dem Punkt "Warteschlange Inspizieren" kannst du einen schnellen Blick auf die zweite Warteschlange werfen.
Solltest du für die Hintergrundprozesse die Worker aktiviert haben, könntest du eine dritte Zahl angezeigt bekommen.
Diese repräsentiert die Anzahl der Aufgaben, die die Worker noch vor sich haben.
**Tastaturbefehle**
Des weiteren findest du eine Übersicht über die Accounts auf dem Friendica Knoten, die unter dem Punkt "Nutzer" moderiert werden können.
Sowie eine Liste der derzeit aktivierten Addons.
Diese Liste ist verlinkt, so dass du schnellen Zugriff auf die Informationsseiten der einzelnen Addons hast.
Abschließend findest du auf der Startseite des Admin Panels die installierte Version von Friendica.
Wenn du in Kontakt mit den Entwicklern trittst und Probleme oder Fehler zu schildern, gib diese Version bitte immer mit an.
Friendica erfasst die folgenden Tastaturbefehle:
Die Unterabschnitte des Admin Panels kannst du in der Seitenleiste auswählen.
* [Pause] - Pausiert die Update-Aktivität via "Ajax". Das ist ein Prozess, der Updates durchführt, ohne die Seite neu zu laden. Du kannst diesen Prozess pausieren, um deine Netzwerkauslastung zu reduzieren und/oder um es in der Javascript-Programmierung zum Debuggen zu nutzen. Ein Pausenzeichen erscheint unten links im Fenster. Klicke die [Pause]-Taste ein weiteres Mal, um die Pause zu beenden.
## Seite
**Geburtstagsbenachrichtigung**
In diesem Bereich des Admin Panels findest du die Hauptkonfiguration deiner Friendica Instanz.
Er ist in mehrere Unterabschnitte aufgeteilt, wobei die Grundeinstellungen oben auf der Seite zu finden sind.
Geburtstage erscheinen auf deiner Startseite für alle Freunde, die in den nächsten 6 Tagen Geburtstag haben.
Um deinen Geburtstag für alle sichtbar zu machen, musst du deinen Geburtstag (zumindest Tag und Monat) in dein Standardprofil eintragen.
Es ist nicht notwendig, das Jahr einzutragen.
Da die meisten Konfigurationsoptionen einen Hilfstext im Admin Panel haben, kann und will dieser Artikel nicht alle Einstellungen abdecken.
**Konfigurationseinstellungen**
### Grundeinstellungen
**Sprache**
Systemeinstellung
Bitte schau dir die Datei util/README an, um Informationen zur Erstellung einer Übersetzung zu erhalten.
Konfiguriere:
```
$a->config['system']['language'] = 'name';
```
**System-Thema (Design)**
Systemeinstellung
Wähle ein Thema als Standardsystemdesign (welches vom Nutzer überschrieben werden kann). Das Standarddesign ist "default".
Konfiguriere:
```
$a->config['system']['theme'] = 'theme-name';
```
**Verifiziere SSL-Zertifikate**
Sicherheitseinstellungen
Standardmäßig erlaubt Friendica SSL-Kommunikation von Seiten, die "selbstunterzeichnete" SSL-Zertifikate nutzen.
Um eine weitreichende Kompatibilität mit anderen Netzwerken und Browsern zu gewährleisten, empfehlen wir, selbstunterzeichnete Zertifikate **nicht** zu nutzen.
Aber wir halten dich nicht davon ab, solche zu nutzen. SSL verschlüsselt alle Daten zwischen den Webseiten (und für deinen Browser), was dir eine komplett verschlüsselte Kommunikation erlaubt.
Auch schützt es deine Login-Daten vor Datendiebstahl. Selbstunterzeichnete Zertifikate können kostenlos erstellt werden.
Diese Zertifikate können allerdings Opfer eines sogenannten ["man-in-the-middle"-Angriffs](http://de.wikipedia.org/wiki/Man-in-the-middle-Angriff) werden, und sind daher weniger bevorzugt.
Wenn du es wünscht, kannst du eine strikte Zertifikatabfrage einstellen.
Das führt dazu, dass du keinerlei Verbindung zu einer selbstunterzeichneten SSL-Seite erstellen kannst
Konfiguriere:
```
$a->config['system']['verifyssl'] = true;
```
**Erlaubte Freunde-Domains**
Kooperationen/Gemeinschaften/Bildung Erweiterung
Kommagetrennte Liste von Domains, welche eine Freundschaft mit dieser Seite eingehen dürfen.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Domains erlaubt.
Konfiguriere:
```
$a->config['system']['allowed_sites'] = "sitea.com, *siteb.com";
```
**Erlaubte Email-Domains**
Kooperationen/Gemeinschaften/Bildung Erweiterung
Kommagetrennte Liste von Domains, welche bei der Registrierung als Part der Email-Adresse erlaubt sind.
Das grenzt Leute aus, die nicht Teil der Gruppe oder Organisation sind.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Email-Adressen erlaubt.
Konfiguriere:
```
$a->config['system']['allowed_email'] = "sitea.com, *siteb.com";
```
**Öffentlichkeit blockieren**
Kooperationen/Gemeinschaften/Bildung Erweiterung
Setze diese Einstellung auf "true" und sperre den öffentlichen Zugriff auf alle Seiten, solange man nicht eingeloggt ist.
Das blockiert die Ansicht von Profilen, Freunden, Fotos, vom Verzeichnis und den Suchseiten.
Ein Nebeneffekt ist, dass Einträge dieser Seite nicht im globalen Verzeichnis erscheinen.
Wir empfehlen, speziell diese Einstellung auszuschalten (die Einstellung ist an anderer Stelle auf dieser Seite erklärt).
Beachte: das ist speziell für Seiten, die beabsichtigen, von anderen Friendica-Netzwerken abgeschottet zu sein.
Unautorisierte Personen haben ebenfalls nicht die Möglichkeit, Freundschaftsanfragen von Seitennutzern zu beantworten.
Die Standardeinstellung steht auf "false".
Verfügbar in Version 2.2 und höher.
Konfiguriere:
```
$a->config['system']['block_public'] = true;
```
**Veröffentlichung erzwingen**
Kooperationen/Gemeinschaften/Bildung Erweiterung
Standardmäßig können Nutzer selbst auswählen, ob ihr Profil im Seitenverzeichnis erscheint.
Diese Einstellung zwingt alle Nutzer dazu, im Verzeichnis zu erscheinen.
Diese Einstellung kann vom Nutzer nicht deaktiviert werden. Die Standardeinstellung steht auf "false".
Konfiguriere:
```
$a->config['system']['publish_all'] = true;
```
**Globales Verzeichnis**
Kooperationen/Gemeinschaften/Bildung Erweiterung
Mit diesem Befehl wird die URL eingestellt, die zum Update des globalen Verzeichnisses genutzt wird.
Dieser Befehl ist in der Standardkonfiguration enthalten.
Der nichtdokumentierte Teil dieser Einstellung ist, dass das globale Verzeichnis gar nicht verfügbar ist, wenn diese Einstellung nicht gesetzt wird.
Dies erlaubt eine private Kommunikation, die komplett vom globalen Verzeichnis isoliert ist.
Konfiguriere:
```
$a->config['system']['directory'] = 'http://dir.friendi.ca';
```
**Proxy Konfigurationseinstellung**
Wenn deine Seite eine Proxy-Einstellung nutzt, musst du diese Einstellungen vornehmen, um mit anderen Seiten im Internet zu kommunizieren.
Konfiguriere:
```
$a->config['system']['proxy'] = "http://proxyserver.domain:port";
$a->config['system']['proxyuser'] = "username:password";
```
**Netzwerk-Timeout**
Legt fest, wie lange das Netzwerk warten soll, bevor ein Timeout eintritt.
Der Wert wird in Sekunden angegeben. Standardmäßig ist 60 eingestellt; 0 steht für "unbegrenzt" (nicht empfohlen).
Konfiguriere:
```
$a->config['system']['curl_timeout'] = 60;
```
**Banner/Logo**
#### Banner/Logo
Hiermit legst du das Banner der Seite fest. Standardmäßig ist das Friendica-Logo und der Name festgelegt.
Du kannst hierfür HTML/CSS nutzen, um den Inhalt zu gestalten und/oder die Position zu ändern, wenn es nicht bereits voreingestellt ist.
Konfiguriere:
#### Systensprache
```
$a->config['system']['banner'] = '<span id="logo-text">Meine tolle Webseite</span>';
```
Diese Einstellung legt die Standardsprache der Instanz fest.
Sie wird verwendet, wenn es Friendica nicht gelingt die Spracheinstellungen des Besuchers zu erkennen oder diese nicht unterstützt wird.
Nutzer können diese Auswahl in den Einstellungen des Benutzerkontos überschreiben.
Die Friendica Gemeinschaft bietet einige Übersetzungen an, von denen einige mehr andere weniger komplett sind.
Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser Seite](/help/translations) der Dokumentation.
**Maximale Bildgröße**
#### Systemweites Theme
Maximale Bild-Dateigröße in Byte. Standardmäßig ist 0 gesetzt, was bedeutet, dass kein Limit gesetzt ist.
Hier kann das Theme bestimmt werden, welches standardmäßig zum Anzeigen der Seite verwendet werden soll.
Nutzer können in ihren Einstellungen andere Themes wählen.
Derzeit ist das "duepunto zero" Theme das vorausgewählte Theme.
Konfiguriere:
Für mobile Geräte kannst du ein spezielles Theme wählen, wenn das Standardtheme ungeeignet für mobile Geräte sein sollte.
Das `vier` Theme z.B. unterstützt kleine Anzeigen und benötigt kein zusätzliches mobiles Theme.
```
$a->config['system']['maximagesize'] = 1000000;
```
### Registrierung
**UTF-8 Reguläre Ausdrücke**
Während der Registrierung werden die Namen daraufhin geprüft, ob sie reguläre UTF-8-Ausdrücke nutzen.
Hierfür wird PHP benötigt, um mit einer speziellen Einstellung kompiliert zu werden, die UTF-8-Ausdrücke benutzt.
Wenn du absolut keine Möglichkeit hast, Accounts zu registrieren, setze den Wert von "no_utf" auf "true".
Standardmäßig ist "false" eingestellt (das bedeutet, dass UTF-8-Ausdrücke unterstützt werden und funktionieren).
Konfiguriere:
```
$a->config['system']['no_utf'] = true;
```
**Prüfe vollständigen Namen**
#### Namen auf Vollständigkeit überprüfen
Es kann vorkommen, dass viele Spammer versuchen, sich auf deiner Seite zu registrieren.
In Testphasen haben wir festgestellt, dass diese automatischen Registrierungen das Feld "Vollständiger Name" oft nur mit Namen ausfüllen, die kein Leerzeichen beinhalten.
Wenn du Leuten erlauben willst, sich nur mit einem Namen anzumelden, dann setze die Einstellung auf "true".
Die Standardeinstellung ist auf "false" gesetzt.
Konfiguriere:
```
$a->config['system']['no_regfullname'] = true;
```
**OpenID**
#### OpenID Unterstützung
Standardmäßig wird OpenID für die Registrierung und für Logins genutzt.
Wenn du nicht willst, dass OpenID-Strukturen für dein System übernommen werden, dann setze "no_openid" auf "true".
Standardmäßig ist hier "false" gesetzt.
Konfiguriere:
```
$a->config['system']['no_openid'] = true;
```
**Multiple Registrierungen**
#### Unterbinde Mehrfachregistrierung
Um mehrfache Seiten zu erstellen, muss sich eine Person mehrfach registrieren können.
Deine Seiteneinstellung kann Registrierungen komplett blockieren oder an Bedingungen knüpfen.
@ -234,42 +76,246 @@ Hier ist weiterhin eine Bestätigung notwendig, wenn "REGISTER_APPROVE" ausgewä
Wenn du die Erstellung weiterer Accounts blockieren willst, dann setze die Einstellung "block_extended_register" auf "true".
Standardmäßig ist hier "false" gesetzt.
Konfiguriere:
```
$a->config['system']['block_extended_register'] = true;
```
### Datei hochladen
#### Maximale Bildgröße
**Entwicklereinstellungen**
Maximale Bild-Dateigröße in Byte. Standardmäßig ist 0 gesetzt, was bedeutet, dass kein Limit gesetzt ist.
Diese sind am nützlichsten, um Protokollprozesse zu debuggen oder andere Kommunikationsfehler einzugrenzen.
### Regeln
Konfiguriere:
```
$a->config['system']['debugging'] = true;
$a->config['system']['logfile'] = 'logfile.out';
$a->config['system']['loglevel'] = LOGGER_DEBUG;
```
Erstellt detaillierte Debugging-Logfiles, die in der Datei "logfile.out" gespeichert werden (Datei muss auf dem Server mit Schreibrechten versehen sein). "LOGGER_DEBUG" zeigt eine Menge an Systeminformationen, enthält aber keine detaillierten Daten.
Du kannst ebenfalls "LOGGER_ALL" auswählen, allerdings empfehlen wir dieses nur, wenn ein spezifisches Problem eingegrenzt werden soll.
Andere Log-Level sind möglich, werden aber derzeit noch nicht genutzt.
#### URL des weltweiten Verzeichnisses
Mit diesem Befehl wird die URL eingestellt, die zum Update des globalen Verzeichnisses genutzt wird.
Dieser Befehl ist in der Standardkonfiguration enthalten.
Der nicht dokumentierte Teil dieser Einstellung ist, dass das globale Verzeichnis gar nicht verfügbar ist, wenn diese Einstellung nicht gesetzt wird.
Dies erlaubt eine private Kommunikation, die komplett vom globalen Verzeichnis isoliert ist.
**PHP-Fehler-Logging**
#### Erzwinge Veröffentlichung
Nutze die folgenden Einstellungen, um PHP-Fehler direkt in einer Datei zu erfassen.
Standardmäßig können Nutzer selbst auswählen, ob ihr Profil im Seitenverzeichnis erscheint.
Diese Einstellung zwingt alle Nutzer dazu, im Verzeichnis zu erscheinen.
Diese Einstellung kann vom Nutzer nicht deaktiviert werden. Die Standardeinstellung steht auf "false".
Konfiguriere:
```
error_reporting(E_ERROR | E_WARNING | E_PARSE );
ini_set('error_log','php.out');
ini_set('log_errors','1');
ini_set('display_errors', '0');
```
#### Öffentlichen Zugriff blockieren
Diese Befehle erfassen alle PHP-Fehler in der Datei "php.out" (Datei muss auf dem Server mit Schreibrechten versehen sein).
Nicht deklarierte Variablen werden manchmal mit einem Verweis versehen, weshalb wir empfehlen, "E_NOTICE" und "E_ALL" nicht zu nutzen.
Die Menge an Fehlern, die auf diesem Level gemeldet werden, ist komplett harmlos.
Bitte informiere die Entwickler über alle Fehler, die du in deinen Log-Dateien mit den oben genannten Einstellungen erhältst.
Sie weisen generell auf Fehler in, die bearbeitet werden müssen.
Wenn du eine leere (weiße) Seite erhältst, schau in die PHP-Log-Datei - dies deutet fast immer darauf hin, dass ein Fehler aufgetreten ist.
Aktiviere diese Einstellung um den öffentlichen Zugriff auf alle Seiten zu sperren, solange man nicht eingeloggt ist.
Das blockiert die Ansicht von Profilen, Freunden, Fotos, vom Verzeichnis und den Suchseiten.
Ein Nebeneffekt ist, dass Einträge dieser Seite nicht im globalen Verzeichnis erscheinen.
Wir empfehlen, speziell diese Einstellung auszuschalten (die Einstellung ist an anderer Stelle auf dieser Seite erklärt).
Beachte: das ist speziell für Seiten, die beabsichtigen, von anderen Friendica-Netzwerken abgeschottet zu sein.
Unautorisierte Personen haben ebenfalls nicht die Möglichkeit, Freundschaftsanfragen von Seitennutzern zu beantworten.
Die Standardeinstellung ist deaktiviert.
Verfügbar in Version 2.2 und höher.
#### Erlaubte Domains für Kontakte
Kommagetrennte Liste von Domains, welche eine Freundschaft mit dieser Seite eingehen dürfen.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Domains erlaubt.
Mit dieser Option kann man einfach geschlossene Netzwerke, z.B. im schulischen Bereich aufbauen, aus denen nicht mit dem Rest des Netzwerks kommuniziert werden soll.
#### Erlaubte Domains für E-Mails
Kommagetrennte Liste von Domains, welche bei der Registrierung als Part der Email-Adresse erlaubt sind.
Das grenzt Leute aus, die nicht Teil der Gruppe oder Organisation sind.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Email-Adressen erlaubt.
#### Nutzern erlauben das remote_self Flag zu setzen
Webb du die Option `Nutzern erlauben das remote_self Flag zu setzen` aktivierst, können alle Nutzer Atom Feeds in den erweiterten Einstellungen des Kontakts als "Entferntes Konto" markieren.
Dadurch werden automatisch alle Beiträge dieser Feeds für diesen Nutzer gespiegelt und an die Kontakte bei Friendica verteilt.
Als Administrator der Friendica Instanz kannst du diese Einstellungen ansonsten nur direkt in der Datenbank vornehmen.
Bevor du das tust solltest du sicherstellen, dass du ein Backup der Datenbank hast und genau weißt was die Änderungen an der Datenbank bewirken, die du vornehmen willst.
### Erweitert
#### Proxy Einstellungen
Wenn deine Seite eine Proxy-Einstellung nutzt, musst du diese Einstellungen vornehmen, um mit anderen Seiten im Internet zu kommunizieren.
#### Netzwerk Wartezeit
Legt fest, wie lange das Netzwerk warten soll, bevor ein Timeout eintritt.
Der Wert wird in Sekunden angegeben. Standardmäßig ist 60 eingestellt; 0 steht für "unbegrenzt" (nicht empfohlen).
#### UTF-8 Reguläre Ausdrücke
Während der Registrierung werden die Namen daraufhin geprüft, ob sie reguläre UTF-8-Ausdrücke nutzen.
Hierfür wird PHP benötigt, um mit einer speziellen Einstellung kompiliert zu werden, die UTF-8-Ausdrücke benutzt.
Wenn du absolut keine Möglichkeit hast, Accounts zu registrieren, setze diesen Wert auf ja.
#### SSL Überprüfen
Standardmäßig erlaubt Friendica SSL-Kommunikation von Seiten, die "selbst unterzeichnete" SSL-Zertifikate nutzen.
Um eine weitreichende Kompatibilität mit anderen Netzwerken und Browsern zu gewährleisten, empfehlen wir, selbst unterzeichnete Zertifikate **nicht** zu nutzen.
Aber wir halten dich nicht davon ab, solche zu nutzen. SSL verschlüsselt alle Daten zwischen den Webseiten (und für deinen Browser), was dir eine komplett verschlüsselte Kommunikation erlaubt.
Auch schützt es deine Login-Daten vor Datendiebstahl. Selbst unterzeichnete Zertifikate können kostenlos erstellt werden.
Diese Zertifikate können allerdings Opfer eines sogenannten ["man-in-the-middle"-Angriffs](http://de.wikipedia.org/wiki/Man-in-the-middle-Angriff) werden, und sind daher weniger bevorzugt.
Wenn du es wünscht, kannst du eine strikte Zertifikatabfrage einstellen.
Das führt dazu, dass du keinerlei Verbindung zu einer selbst unterzeichneten SSL-Seite erstellen kannst
### Automatisch ein Kontaktverzeichnis erstellen
### Performance
### Worker
### Umsiedeln
## Nutzer
In diesem Abschnitt des Admin Panels kannst du die Nutzer deiner Friendica Instanz moderieren.
Solltest du für **Registrierungsmethode** die Einstellung "Bedarf Zustimmung" gewählt haben, werden hier zu Beginn der Seite neue Registrationen aufgelistet.
Als Administrator kannst du hier die Registration akzeptieren oder ablehnen.
Unter dem Abschnitt mit den Registrationen werden die aktuell auf der Instanz registrierten Nutzer aufgelistet.
Die Liste kann nach Namen, E-Mail Adresse, Datum der Registration, der letzten Anmeldung oder dem letzten Beitrag und dem Account Typ sortiert werden.
An dieser Stelle kannst du existierende Accounts vom Zugriff auf die Instanz blockieren, sie wieder frei geben oder Accounts endgültig löschen.
Im letzten Bereich auf der Seite kannst du als Administrator neue Accounts anlegen.
Das Passwort für so eingerichtete Accounts werden per E-Mail an die Nutzer geschickt.
## Plugins
Dieser Bereich des Admin Panels dient der Auswahl und Konfiguration der Erweiterungen von Friendica.
Sie müssen in das `/addon` Verzeichnis kopiert werden.
Auf der Seite wird eine Liste der verfügbaren Erweiterungen angezeigt.
Neben den Namen der Erweiterungen wird ein Indikator angezeigt, der anzeigt ob das Addon gerade aktiviert ist oder nicht.
Wenn du die Erweiterungen aktualisiert die du auf deiner Friendica Instanz nutzt könnte es sein, dass sie neu geladen werden müssen, damit die Änderungen aktiviert werden.
Um diesen Prozess zu vereinfachen gibt es am Anfang der Seite einen Button um alle aktiven Plugins neu zu laden.
## Themen
Der Bereich zur Kontrolle der auf der Friendica Instanz verfügbaren Themen funktioniert analog zum Plugins Bereich.
Jedes Theme hat eine extra Seite auf der der aktuelle Status, ein Bildschirmfoto des Themes, zusätzliche Informationen und eventuelle Einstellungen des Themes zu finden sind.
Genau wie Erweiterungen können Themes in der Übersichtsliste oder der Theme-Seite aktiviert bzw. deaktiviert werden.
Um ein Standardtheme für die Instanz zu wählen, benutze bitte die *Seiten* Bereich des Admin Panels.
## Zusätzliche Features
Es gibt einige optionale Features in Friendica, die Nutzer benutzen können oder halt nicht.
Zum Beispiel den *dislike* Button oder den *Webeditor* beim Erstellen von neuen Beiträgen.
In diesem Bereich des Admin Panels kannst du die Grundeinstellungen für diese Features festlegen und gegebenenfalls die Entscheidung treffen, dass Nutzer deiner Instanz diese auch nicht mehr ändern können.
## DB Updates
Wenn sich die Datenbankstruktur Friendicas ändert werden die Änderungen automatisch angewandt.
Solltest du den Verdacht haben, das eine Aktualisierung fehlgeschlagen ist, kannst du in diesem Bereich des Admin Panels den Status der Aktualisierungen überprüfen.
## Warteschlange Inspizieren
Auf der Eingangsseite des Admin Panels werden zwei Zahlen fpr die Warteschlangen angegeben.
Die zweite Zahl steht für die Beiträge, die initial nicht zugestellt werden konnten und später nochmal zugestellt werden sollen.
Sollte diese Zahl durch die Decke brechen, solltest du nachsehen an welchen Kontakt die Zustellung der Beiträge nicht funktioniert.
Unter dem Menüpunkt "Warteschlange Inspizieren" findest du eine Liste dieser nicht zustellbaren Beiträge.
Diese Liste ist nach dem Empfänger sortiert.
Die Kommunikation zu dem Empfänger kann aus unterschiedlichen Gründen gestört sein.
Der andere Server könnte offline sein, oder gerade einfach nur eine hohe Systemlast aufweisen.
Aber keine Panik!
Friendica wird die Beiträge nicht für alle Zeiten in der Warteschlange behalten.
Nach einiger Zeit werden Knoten als inaktiv identifiziert und Nachrichten an Nutzer dieser Knoten aus der Warteschlange gelöscht.
## Federation Statistik
Deine Instanz ist ein Teil eines Netzwerks von Servern dezentraler sozialer Netzwerke, der sogenannten **Federation**.
In diesem Bereich des Admin Panels findest du ein paar Zahlen zu dem Teil der Federation, die deine Instanz kennt.
## Plugin Features
Einige der Erweiterungen von Friendica benötigen global gültige Einstellungen, die der Administrator vornehmen muss.
Diese Erweiterungen sind hier aufgelistet, damit du die Einstellungen schneller findest.
## Protokolle
Dieser Bereich des Admin Panels ist auf zwei Seiten verteilt.
Die eine Seite dient der Konfiguration, die andere dem Anzeigen der Logs.
Du solltest die Logdatei nicht in einem Verzeichnis anlegen, auf das man vom Internet aus zugreifen kann.
Wenn du das dennoch tun musste und die Standardeinstellungen des Apache Servers verwendest, dann solltest du darauf achten, dass die Logdateien mit der Endung `.log` oder `.out` enden.
Solltest du einen anderen Webserver verwenden, solltest du sicherstellen, dass der Zugrif zu Dateien mit diesen Endungen nicht möglich ist.
Es gibt fünf Level der Ausführlichkeit mit denen Friendica arbeitet: Normal, Trace, Debug, Data und All.
Normalerweise solltest du für den Betrieb deiner Friendica Instanz keine Logs benötigen.
Wenn du versuchst einem Problem auf den Grund zu gehen, solltest du das "DEBUG" Level wählen.
Mit dem "All" Level schreibt Friendica alles in die Logdatei.
Die Datenmenge der geloggten Daten kann relativ schnell anwachsen, deshalb empfehlen wir das Anlegen von Protokollen nur zu aktivieren wenn es unbedingt nötig ist.
**Die Größe der Logdateien kann schnell anwachsen**.
Du solltest deshalb einen Dienst zur [log rotation](https://en.wikipedia.org/wiki/Log_rotation) einrichten.
**Bekannte Probleme**: Der Dateiname `friendica.log` kann bei speziellen Server Konfigurationen zu Problemen führen (siehe [issue 2209](https://github.com/friendica/friendica/issues/2209)).
Normalerweise werden Fehler- und Warnmeldungen von PHP unterdrückt.
Wenn du sie aktivieren willst, musst du folgendes in der `.htconfig.php` Datei eintragen um die Meldungen in die Datei `php.out` zu speichern
error_reporting(E_ERROR | E_WARNING | E_PARSE );
ini_set('error_log','php.out');
ini_set('log_errors','1');
ini_set('display_errors', '0');
Die Datei `php.out` muss vom Webserver schreibbar sein und sollte ebenfalls außerhalb der Webverzeichnisse liegen.
Es kommt gelegentlich vor, dass nicht deklarierte Variablen referenziert werden, dehalb raten wir davon ab `E_NOTICE` oder `E_ALL` zu verwenden.
Die überwiegende Mehrzahl der auf diesen Stufen dokumentierten Fehler sind absolut harmlos.
Solltest du mit den oben empfohlenen Einstellungen Fehler finden, teile sie bitte den Entwicklern mit.
Im Allgemeinen sind dies Fehler, die behoben werden sollten.
Solltest du eine leere (weiße) Seite vorfinden, während du Friendica nutzt, werfe bitte einen Blick in die PHP Logs.
Solche *White Screens* sind so gut wie immer ein Zeichen dafür, dass ein Fehler aufgetreten ist.
## Diagnose
In diesem Bereich des Admin Panels findest du zwei Werkzeuge mit der du untersuchen kannst, wie Friendica bestimmte Ressourcen einschätzt.
Diese Werkzeuge sind insbesondere bei der Analyse von Kommunikationsproblemen hilfreich.
"Adresse untersuchen" zeigt Informationen zu einer URL an, wie Friendica sie wahrnimmt.
Mit dem zweiten Werkzeug "Webfinger überprüfen" kannst du Informationen zu einem Ding anfordern, das über einen Webfinger ( jemand@example.com ) identifiziert wird.
# Die Ausnahmen der Regel
Für die oben genannte Regel gibt es vier Ausnahmen, deren Konfiguration nicht über das Admin Panel vorgenommen werden kann.
Dies sind die Datenbank Einstellungen, die Administrator Accounts, der PHP Pfad und die Konfiguration einer eventuellen Installation in ein Unterverzeichnis unterhalb der Hauptdomain.
## Datenbank Einstellungen
Mit den folgenden Einstellungen kannst du die Zugriffsdaten für den Datenbank Server festlegen.
$db_host = 'your.db.host';
$db_user = 'db_username';
$db_pass = 'db_password';
$db_data = 'database_name';
## Administratoren
Du kannst einen, oder mehrere Accounts, zu Administratoren machen.
Normalerweise trifft dies auf den ersten Account zu, der nach der Installation angelegt wird.
Die Liste der E-Mail Adressen kann aber einfach erweitert werden.
Mit keiner der angegebenen E-Mail Adressen können weitere Accounts registriert werden.
$a->config['admin_email'] = 'you@example.com, buddy@example.com';
## PHP Pfad
Einige Prozesse von Friendica laufen im Hintergrund.
Für diese Prozesse muss der Pfad zu der PHP Version gesetzt sein, die verwendet werden soll.
$a->config['php_path'] = '/pfad/zur/php-version';
## Unterverzeichnis Konfiguration
Man kann Friendica in ein Unterverzeichnis des Webservers installieren.
Wir raten allerdings dringen davon ab, da es die Interoperabilität mit anderen Netzwerken (z.B. Diaspora, GNU Social, Hubzilla) verhindert.
Mal angenommen, du hast ein Unterverzeichnis tests und willst Friendica in ein weiteres Unterverzeichnis installieren, dann lautet die Konfiguration hierfür:
$a->path = 'tests/friendica';
## Weitere Ausnahmen
Es gibt noch einige experimentelle Einstellungen, die nur in der ``.htconfig.php`` Datei konfiguriert werden können.
Im [Konfigurationswerte, die nur in der .htconfig.php gesetzt werden können (EN)](help/htconfig) Artikel kannst du mehr darüber erfahren.

View file

@ -34,9 +34,12 @@ line to your .htconfig.php:
* like_no_comment (Boolean) - Don't update the "commented" value of an item when it is liked.
* local_block (Boolean) - Used in conjunction with "block_public".
* local_search (Boolean) - Blocks the search for not logged in users to prevent crawlers from blocking your system.
* max_connections - The poller process isn't started when 3/4 of the possible database connections are used. When the system can't detect the maximum numbers of connection then this value can be used.
* max_connections - The poller process isn't started when the maximum level of the possible database connections are used. When the system can't detect the maximum numbers of connection then this value can be used.
* max_connections_level - The maximum level of connections that are allowed to let the poller start. It is a percentage value. Default value is 75.
* max_contact_queue - Default value is 500.
* max_batch_queue - Default value is 1000.
* max_processes_backend - Maximum number of concurrent database processes for background tasks. Default value is 5.
* max_processes_frontend - Maximum number of concurrent database processes for foreground tasks. Default value is 20.
* no_oembed (Boolean) - Don't use OEmbed to fetch more information about a link.
* no_oembed_rich_content (Boolean) - Don't show the rich content (e.g. embedded PDF).
* no_smilies (Boolean) - Don't show smilies.

View file

@ -129,7 +129,7 @@ function terminate_friendship($user,$self,$contact) {
}
elseif($contact['network'] === NETWORK_DIASPORA) {
require_once('include/diaspora.php');
diaspora_unshare($user,$contact);
diaspora::send_unshare($user,$contact);
}
elseif($contact['network'] === NETWORK_DFRN) {
require_once('include/dfrn.php');
@ -192,72 +192,85 @@ function unmark_for_death($contact) {
);
}}
function get_contact_details_by_url($url, $uid = -1) {
/**
* @brief Get contact data for a given profile link
*
* The function looks at several places (contact table and gcontact table) for the contact
*
* @param string $url The profile link
* @param int $uid User id
* @param array $default If not data was found take this data as default value
*
* @return array Contact data
*/
function get_contact_details_by_url($url, $uid = -1, $default = array()) {
if ($uid == -1)
$uid = local_user();
$r = q("SELECT `id` AS `gid`, `url`, `name`, `nick`, `addr`, `photo`, `location`, `about`, `keywords`, `gender`, `community`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link($url)));
if ($r) {
$profile = $r[0];
if ((($profile["addr"] == "") OR ($profile["name"] == "")) AND
in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
proc_run('php',"include/update_gcontact.php", $profile["gid"]);
}
// Fetching further contact data from the contact table
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `thumb`, `addr`, `forum`, `prv`, `bd`, `self` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` IN ('%s', '')",
dbesc(normalise_link($url)), intval($uid), dbesc($profile["network"]));
if (!count($r) AND !isset($profile))
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `thumb`, `addr`, `forum`, `prv`, `bd`, `self` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
// Fetch contact data from the contact table for the given user
$r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`,
`keywords`, `gender`, `photo`, `thumb`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `bd` AS `birthday`, `self`
FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
dbesc(normalise_link($url)), intval($uid));
if (!count($r) AND !isset($profile))
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `thumb`, `addr`, `forum`, `prv`, `bd` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
dbesc(normalise_link($url)));
// Fetch the data from the contact table with "uid=0" (which is filled automatically)
if (!$r)
$r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`,
`keywords`, `gender`, `photo`, `thumb`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `bd` AS `birthday`, 0 AS `self`
FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
dbesc(normalise_link($url)));
// Fetch the data from the gcontact table
if (!$r)
$r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`,
`keywords`, `gender`, `photo`, `photo` AS `thumb`, `community` AS `forum`, 0 AS `prv`, `community`, `birthday`, 0 AS `self`
FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($url)));
if ($r) {
if (!isset($profile["url"]) AND $r[0]["url"])
$profile["url"] = $r[0]["url"];
if (!isset($profile["name"]) AND $r[0]["name"])
$profile["name"] = $r[0]["name"];
if (!isset($profile["nick"]) AND $r[0]["nick"])
$profile["nick"] = $r[0]["nick"];
if (!isset($profile["addr"]) AND $r[0]["addr"])
$profile["addr"] = $r[0]["addr"];
if ((!isset($profile["photo"]) OR $r[0]["self"]) AND $r[0]["photo"])
$profile["photo"] = $r[0]["photo"];
if (!isset($profile["location"]) AND $r[0]["location"])
$profile["location"] = $r[0]["location"];
if (!isset($profile["about"]) AND $r[0]["about"])
$profile["about"] = $r[0]["about"];
if (!isset($profile["keywords"]) AND $r[0]["keywords"])
$profile["keywords"] = $r[0]["keywords"];
if (!isset($profile["gender"]) AND $r[0]["gender"])
$profile["gender"] = $r[0]["gender"];
if (isset($r[0]["forum"]) OR isset($r[0]["prv"]))
$profile["community"] = ($r[0]["forum"] OR $r[0]["prv"]);
if (!isset($profile["network"]) AND $r[0]["network"])
$profile["network"] = $r[0]["network"];
if (!isset($profile["addr"]) AND $r[0]["addr"])
$profile["addr"] = $r[0]["addr"];
if (!isset($profile["bd"]) AND $r[0]["bd"])
$profile["bd"] = $r[0]["bd"];
if (isset($r[0]["thumb"]))
$profile["thumb"] = $r[0]["thumb"];
if ($r[0]["uid"] == 0)
$profile["cid"] = 0;
else
$profile["cid"] = $r[0]["id"];
} else
$profile["cid"] = 0;
// If there is more than one entry we filter out the connector networks
if (count($r) > 1)
foreach ($r AS $id => $result)
if ($result["network"] == NETWORK_STATUSNET)
unset($r[$id]);
$profile = array_shift($r);
// "bd" always contains the upcoming birthday of a contact.
// "birthday" might contain the birthday including the year of birth.
if ($profile["birthday"] != "0000-00-00") {
$bd_timestamp = strtotime($profile["birthday"]);
$month = date("m", $bd_timestamp);
$day = date("d", $bd_timestamp);
$current_timestamp = time();
$current_year = date("Y", $current_timestamp);
$current_month = date("m", $current_timestamp);
$current_day = date("d", $current_timestamp);
$profile["bd"] = $current_year."-".$month."-".$day;
$current = $current_year."-".$current_month."-".$current_day;
if ($profile["bd"] < $current)
$profile["bd"] = (++$current_year)."-".$month."-".$day;
} else
$profile["bd"] = "0000-00-00";
} else {
$profile = $default;
if (!isset($profile["thumb"]) AND isset($profile["photo"]))
$profile["thumb"] = $profile["photo"];
}
if ((($profile["addr"] == "") OR ($profile["name"] == "")) AND ($profile["gid"] != 0) AND
in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
proc_run('php',"include/update_gcontact.php", $profile["gid"]);
// Show contact details of Diaspora contacts only if connected
if (($profile["cid"] == 0) AND ($profile["network"] == NETWORK_DIASPORA)) {
$profile["location"] = "";
$profile["about"] = "";
$profile["gender"] = "";
$profile["birthday"] = "0000-00-00";
}
return($profile);
@ -555,60 +568,6 @@ function posts_from_gcontact($a, $gcontact_id) {
return $o;
}
/**
* @brief set the gcontact-id in all item entries
*
* This job has to be started multiple times until all entries are set.
* It isn't started in the update function since it would consume too much time and can be done in the background.
*/
function item_set_gcontact() {
define ('POST_UPDATE_VERSION', 1192);
// Was the script completed?
if (get_config("system", "post_update_version") >= POST_UPDATE_VERSION)
return;
// Check if the first step is done (Setting "gcontact-id" in the item table)
$r = q("SELECT `author-link`, `author-name`, `author-avatar`, `uid`, `network` FROM `item` WHERE `gcontact-id` = 0 LIMIT 1000");
if (!$r) {
// Are there unfinished entries in the thread table?
$r = q("SELECT COUNT(*) AS `total` FROM `thread`
INNER JOIN `item` ON `item`.`id` =`thread`.`iid`
WHERE `thread`.`gcontact-id` = 0 AND
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
if ($r AND ($r[0]["total"] == 0)) {
set_config("system", "post_update_version", POST_UPDATE_VERSION);
return false;
}
// Update the thread table from the item table
q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid`
SET `thread`.`gcontact-id` = `item`.`gcontact-id`
WHERE `thread`.`gcontact-id` = 0 AND
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
return false;
}
$item_arr = array();
foreach ($r AS $item) {
$index = $item["author-link"]."-".$item["uid"];
$item_arr[$index] = array("author-link" => $item["author-link"],
"uid" => $item["uid"],
"network" => $item["network"]);
}
// Set the "gcontact-id" in the item table and add a new gcontact entry if needed
foreach($item_arr AS $item) {
$gcontact_id = get_gcontact_id(array("url" => $item['author-link'], "network" => $item['network'],
"photo" => $item['author-avatar'], "name" => $item['author-name']));
q("UPDATE `item` SET `gcontact-id` = %d WHERE `uid` = %d AND `author-link` = '%s' AND `gcontact-id` = 0",
intval($gcontact_id), intval($item["uid"]), dbesc($item["author-link"]));
}
return true;
}
/**
* @brief Returns posts from a given contact
*

236
include/Core/Config.php Normal file
View file

@ -0,0 +1,236 @@
<?php
namespace Friendica\Core;
/**
* @file include/Core/Config.php
*
* @brief Contains the class with methods for system configuration
*/
/**
* @brief Arbitrary sytem configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The Config::get() functions return boolean false for keys that are unset,
* and this could lead to subtle bugs.
*
* There are a few places in the code (such as the admin panel) where boolean
* configurations need to be fixed as of 10/08/2011.
*/
class Config {
/**
* @brief Loads all configuration values of family into a cached storage.
*
* All configuration values of the system are stored in global cache
* which is available under the global variable $a->config
*
* @param string $family
* The category of the configuration value
* @return void
*/
public static function load($family) {
global $a;
$r = q("SELECT `v`, `k` FROM `config` WHERE `cat` = '%s'", dbesc($family));
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
if ($family === 'config') {
$a->config[$k] = $rr['v'];
} else {
$a->config[$family][$k] = $rr['v'];
}
}
} else if ($family != 'config') {
// Negative caching
$a->config[$family] = "!<unset>!";
}
}
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
* $instore is only used by the set_config function
* to determine if the key already exists in the DB
* If a key is found in the DB but doesn't exist in
* local config cache, pull it into the cache so we don't have
* to hit the DB again for this item.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param mixed $default_value optional
* The value to return if key is not set (default: null)
* @param boolean $refresh optional
* If true the config is loaded from the db and not from the cache (default: false)
* @return mixed Stored value or null if it does not exist
*/
public static function get($family, $key, $default_value=null, $refresh = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$family])) {
if($a->config[$family] === '!<unset>!') {
return $default_value;
}
}
if(isset($a->config[$family][$key])) {
if($a->config[$family][$key] === '!<unset>!') {
return $default_value;
}
return $a->config[$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($family."|".$key)) {
$val = apc_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_fetch") AND function_exists("xcache_isset"))
if (xcache_isset($family."|".$key)) {
$val = xcache_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
*/
$ret = q("SELECT `v` FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
if(count($ret)) {
// manage array value
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, '!<unset>!', 600);*/
}
return $default_value;
}
/**
* @brief Sets a configuration value for system config
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false if the database update failed
*/
public static function set($family,$key,$value) {
global $a;
// If $a->config[$family] has been previously set to '!<unset>!', then
// $a->config[$family][$key] will evaluate to $a->config[$family][0], and
// $a->config[$family][$key] = $value will be equivalent to
// $a->config[$family][0] = $value[0] (this causes infuriating bugs),
// so unset the family before assigning a value to a family's key
if($a->config[$family] === '!<unset>!')
unset($a->config[$family]);
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
$dbvalue = (is_bool($dbvalue) ? intval($dbvalue) : $dbvalue);
if(is_null(self::get($family,$key,null,true))) {
$a->config[$family][$key] = $value;
$ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
$a->config[$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}
/**
* @brief Deletes the given key from the system configuration.
*
* Removes the configured value from the stored cache in $a->config
* and removes it from the database.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
public static function delete($family,$key) {
global $a;
if(x($a->config[$family],$key))
unset($a->config[$family][$key]);
$ret = q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($family),
dbesc($key)
);
// If APC is enabled then delete the data from there, else try XCache
/*if (function_exists("apc_delete"))
apc_delete($family."|".$key);
elseif (function_exists("xcache_unset"))
xcache_unset($family."|".$key);*/
return $ret;
}
}

222
include/Core/PConfig.php Normal file
View file

@ -0,0 +1,222 @@
<?php
namespace Friendica\Core;
/**
* @file include/Core/PConfig.php
* @brief contains the class with methods for the management
* of the user configuration
*/
/**
* @brief Management of user configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The PConfig::get() functions return boolean false for keys that are unset,
* and this could lead to subtle bugs.
*/
class PConfig {
/**
* @brief Loads all configuration values of a user's config family into a cached storage.
*
* All configuration values of the given user are stored in global cache
* which is available under the global variable $a->config[$uid].
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @return void
*/
public static function load($uid,$family) {
global $a;
$r = q("SELECT `v`,`k` FROM `pconfig` WHERE `cat` = '%s' AND `uid` = %d",
dbesc($family),
intval($uid)
);
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
$a->config[$uid][$family][$k] = $rr['v'];
}
} else if ($family != 'config') {
// Negative caching
$a->config[$uid][$family] = "!<unset>!";
}
}
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular user's config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param mixed $default_value optional
* The value to return if key is not set (default: null)
* @param boolean $refresh optional
* If true the config is loaded from the db and not from the cache (default: false)
* @return mixed Stored value or null if it does not exist
*/
public static function get($uid, $family, $key, $default_value = null, $refresh = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$uid][$family])) {
if($a->config[$uid][$family] === '!<unset>!') {
return $default_value;
}
}
if(isset($a->config[$uid][$family][$key])) {
if($a->config[$uid][$family][$key] === '!<unset>!') {
return $default_value;
}
return $a->config[$uid][$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($uid."|".$family."|".$key)) {
$val = apc_fetch($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_get") AND function_exists("xcache_isset"))
if (xcache_isset($uid."|".$family."|".$key)) {
$val = xcache_get($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}*/
$ret = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
intval($uid),
dbesc($family),
dbesc($key)
);
if(count($ret)) {
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$uid][$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$uid][$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, '!<unset>!', 600);*/
}
return $default_value;
}
/**
* @brief Sets a configuration value for a user
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
public static function set($uid,$family,$key,$value) {
global $a;
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
if(is_null(self::get($uid,$family,$key,null, true))) {
$a->config[$uid][$family][$key] = $value;
$ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `pconfig` SET `v` = '%s' WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
intval($uid),
dbesc($family),
dbesc($key)
);
$a->config[$uid][$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}
/**
* @brief Deletes the given key from the users's configuration.
*
* Removes the configured value from the stored cache in $a->config[$uid]
* and removes it from the database.
*
* @param string $uid The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
public static function delete($uid,$family,$key) {
global $a;
if(x($a->config[$uid][$family],$key))
unset($a->config[$uid][$family][$key]);
$ret = q("DELETE FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}
}

63
include/DirSearch.php Normal file
View file

@ -0,0 +1,63 @@
<?php
/**
* @file include/DirSearch.php
* @brief This file includes the DirSearch class with directory related functions
*/
/**
* @brief This class handels directory related functions
*/
class DirSearch {
/**
* @brief Search global contact table by nick or name
*
* @param string $search Name or nick
* @param string $mode Search mode (e.g. "community")
* @return array with search results
*/
public static function global_search_by_name($search, $mode = '') {
if($search) {
// check supported networks
if (get_config('system','diaspora_enabled'))
$diaspora = NETWORK_DIASPORA;
else
$diaspora = NETWORK_DFRN;
if (!get_config('system','ostatus_disabled'))
$ostatus = NETWORK_OSTATUS;
else
$ostatus = NETWORK_DFRN;
// check if we search only communities or every contact
if($mode === "community")
$extra_sql = " AND `community`";
else
$extra_sql = "";
$search .= "%";
$results = q("SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`nick`, `gcontact`.`photo`,
`gcontact`.`network`, `gcontact`.`keywords`, `gcontact`.`addr`, `gcontact`.`community`
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 (`contact`.`id` > 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND
(`gcontact`.`addr` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`nick` LIKE '%s') $extra_sql
GROUP BY `gcontact`.`nurl`
ORDER BY `gcontact`.`nurl` DESC
LIMIT 1000",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN), dbesc($ostatus), dbesc($diaspora),
dbesc(escape_tags($search)), dbesc(escape_tags($search)), dbesc(escape_tags($search)));
return $results;
}
}
}

View file

@ -1,12 +1,12 @@
<?php
/**
* @file include/forum.php
* @brief Functions related to forum functionality *
* @file include/ForumManager.php
* @brief ForumManager class with its methods related to forum functionality *
*/
/**
* @brief This class handles functions related to the forum functionality
* @brief This class handles metheods related to the forum functionality
*/
class ForumManager {

View file

@ -823,9 +823,12 @@ function get_photo_info($url) {
$data = Cache::get($url);
if (is_null($data)) {
$img_str = fetch_url($url, true, $redirects, 4);
// Unserialise to be able to check in the next step if the cached data is alright.
if (!is_null($data))
$data = unserialize($data);
if (is_null($data) OR !$data) {
$img_str = fetch_url($url, true, $redirects, 4);
$filesize = strlen($img_str);
if (function_exists("getimagesizefromstring"))
@ -846,8 +849,7 @@ function get_photo_info($url) {
$data["size"] = $filesize;
Cache::set($url, serialize($data));
} else
$data = unserialize($data);
}
return $data;
}

View file

@ -23,13 +23,15 @@ function scrape_dfrn($url, $dont_probe = false) {
if (is_array($noscrapedata)) {
if ($noscrapedata["nick"] != "")
return($noscrapedata);
else
unset($noscrapedata["nick"]);
} else
$noscrapedata = array();
}
$s = fetch_url($url);
if(! $s)
if (!$s)
return $ret;
if (!$dont_probe) {
@ -356,7 +358,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
$result = array();
if(! $url)
if (!$url)
return $result;
$result = Cache::get("probe_url:".$mode.":".$url);
@ -365,6 +367,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
return $result;
}
$original_url = $url;
$network = null;
$diaspora = false;
$diaspora_base = '';
@ -393,7 +396,12 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
else
$links = lrdd($url);
if(count($links)) {
if ((count($links) == 0) AND strstr($url, "/index.php")) {
$url = str_replace("/index.php", "", $url);
$links = lrdd($url);
}
if (count($links)) {
$has_lrdd = true;
logger('probe_url: found lrdd links: ' . print_r($links,true), LOGGER_DATA);
@ -440,12 +448,21 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
// aliases, let's hope we're lucky and get one that matches the feed author-uri because
// otherwise we're screwed.
$backup_alias = "";
foreach($links as $link) {
if($link['@attributes']['rel'] === 'alias') {
if(strpos($link['@attributes']['href'],'@') === false) {
if(isset($profile)) {
if($link['@attributes']['href'] !== $profile)
$alias = unamp($link['@attributes']['href']);
$alias_url = $link['@attributes']['href'];
if(($alias_url !== $profile) AND ($backup_alias == "") AND
($alias_url !== str_replace("/index.php", "", $profile)))
$backup_alias = $alias_url;
if(($alias_url !== $profile) AND !strstr($alias_url, "index.php") AND
($alias_url !== str_replace("/index.php", "", $profile)))
$alias = $alias_url;
}
else
$profile = unamp($link['@attributes']['href']);
@ -453,6 +470,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
}
}
if ($alias == "")
$alias = $backup_alias;
// If the profile is different from the url then the url is abviously an alias
if (($alias == "") AND ($profile != "") AND !$at_addr AND (normalise_link($profile) != normalise_link($url)))
$alias = $url;
@ -576,7 +596,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if($diaspora && $diaspora_base && $diaspora_guid) {
$diaspora_notify = $diaspora_base.'receive/users/'.$diaspora_guid;
if($mode == PROBE_DIASPORA || ! $notify || ($notify == $diaspora_notify)) {
if($mode == PROBE_DIASPORA || !$notify || ($notify == $diaspora_notify)) {
$notify = $diaspora_notify;
$batch = $diaspora_base . 'receive/public' ;
}
@ -685,7 +705,14 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if (($vcard["nick"] == "") AND ($data["header"]["author-nick"] != ""))
$vcard["nick"] = $data["header"]["author-nick"];
if(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
if ($network == NETWORK_OSTATUS) {
if ($data["header"]["author-id"] != "")
$alias = $data["header"]["author-id"];
if ($data["header"]["author-link"] != "")
$profile = $data["header"]["author-link"];
} elseif(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
$profile = $data["header"]["author-link"];
}
}
@ -769,6 +796,12 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if (($baseurl == "") AND ($poll != ""))
$baseurl = matching_url(normalise_link($profile), normalise_link($poll));
if (substr($baseurl, -10) == "/index.php")
$baseurl = str_replace("/index.php", "", $baseurl);
if ($network == "")
$network = NETWORK_PHANTOM;
$baseurl = rtrim($baseurl, "/");
if(strpos($url,'@') AND ($addr == "") AND ($network == NETWORK_DFRN))
@ -802,7 +835,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
require_once('include/bbcode.php');
$address = GetProfileUsername($url, "", true);
$result2 = probe_url($address, $mode, ++$level);
if ($result2['network'] != "")
if (!in_array($result2['network'], array("", NETWORK_PHANTOM, NETWORK_FEED)))
$result = $result2;
}
@ -810,14 +843,46 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if (($result['network'] == NETWORK_FEED) AND ($result['baseurl'] != "") AND ($result['nick'] != "")) {
$addr = $result['nick'].'@'.str_replace("http://", "", $result['baseurl']);
$result2 = probe_url($addr, $mode, ++$level);
if (($result2['network'] != "") AND ($result2['network'] != NETWORK_FEED))
if (!in_array($result2['network'], array("", NETWORK_PHANTOM, NETWORK_FEED)))
$result = $result2;
}
// Quickfix for Hubzilla systems with enabled OStatus plugin
if (($result['network'] == NETWORK_DIASPORA) AND ($result["batch"] == "")) {
$result2 = probe_url($url, PROBE_DIASPORA, ++$level);
if ($result2['network'] == NETWORK_DIASPORA) {
$addr = $result["addr"];
$result = $result2;
if (($result["addr"] == "") AND ($addr != ""))
$result["addr"] = $addr;
}
}
}
// Only store into the cache if the value seems to be valid
if ($result['network'] != NETWORK_PHANTOM)
Cache::set("probe_url:".$mode.":".$url,serialize($result), CACHE_DAY);
if ($result['network'] != NETWORK_PHANTOM) {
Cache::set("probe_url:".$mode.":".$original_url,serialize($result), CACHE_DAY);
/// @todo temporary fix - we need a real contact update function that updates only changing fields
/// The biggest problem is the avatar picture that could have a reduced image size.
/// It should only be updated if the existing picture isn't existing anymore.
if (($result['network'] != NETWORK_FEED) AND ($mode == PROBE_NORMAL) AND
$result["name"] AND $result["nick"] AND $result["url"] AND $result["addr"] AND $result["poll"])
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `url` = '%s', `addr` = '%s',
`notify` = '%s', `poll` = '%s', `alias` = '%s', `success_update` = '%s'
WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
dbesc($result["name"]),
dbesc($result["nick"]),
dbesc($result["url"]),
dbesc($result["addr"]),
dbesc($result["notify"]),
dbesc($result["poll"]),
dbesc($result["alias"]),
dbesc(datetime_convert()),
dbesc(normalise_link($result['url']))
);
}
return $result;
}

182
include/Smilies.php Normal file
View file

@ -0,0 +1,182 @@
<?php
/**
* @file include/Smilies.php
* @brief This file contains the Smilies class which contains functions to handle smiles
*/
/**
* This class contains functions to handle smiles
*/
class Smilies {
/**
* @brief Function to list all smilies
*
* Get an array of all smilies, both internal and from addons.
*
* @return array
* 'texts' => smilie shortcut
* 'icons' => icon in html
*
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array)
*/
public static function get_list() {
$texts = array(
'&lt;3',
'&lt;/3',
'&lt;\\3',
':-)',
';-)',
':-(',
':-P',
':-p',
':-"',
':-&quot;',
':-x',
':-X',
':-D',
'8-|',
'8-O',
':-O',
'\\o/',
'o.O',
'O.o',
'o_O',
'O_o',
":'(",
":-!",
":-/",
":-[",
"8-)",
':beer',
':homebrew',
':coffee',
':facepalm',
':like',
':dislike',
'~friendica',
'red#',
'red#matrix'
);
$icons = array(
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" title="&lt;3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;/3" title="&lt;/3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" title="&lt;\\3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-smile.gif" alt=":-)" title=":-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-wink.gif" alt=";-)" title=";-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-frown.gif" alt=":-(" title=":-(" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" title=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-p" title=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" title=":-x" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" title=":-X" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" title=":-D" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" title="8-|" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" title="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt=":-O" title="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-thumbsup.gif" alt="\\o/" title="\\o/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o.O" title="o.O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O.o" title="O.o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o_O" title="o_O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O_o" title="O_o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cry.gif" alt=":\'(" title=":\'("/>',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-foot-in-mouth.gif" alt=":-!" title=":-!" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-undecided.gif" alt=":-/" title=":-/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-embarassed.gif" alt=":-[" title=":-[" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cool.gif" alt="8-)" title="8-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":beer" title=":beer" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":homebrew" title=":homebrew" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/coffee.gif" alt=":coffee" title=":coffee" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" title=":facepalm" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/like.gif" alt=":like" title=":like" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/dislike.gif" alt=":dislike" title=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . app::get_baseurl() . '/images/friendica-16.png" alt="~friendica" title="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red#" title="red#" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red#matrix" title="red#matrix" />matrix</a>'
);
$params = array('texts' => $texts, 'icons' => $icons);
call_hooks('smilie', $params);
return $params;
}
/**
* @brief Replaces text emoticons with graphical images
*
* It is expected that this function will be called using HTML text.
* We will escape text between HTML pre and code blocks from being
* processed.
*
* At a higher level, the bbcode [nosmile] tag can be used to prevent this
* function from being executed by the prepare_text() routine when preparing
* bbcode source for HTML display
*
* @param string $s
* @param boolean $sample
*
* @return string HML Output of the Smilie
*/
public static function replace($s, $sample = false) {
if(intval(get_config('system','no_smilies'))
|| (local_user() && intval(get_pconfig(local_user(),'system','no_smilies'))))
return $s;
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','self::encode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','self::encode',$s);
$params = self::get_list();
$params['string'] = $s;
if($sample) {
$s = '<div class="smiley-sample">';
for($x = 0; $x < count($params['texts']); $x ++) {
$s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>';
}
}
else {
$params['string'] = preg_replace_callback('/&lt;(3+)/','self::preg_heart',$params['string']);
$s = str_replace($params['texts'],$params['icons'],$params['string']);
}
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','self::decode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','self::decode',$s);
return $s;
}
private function encode($m) {
return(str_replace($m[1],base64url_encode($m[1]),$m[0]));
}
private function decode($m) {
return(str_replace($m[1],base64url_decode($m[1]),$m[0]));
}
/**
* @brief expand <3333 to the correct number of hearts
*
* @param string $x
* @return string HTML Output
*
* @todo: Rework because it doesn't work correctly
*/
private function preg_heart($x) {
if(strlen($x[1]) == 1)
return $x[0];
$t = '';
for($cnt = 0; $cnt < strlen($x[1]); $cnt ++)
$t .= '<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" />';
$r = str_replace($x[0],$t,$x[0]);
return $r;
}
}

View file

@ -1,13 +1,15 @@
<?php
/**
* @file include/acl_selectors.php
*/
require_once("include/contact_selectors.php");
require_once("include/contact_widgets.php");
require_once("include/DirSearch.php");
require_once("include/features.php");
require_once("mod/proxy.php");
/**
*
*/
/**
* @package acl_selectors
@ -257,7 +259,7 @@ function prune_deadguys($arr) {
if(! $arr)
return $arr;
$str = dbesc(implode(',',$arr));
$r = q("select id from contact where id in ( " . $str . ") and blocked = 0 and pending = 0 and archive = 0 ");
$r = q("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 ");
if($r) {
$ret = array();
foreach($r as $rr)
@ -393,13 +395,14 @@ function acl_lookup(&$a, $out_type = 'json') {
if(!local_user())
return "";
$start = (x($_REQUEST,'start')?$_REQUEST['start']:0);
$count = (x($_REQUEST,'count')?$_REQUEST['count']:100);
$search = (x($_REQUEST,'search')?$_REQUEST['search']:"");
$type = (x($_REQUEST,'type')?$_REQUEST['type']:"");
$conv_id = (x($_REQUEST,'conversation')?$_REQUEST['conversation']:null);
$start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0);
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
$search = (x($_REQUEST,'search') ? $_REQUEST['search'] : "");
$type = (x($_REQUEST,'type') ? $_REQUEST['type'] : "");
$mode = (x($_REQUEST,'mode') ? $_REQUEST['mode'] : "");
$conv_id = (x($_REQUEST,'conversation') ? $_REQUEST['conversation'] : null);
// For use with jquery.autocomplete for private mail completion
// For use with jquery.textcomplete for private mail completion
if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
if(! $type)
@ -428,6 +431,7 @@ function acl_lookup(&$a, $out_type = 'json') {
$sql_extra2 .= " ".unavailable_networks();
// autocomplete for editor mentions
if ($type=='' || $type=='c'){
$r = q("SELECT COUNT(*) AS c FROM `contact`
WHERE `uid` = %d AND `self` = 0
@ -476,7 +480,7 @@ function acl_lookup(&$a, $out_type = 'json') {
if ($type=='' || $type=='g'){
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') as uids
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
FROM `group`,`group_member`
WHERE `group`.`deleted` = 0 AND `group`.`uid` = %d
AND `group_member`.`gid`=`group`.`id`
@ -505,7 +509,7 @@ function acl_lookup(&$a, $out_type = 'json') {
if ($type==''){
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, forum FROM `contact`
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != ''
AND NOT (`network` IN ('%s', '%s'))
$sql_extra2
@ -516,7 +520,7 @@ function acl_lookup(&$a, $out_type = 'json') {
}
elseif ($type=='c'){
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, forum FROM `contact`
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != ''
AND NOT (`network` IN ('%s'))
$sql_extra2
@ -538,36 +542,41 @@ function acl_lookup(&$a, $out_type = 'json') {
);
}
elseif($type == 'a') {
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag` FROM `contact`
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `pending` = 0
$sql_extra2
ORDER BY `name` ASC ",
intval(local_user())
);
}
elseif($type == 'x') {
// autocomplete for global contact search (e.g. navbar search)
$r = navbar_complete($a);
$contacts = array();
if($r) {
foreach($r as $g) {
$contacts[] = array(
"photo" => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
"name" => $g['name'],
"nick" => (x($g['addr']) ? $g['addr'] : $g['url']),
"network" => $g['network'],
"link" => $g['url'],
"forum" => (x($g['community']) ? 1 : 0),
);
}
}
$o = array(
'start' => $start,
'count' => $count,
'items' => $contacts,
);
echo json_encode($o);
killme();
}
else
$r = array();
if($type == 'm' || $type == 'a') {
$x = array();
$x['query'] = $search;
$x['photos'] = array();
$x['links'] = array();
$x['suggestions'] = array();
$x['data'] = array();
if(count($r)) {
foreach($r as $g) {
$x['photos'][] = proxy_url($g['micro'], false, PROXY_SIZE_MICRO);
$x['links'][] = $g['url'];
$x['suggestions'][] = htmlentities($g['name']);
$x['data'][] = intval($g['id']);
}
}
echo json_encode($x);
killme();
}
if(count($r)) {
foreach($r as $g){
$contacts[] = array(
@ -578,7 +587,7 @@ function acl_lookup(&$a, $out_type = 'json') {
"network" => $g['network'],
"link" => $g['url'],
"nick" => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
"forum" => $g['forum']
"forum" => ((x($g['forum']) || x($g['prv'])) ? 1 : 0),
);
}
}
@ -591,14 +600,10 @@ function acl_lookup(&$a, $out_type = 'json') {
function _contact_link($i){ return dbesc($i['link']); }
$known_contacts = array_map(_contact_link, $contacts);
$unknow_contacts=array();
$r = q("select
`author-avatar`,`author-name`,`author-link`
from item where parent=%d
and (
`author-name` LIKE '%%%s%%' OR
`author-link` LIKE '%%%s%%'
) and
`author-link` NOT IN ('%s')
$r = q("SELECT `author-avatar`,`author-name`,`author-link`
FROM `item` WHERE `parent` = %d
AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
AND `author-link` NOT IN ('%s')
GROUP BY `author-link`
ORDER BY `author-name` ASC
",
@ -632,26 +637,84 @@ function acl_lookup(&$a, $out_type = 'json') {
$tot += count($unknow_contacts);
}
$results = array(
"tot" => $tot,
"start" => $start,
"count" => $count,
"groups" => $groups,
"contacts" => $contacts,
"items" => $items,
"type" => $type,
"search" => $search,
);
call_hooks('acl_lookup_end', $results);
if($out_type === 'html') {
$o = array(
'tot' => $tot,
'start' => $start,
'count' => $count,
'groups' => $groups,
'contacts' => $contacts,
'tot' => $results["tot"],
'start' => $results["start"],
'count' => $results["count"],
'groups' => $results["groups"],
'contacts' => $results["contacts"],
);
return $o;
}
$o = array(
'tot' => $tot,
'start' => $start,
'count' => $count,
'items' => $items,
'tot' => $results["tot"],
'start' => $results["start"],
'count' => $results["count"],
'items' => $results["items"],
);
echo json_encode($o);
killme();
}
/**
* @brief Searching for global contacts for autocompletion
*
* @param App $a
* @return array with the search results
*/
function navbar_complete(&$a) {
// logger('navbar_complete');
if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
return;
}
// check if searching in the local global contact table is enabled
$localsearch = get_config('system','poco_local_search');
$search = $prefix.notags(trim($_REQUEST['search']));
$mode = $_REQUEST['mode'];
// don't search if search term has less than 2 characters
if(! $search || mb_strlen($search) < 2)
return array();
if(substr($search,0,1) === '@')
$search = substr($search,1);
if($localsearch) {
$x = DirSearch::global_search_by_name($search, $mode);
return $x;
}
if(! $localsearch) {
$p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : '');
$x = z_fetch_url(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search));
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j && $j['results']) {
return $j['results'];
}
}
}
return;
}

View file

@ -24,6 +24,7 @@
require_once('include/group.php');
require_once('include/like.php');
require_once('include/NotificationsManager.php');
require_once('include/plaintext.php');
define('API_METHOD_ANY','*');
@ -269,8 +270,6 @@
api_login($a);
}
load_contact_links(api_user());
logger('API call for ' . $a->user['username'] . ': ' . $a->query_string);
logger('API parameters: ' . print_r($_REQUEST,true));
@ -1310,7 +1309,7 @@
$r = q("SELECT STRAIGHT_JOIN `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d AND `verb` = '%s'
AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
@ -1334,9 +1333,12 @@
$idlist = implode(",", $idarray);
if ($idlist != "")
$r = q("UPDATE `item` SET `unseen` = 0 WHERE `unseen` AND `id` IN (%s)", $idlist);
if ($idlist != "") {
$unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `id` IN (%s)", $idlist);
if ($unseen)
$r = q("UPDATE `item` SET `unseen` = 0 WHERE `unseen` AND `id` IN (%s)", $idlist);
}
$data = array('$statuses' => $ret);
switch($type){
@ -1386,7 +1388,7 @@
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`,
`contact`.`id` AS `cid`,
`user`.`nickname`, `user`.`hidewall`
FROM `item` STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
STRAIGHT_JOIN `user` ON `user`.`uid` = `item`.`uid`
@ -1455,7 +1457,7 @@
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM `item`, `contact`
WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
AND `contact`.`id` = `item`.`contact-id` AND `item`.`uid` = %d AND `item`.`verb` = '%s'
@ -1524,15 +1526,21 @@
if ($max_id > 0)
$sql_extra = ' AND `item`.`id` <= '.intval($max_id);
// Not sure why this query was so complicated. We should keep it here for a while,
// just to make sure that we really don't need it.
// FROM `item` INNER JOIN (SELECT `uri`,`parent` FROM `item` WHERE `id` = %d) AS `temp1`
// ON (`item`.`thr-parent` = `temp1`.`uri` AND `item`.`parent` = `temp1`.`parent`)
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` INNER JOIN (SELECT `uri`,`parent` FROM `item` WHERE `id` = %d) AS `temp1`
ON (`item`.`thr-parent` = `temp1`.`uri` AND `item`.`parent` = `temp1`.`parent`), `contact`
WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
AND `item`.`uid` = %d AND `item`.`verb` = '%s' AND `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
`contact`.`id` AS `cid`
FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`parent` = %d AND `item`.`visible`
AND NOT `item`.`moderated` AND NOT `item`.`deleted`
AND `item`.`uid` = %d AND `item`.`verb` = '%s'
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
AND `item`.`id`>%d $sql_extra
ORDER BY `item`.`id` DESC LIMIT %d ,%d",
intval($id), intval(api_user()),
@ -1550,6 +1558,7 @@
return api_apply_template("timeline", $type, $data);
}
api_register_func('api/conversation/show','api_conversation_show', true);
api_register_func('api/statusnet/conversation','api_conversation_show', true);
/**
@ -1577,7 +1586,7 @@
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`, `contact`.`nick` as `reply_author`,
`contact`.`name`, `contact`.`photo` as `reply_photo`, `contact`.`url` as `reply_url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM `item`, `contact`
WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
AND `contact`.`id` = `item`.`contact-id`
@ -1690,7 +1699,7 @@
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM `item` FORCE INDEX (`uid_id`), `contact`
WHERE `item`.`uid` = %d AND `verb` = '%s'
AND NOT (`item`.`author-link` IN ('https://%s', 'http://%s'))
@ -1767,7 +1776,7 @@
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d AND `verb` = '%s'
AND `item`.`contact-id` = %d
@ -1895,7 +1904,7 @@
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM `item`, `contact`
WHERE `item`.`uid` = %d
AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
@ -2058,6 +2067,16 @@
$statushtml = trim(bbcode($body, false, false));
$search = array("<br>", "<blockquote>", "</blockquote>",
"<h1>", "</h1>", "<h2>", "</h2>",
"<h3>", "</h3>", "<h4>", "</h4>",
"<h5>", "</h5>", "<h6>", "</h6>");
$replace = array("<br>\n", "\n<blockquote>", "</blockquote>\n",
"\n<h1>", "</h1>\n", "\n<h2>", "</h2>\n",
"\n<h3>", "</h3>\n", "\n<h4>", "</h4>\n",
"\n<h5>", "</h5>\n", "\n<h6>", "</h6>\n");
$statushtml = str_replace($search, $replace, $statushtml);
if ($item['title'] != "")
$statushtml = "<h4>".bbcode($item['title'])."</h4>\n".$statushtml;
@ -2850,7 +2869,7 @@
$scale_sql = ($scale === false ? "" : sprintf("and scale=%d",intval($scale)));
$data_sql = ($scale === false ? "" : "data, ");
$r = q("select %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
$r = q("select %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`,
`type`, `height`, `width`, `datasize`, `profile`, min(`scale`) as minscale, max(`scale`) as maxscale
from photo where `uid` = %d and `resource-id` = '%s' %s group by `resource-id`",
$data_sql,
@ -3104,42 +3123,37 @@
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",'[url=$1]$1[/url]',$Text);
}
$Text = preg_replace_callback("((.*?)\[class=(.*?)\](.*?)\[\/class\])ism","api_cleanup_share",$Text);
// Simplify "attachment" element
$Text = api_clean_attachments($Text);
return($Text);
}
function api_cleanup_share($shared) {
if ($shared[2] != "type-link")
return($shared[0]);
/**
* @brief Removes most sharing information for API text export
*
* @param string $body The original body
*
* @return string Cleaned body
*/
function api_clean_attachments($body) {
$data = get_attachment_data($body);
if (!preg_match_all("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism",$shared[3], $bookmark))
return($shared[0]);
if (!$data)
return $body;
$title = "";
$link = "";
$body = "";
if (isset($bookmark[2][0]))
$title = $bookmark[2][0];
if (isset($data["text"]))
$body = $data["text"];
if (isset($bookmark[1][0]))
$link = $bookmark[1][0];
if (($body == "") AND (isset($data["title"])))
$body = $data["title"];
if (strpos($shared[1],$title) !== false)
$title = "";
if (isset($data["url"]))
$body .= "\n".$data["url"];
if (strpos($shared[1],$link) !== false)
$link = "";
$text = trim($shared[1]);
//if (strlen($text) < strlen($title))
if (($text == "") AND ($title != ""))
$text .= "\n\n".trim($title);
if ($link != "")
$text .= "\n".trim($link);
return(trim($text));
return $body;
}
function api_best_nickname(&$contacts) {

View file

@ -1,78 +1,79 @@
<?php
require_once('include/security.php');
require_once('include/datetime.php');
function nuke_session() {
if (get_config('system', 'disable_database_session')) {
session_unset();
return;
// When the "Friendica" cookie is set, take the value to authenticate and renew the cookie.
if (isset($_COOKIE["Friendica"])) {
$data = json_decode($_COOKIE["Friendica"]);
if (isset($data->uid)) {
$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
FROM `user` WHERE `uid` = %d AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1",
intval($data->uid)
);
if ($r) {
if ($data->hash != cookie_hash($r[0])) {
logger("Hash for user ".$data->uid." doesn't fit.");
nuke_session();
goaway(z_root());
}
// Renew the cookie
new_cookie(604800, $r[0]);
// Do the authentification if not done by now
if (!isset($_SESSION) OR !isset($_SESSION['authenticated'])) {
authenticate_success($r[0]);
if (get_config('system','paranoia'))
$_SESSION['addr'] = $data->ip;
}
}
}
new_cookie(0); // make sure cookie is deleted on browser close, as a security measure
unset($_SESSION['authenticated']);
unset($_SESSION['uid']);
unset($_SESSION['visitor_id']);
unset($_SESSION['administrator']);
unset($_SESSION['cid']);
unset($_SESSION['theme']);
unset($_SESSION['mobile-theme']);
unset($_SESSION['page_flags']);
unset($_SESSION['submanage']);
unset($_SESSION['my_url']);
unset($_SESSION['my_address']);
unset($_SESSION['addr']);
unset($_SESSION['return_url']);
}
// login/logout
if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params') || ($_POST['auth-params'] !== 'login'))) {
if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-params'))) || ($_POST['auth-params'] !== 'login'))) {
if(((x($_POST,'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) {
if ((x($_POST,'auth-params') && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) {
// process logout request
call_hooks("logging_out");
nuke_session();
info( t('Logged out.') . EOL);
info(t('Logged out.').EOL);
goaway(z_root());
}
if(x($_SESSION,'visitor_id') && (! x($_SESSION,'uid'))) {
if (x($_SESSION,'visitor_id') && !x($_SESSION,'uid')) {
$r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($_SESSION['visitor_id'])
);
if(count($r)) {
if (count($r)) {
$a->contact = $r[0];
}
}
if(x($_SESSION,'uid')) {
if (x($_SESSION,'uid')) {
// already logged in user returning
$check = get_config('system','paranoia');
// extra paranoia - if the IP changed, log them out
if($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) {
logger('Session address changed. Paranoid setting in effect, blocking session. '
. $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']);
if ($check && ($_SESSION['addr'] != $_SERVER['REMOTE_ADDR'])) {
logger('Session address changed. Paranoid setting in effect, blocking session. '.
$_SESSION['addr'].' != '.$_SERVER['REMOTE_ADDR']);
nuke_session();
goaway(z_root());
}
$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
FROM `user` WHERE `uid` = %d AND `blocked` = 0 AND `account_expired` = 0 AND `account_removed` = 0 AND `verified` = 1 LIMIT 1",
FROM `user` WHERE `uid` = %d AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1",
intval($_SESSION['uid'])
);
if(! count($r)) {
if (!count($r)) {
nuke_session();
goaway(z_root());
}
@ -80,32 +81,29 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
// Make sure to refresh the last login time for the user if the user
// stays logged in for a long time, e.g. with "Remember Me"
$login_refresh = false;
if(! x($_SESSION['last_login_date'])) {
if (!x($_SESSION['last_login_date'])) {
$_SESSION['last_login_date'] = datetime_convert('UTC','UTC');
}
if( strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0 ) {
if (strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0) {
$_SESSION['last_login_date'] = datetime_convert('UTC','UTC');
$login_refresh = true;
}
authenticate_success($r[0], false, false, $login_refresh);
}
}
else {
} else {
if(isset($_SESSION)) {
nuke_session();
}
session_unset();
if((x($_POST,'password')) && strlen($_POST['password']))
if (x($_POST,'password') && strlen($_POST['password']))
$encrypted = hash('whirlpool',trim($_POST['password']));
else {
if((x($_POST,'openid_url')) && strlen($_POST['openid_url']) ||
if ((x($_POST,'openid_url')) && strlen($_POST['openid_url']) ||
(x($_POST,'username')) && strlen($_POST['username'])) {
$noid = get_config('system','no_openid');
$openid_url = trim((strlen($_POST['openid_url'])?$_POST['openid_url']:$_POST['username']) );
$openid_url = trim((strlen($_POST['openid_url'])?$_POST['openid_url']:$_POST['username']));
// validate_url alters the calling parameter
@ -113,36 +111,36 @@ else {
// if it's an email address or doesn't resolve to a URL, fail.
if(($noid) || (strpos($temp_string,'@')) || (! validate_url($temp_string))) {
if ($noid || strpos($temp_string,'@') || !validate_url($temp_string)) {
$a = get_app();
notice( t('Login failed.') . EOL);
notice(t('Login failed.').EOL);
goaway(z_root());
// NOTREACHED
}
// Otherwise it's probably an openid.
try {
require_once('library/openid.php');
$openid = new LightOpenID;
$openid->identity = $openid_url;
$_SESSION['openid'] = $openid_url;
$a = get_app();
$openid->returnUrl = $a->get_baseurl(true) . '/openid';
goaway($openid->authUrl());
} catch (Exception $e) {
notice( t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'. t('The error message was:').' '.$e->getMessage());
}
try {
require_once('library/openid.php');
$openid = new LightOpenID;
$openid->identity = $openid_url;
$_SESSION['openid'] = $openid_url;
$a = get_app();
$openid->returnUrl = $a->get_baseurl(true).'/openid';
goaway($openid->authUrl());
} catch (Exception $e) {
notice(t('We encountered a problem while logging in with the OpenID you provided. Please check the correct spelling of the ID.').'<br /><br >'.t('The error message was:').' '.$e->getMessage());
}
// NOTREACHED
}
}
if((x($_POST,'auth-params')) && $_POST['auth-params'] === 'login') {
if (x($_POST,'auth-params') && $_POST['auth-params'] === 'login') {
$record = null;
$addon_auth = array(
'username' => trim($_POST['username']),
'username' => trim($_POST['username']),
'password' => trim($_POST['password']),
'authenticated' => 0,
'user_record' => null
@ -158,48 +156,37 @@ else {
call_hooks('authenticate', $addon_auth);
if(($addon_auth['authenticated']) && (count($addon_auth['user_record']))) {
if ($addon_auth['authenticated'] && count($addon_auth['user_record']))
$record = $addon_auth['user_record'];
}
else {
// process normal login request
$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
FROM `user` WHERE ( `email` = '%s' OR `nickname` = '%s' )
AND `password` = '%s' AND `blocked` = 0 AND `account_expired` = 0 AND `account_removed` = 0 AND `verified` = 1 LIMIT 1",
FROM `user` WHERE (`email` = '%s' OR `nickname` = '%s')
AND `password` = '%s' AND NOT `blocked` AND NOT `account_expired` AND NOT `account_removed` AND `verified` LIMIT 1",
dbesc(trim($_POST['username'])),
dbesc(trim($_POST['username'])),
dbesc($encrypted)
);
if(count($r))
if (count($r))
$record = $r[0];
}
if((! $record) || (! count($record))) {
logger('authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR']);
notice( t('Login failed.') . EOL );
if (!$record || !count($record)) {
logger('authenticate: failed login attempt: '.notags(trim($_POST['username'])).' from IP '.$_SERVER['REMOTE_ADDR']);
notice(t('Login failed.').EOL);
goaway(z_root());
}
}
// If the user specified to remember the authentication, then change the cookie
// to expire after one year (the default is when the browser is closed).
// If the user did not specify to remember, change the cookie to expire when the
// browser is closed. The reason this is necessary is because if the user
// specifies to remember, then logs out and logs back in without specifying to
// remember, the old "remember" cookie may remain and prevent the session from
// expiring when the browser is closed.
//
// It seems like I should be able to test for the old cookie, but for some reason when
// I read the lifetime value from session_get_cookie_params(), I always get '0'
// (i.e. expire when the browser is closed), even when there's a time expiration
// on the cookie
if($_POST['remember']) {
new_cookie(31449600); // one year
}
else {
// If the user specified to remember the authentication, then set a cookie
// that expires after one week (the default is when the browser is closed).
// The cookie will be renewed automatically.
// The week ensures that sessions will expire after some inactivity.
if ($_POST['remember'])
new_cookie(604800, $r[0]);
else
new_cookie(0); // 0 means delete on browser exit
}
// if we haven't failed up this point, log them in.
@ -208,14 +195,48 @@ else {
}
}
function new_cookie($time) {
if (!get_config('system', 'disable_database_session'))
$old_sid = session_id();
/**
* @brief Kills the "Friendica" cookie and all session data
*/
function nuke_session() {
new_cookie(-3600); // make sure cookie is deleted on browser close, as a security measure
session_unset();
session_destroy();
}
/**
* @brief Calculate the hash that is needed for the "Friendica" cookie
*
* @param array $user Record from "user" table
*
* @return string Hashed data
*/
function cookie_hash($user) {
return(hash("sha256", get_config("system", "site_prvkey").
$user["uprvkey"].
$user["password"]));
}
/**
* @brief Set the "Friendica" cookie
*
* @param int $time
* @param array $user Record from "user" table
*/
function new_cookie($time, $user = array()) {
if ($time != 0)
$time = $time + time();
if ($user)
$value = json_encode(array("uid" => $user["uid"],
"hash" => cookie_hash($user),
"ip" => $_SERVER['REMOTE_ADDR']));
else
$value = "";
setcookie("Friendica", $value, $time, "/", "",
(get_config('system', 'ssl_policy') == SSL_POLICY_FULL), true);
session_set_cookie_params($time);
if (!get_config('system', 'disable_database_session')) {
session_regenerate_id(false);
q("UPDATE session SET sid = '%s' WHERE sid = '%s'", dbesc(session_id()), dbesc($old_sid));
}
}

View file

@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
$baseDir = dirname($vendorDir);
return array(
'Friendica\\' => array($baseDir . '/include'),
);

View file

@ -4,6 +4,7 @@ require_once('include/event.php');
require_once('include/map.php');
require_once('mod/proxy.php');
require_once('include/Contact.php');
require_once('include/plaintext.php');
function bb_PictureCacheExt($matches) {
if (strpos($matches[3], "data:image/") === 0)
@ -31,238 +32,101 @@ function bb_map_location($match) {
}
function bb_attachment($Text, $simplehtml = false, $tryoembed = true) {
$Text = preg_replace_callback("/(.*?)\[attachment(.*?)\](.*?)\[\/attachment\]/ism",
function ($match) use ($simplehtml, $tryoembed){
$attributes = $match[2];
$data = get_attachment_data($Text);
$type = "";
preg_match("/type='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$type = strtolower($matches[1]);
if (!$data)
return $Text;
preg_match('/type="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$type = strtolower($matches[1]);
if ($type == "")
return($match[0]);
if (!in_array($type, array("link", "audio", "video")))
return($match[0]);
$url = "";
preg_match("/url='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$url = $matches[1];
preg_match('/url="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$url = $matches[1];
$title = "";
preg_match("/title='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$title = $matches[1];
preg_match('/title="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$title = $matches[1];
//$title = htmlentities($title, ENT_QUOTES, 'UTF-8', false);
$title = bbcode(html_entity_decode($title, ENT_QUOTES, 'UTF-8'), false, false, true);
$title = str_replace(array("[", "]"), array("&#91;", "&#93;"), $title);
$image = "";
if ($type != "video") {
preg_match("/image='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$image = $matches[1];
preg_match('/image="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$image = $matches[1];
}
$preview = "";
if ($type != "video") {
preg_match("/preview='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$preview = $matches[1];
preg_match('/preview="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$preview = $matches[1];
}
if (((strpos($match[1], "[img=") !== false) OR (strpos($match[1], "[img]") !== false)) AND ($image != "")) {
$preview = $image;
$image = "";
}
if ($simplehtml == 7) {
$title2 = $title;
$test1 = trim(html_entity_decode($match[1],ENT_QUOTES,'UTF-8'));
$test2 = trim(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
// If the link description is similar to the text above then don't add the link description
if (($title != "") AND ((strpos($test1,$test2) !== false) OR
(similar_text($test1,$test2) / strlen($title)) > 0.9))
$title2 = $url;
$text = sprintf('<a href="%s" title="%s" class="attachment thumbnail" rel="nofollow external">%s</a><br />',
$url, $title, $title2);
} elseif (($simplehtml != 4) AND ($simplehtml != 0))
$text = sprintf('<a href="%s" target="_blank">%s</a><br>', $url, $title);
else {
$text = sprintf('<span class="type-%s">', $type);
$bookmark = array(sprintf('[bookmark=%s]%s[/bookmark]', $url, $title), $url, $title);
if ($tryoembed)
$oembed = tryoembed($bookmark);
else
$oembed = $bookmark[0];
if (strstr(strtolower($oembed), "<iframe "))
$text = $oembed;
else {
if (($image != "") AND !strstr(strtolower($oembed), "<img "))
$text .= sprintf('<a href="%s" target="_blank"><img src="%s" alt="" title="%s" class="attachment-image" /></a><br />', $url, proxy_url($image), $title);
elseif (($preview != "") AND !strstr(strtolower($oembed), "<img "))
$text .= sprintf('<a href="%s" target="_blank"><img src="%s" alt="" title="%s" class="attachment-preview" /></a><br />', $url, proxy_url($preview), $title);
$text .= $oembed;
$text .= sprintf('<blockquote>%s</blockquote></span>', trim($match[3]));
}
}
return($match[1].$text);
},$Text);
return($Text);
}
function bb_rearrange_share($shared) {
if (!in_array(strtolower($shared[2]), array("type-link", "type-audio", "type-video")))
return($shared[0]);
if (!preg_match_all("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism",$shared[3], $bookmark))
return($shared[0]);
$type = substr(trim(strtolower($shared[2])), 5);
$title = "";
$url = "";
$preview = "";
$description = "";
if (isset($bookmark[2][0]))
$title = $bookmark[2][0];
if (isset($bookmark[1][0]))
$url = $bookmark[1][0];
$cleanedshare = trim($shared[3]);
$cleanedshare = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $cleanedshare);
preg_match("/\[img\](.*?)\[\/img\]/ism", $cleanedshare, $matches);
if ($matches)
$preview = trim($matches[1]);
preg_match("/\[quote\](.*?)\[\/quote\]/ism", $cleanedshare, $matches);
if ($matches)
$description = trim($matches[1]);
$url = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($url, ENT_QUOTES, 'UTF-8', false));
$title = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($title, ENT_QUOTES, 'UTF-8', false));
$preview = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($preview, ENT_QUOTES, 'UTF-8', false));
$Text = trim($shared[1])."\n[attachment type='".$type."'";
if ($url != "")
$Text .= " url='".$url."'";
if ($title != "")
$Text .= " title='".$title."'";
if ($preview != "") {
require_once("include/Photo.php");
$picturedata = get_photo_info($preview);
if (count($picturedata) > 0) {
// if the preview picture is larger than 500 pixels then show it in a larger mode
// But only, if the picture isn't higher than large (To prevent huge posts)
if (($picturedata[0] >= 500) AND ($picturedata[0] >= $picturedata[1]))
$Text .= " image='".$preview."'";
else
$Text .= " preview='".$preview."'";
} else
$Text .= " preview='".$preview."'";
if (isset($data["title"])) {
$data["title"] = strip_tags($data["title"]);
$data["title"] = str_replace(array("http://", "https://"), "", $data["title"]);
}
$Text .= "]".$description."[/attachment]";
return($Text);
if (((strpos($data["text"], "[img=") !== false) OR (strpos($data["text"], "[img]") !== false)) AND ($data["image"] != "")) {
$data["preview"] = $data["image"];
$data["image"] = "";
}
if ($simplehtml == 7) {
$title2 = $data["title"];
$test1 = trim(html_entity_decode($data["text"],ENT_QUOTES,'UTF-8'));
$test2 = trim(html_entity_decode($data["title"],ENT_QUOTES,'UTF-8'));
// If the link description is similar to the text above then don't add the link description
if (($data["title"] != "") AND ((strpos($test1,$test2) !== false) OR
(similar_text($test1,$test2) / strlen($data["title"])) > 0.9))
$title2 = $data["url"];
$text = sprintf('<a href="%s" title="%s" class="attachment thumbnail" rel="nofollow external">%s</a><br />',
$data["url"], $data["title"], $title2);
} elseif (($simplehtml != 4) AND ($simplehtml != 0))
$text = sprintf('<a href="%s" target="_blank">%s</a><br>', $data["url"], $data["title"]);
else {
$text = sprintf('<span class="type-%s">', $data["type"]);
$bookmark = array(sprintf('[bookmark=%s]%s[/bookmark]', $data["url"], $data["title"]), $data["url"], $data["title"]);
if ($tryoembed)
$oembed = tryoembed($bookmark);
else
$oembed = $bookmark[0];
if (strstr(strtolower($oembed), "<iframe "))
$text = $oembed;
else {
if (($data["image"] != "") AND !strstr(strtolower($oembed), "<img "))
$text .= sprintf('<a href="%s" target="_blank"><img src="%s" alt="" title="%s" class="attachment-image" /></a><br />', $data["url"], proxy_url($data["image"]), $data["title"]);
elseif (($data["preview"] != "") AND !strstr(strtolower($oembed), "<img "))
$text .= sprintf('<a href="%s" target="_blank"><img src="%s" alt="" title="%s" class="attachment-preview" /></a><br />', $data["url"], proxy_url($data["preview"]), $data["title"]);
if (($data["type"] == "photo") AND ($data["url"] != "") AND ($data["image"] != ""))
$text .= sprintf('<a href="%s" target="_blank"><img src="%s" alt="" title="%s" class="attachment-image" /></a>', $data["url"], proxy_url($data["image"]), $data["title"]);
else
$text .= $oembed;
if (trim($data["description"]) != "")
$text .= sprintf('<blockquote>%s</blockquote></span>', trim($data["description"]));
}
}
return $data["text"].$text.$data["after"];
}
function bb_remove_share_information($Text, $plaintext = false, $nolink = false) {
$Text = preg_replace_callback("((.*?)\[class=(.*?)\](.*?)\[\/class\])ism",
function ($match) use ($plaintext, $nolink){
return(bb_cleanup_share($match, $plaintext, $nolink));
},$Text);
return($Text);
}
function bb_cleanup_share($shared, $plaintext, $nolink) {
$shared[1] = trim($shared[1]);
$data = get_attachment_data($Text);
if (!in_array($shared[2], array("type-link", "type-video")))
return($shared[0]);
if ($plaintext)
$shared[3] = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism","[bookmark=$1]$1[/bookmark]", $shared[3]);
if (!preg_match_all("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism",$shared[3], $bookmark))
return($shared[0]);
if (!$data)
return $Text;
if ($nolink)
return($shared[1]);
return $data["text"].$data["after"];
$title = "";
$link = "";
$title = htmlentities($data["title"], ENT_QUOTES, 'UTF-8', false);
$text = htmlentities($data["text"], ENT_QUOTES, 'UTF-8', false);
if ($plaintext OR (($title != "") AND strstr($text, $title)))
$data["title"] = $data["url"];
elseif (($text != "") AND strstr($title, $text)) {
$data["text"] = $data["title"];
$data["title"] = $data["url"];
}
if (isset($bookmark[2][0]))
$title = $bookmark[2][0];
if (isset($bookmark[1][0]))
$link = $bookmark[1][0];
if (($shared[1] != "") AND (strpos($title, $shared[1]) !== false))
$shared[1] = $title;
if (($title != "") AND ((strpos($shared[1],$title) !== false) OR
(similar_text($shared[1],$title) / strlen($title)) > 0.9))
$title = "";
// if (strpos($shared[1],$link) !== false)
// $link = "";
$text = trim($shared[1]);
if (($text == "") AND ($title != "") AND ($link == ""))
$text .= "\n\n".trim($title);
if (($data["text"] == "") AND ($data["title"] != "") AND ($data["url"] == ""))
return $data["title"].$data["after"];
// If the link already is included in the post, don't add it again
if (($link != "") AND strpos($text, $link))
return(trim($text));
if (($data["url"] != "") AND strpos($data["text"], $data["url"]))
return $data["text"].$data["after"];
if (($link != "") AND ($title != ""))
$text .= "\n[url=".trim($link)."]".trim($title)."[/url]";
elseif (($link != ""))
$text .= "\n".trim($link);
$text = $data["text"];
return(trim($text));
if (($data["url"] != "") AND ($data["title"] != ""))
$text .= "\n[url=".$data["url"]."]".$data["title"]."[/url]";
elseif (($data["url"] != ""))
$text .= "\n".$data["url"];
return $text."\n".$data["after"];
}
function bb_cleanstyle($st) {
return "<span style=\"".cleancss($st[1]).";\">".$st[2]."</span>";
}
@ -311,6 +175,9 @@ function tryoembed($match){
$o = oembed_fetch_url($url);
if (!is_object($o))
return $match[0];
if (isset($match[2]))
$o->title = $match[2];
@ -529,18 +396,17 @@ function bb_ShareAttributes($share, $simplehtml) {
$itemcache = get_itemcachepath();
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$posted = $matches[1];
preg_match('/posted="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$posted = $matches[1];
// relative dates only make sense when they aren't cached
if ($itemcache == "") {
preg_match("/posted='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$posted = $matches[1];
preg_match('/posted="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$posted = $matches[1];
if ($itemcache == "")
$reldate = (($posted) ? " " . relative_date($posted) : '');
}
$data = get_contact_details_by_url($profile);
@ -622,13 +488,20 @@ function bb_ShareAttributes($share, $simplehtml) {
$text .= "<br /><br />".$link;
break;
default:
$headline = trim($share[1]).'<div class="shared_header">';
if ($avatar != "")
$headline .= '<img src="'.proxy_url($avatar, false, PROXY_SIZE_MICRO).'" height="32" width="32" >';
$text = trim($share[1])."\n";
$headline .= sprintf(t('<span><a href="%s" target="_blank">%s</a> wrote the following <a href="%s" target="_blank">post</a>'.$reldate.':</span>'), $profile, $author, $link);
$headline .= "</div>";
$text = $headline.'<blockquote class="shared_content">'.trim($share[3])."</blockquote>";
$tpl = get_markup_template('shared_content.tpl');
$text .= replace_macros($tpl,
array(
'$profile' => $profile,
'$avatar' => $avatar,
'$author' => $author,
'$link' => $link,
'$posted' => $posted,
'$reldate' => $reldate,
'$content' => trim($share[3])
)
);
break;
}
return($text);
@ -892,9 +765,6 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$Text = preg_replace("/\n\[code\]/ism", "[code]", $Text);
$Text = preg_replace("/\[\/code\]\n/ism", "[/code]", $Text);
// Rearrange shares to attachments
$Text = preg_replace_callback("((.*?)\[class=(.*?)\](.*?)\[\/class\])ism", "bb_rearrange_share",$Text);
// when the content is meant exporting to other systems then remove the avatar picture since this doesn't really look good on these systems
if (!$tryoembed)
$Text = preg_replace("/\[share(.*?)avatar\s?=\s?'.*?'\s?(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","\n[share$1$2]$3[/share]",$Text);
@ -945,7 +815,10 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$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>',
$Text);
elseif (!$simplehtml)
$Text = preg_replace("/([@])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<a href="$2" class="userinfo mention" title="$3">$3</a>',
$Text);
// Bookmarks in red - will be converted to bookmarks in friendica
$Text = preg_replace("/#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '[bookmark=$1]$1[/bookmark]', $Text);
@ -987,6 +860,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
if ($tryoembed)
$Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism",'tryoembed',$Text);
$Text = preg_replace("/([#])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<a href="$2" class="tag" title="$3">$3</a>', $Text);
$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank">$1</a>', $Text);
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $Text);
//$Text = preg_replace("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $Text);

View file

@ -1,8 +1,8 @@
<?php
/**
*
* Arbitrary configuration storage
* @file include/config.php
*
* @brief (Deprecated) Arbitrary configuration storage
* Note:
* Please do not store booleans - convert to 0/1 integer values
* The get_?config() functions return boolean false for keys that are unset,
@ -12,330 +12,140 @@
* configurations need to be fixed as of 10/08/2011.
*/
use \Friendica\Core\Config;
use \Friendica\Core\PConfig;
// retrieve a "family" of config variables from database to cached storage
if(! function_exists('load_config')) {
/**
* @brief (Deprecated) Loads all configuration values of family into a cached storage.
*
* Note: This function is deprecated. Use Config::load() instead.
*
* @param string $family
* The category of the configuration value
* @return void
*/
function load_config($family) {
global $a;
return Config::load($family);
}
$r = q("SELECT `v`, `k` FROM `config` WHERE `cat` = '%s'", dbesc($family));
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
if ($family === 'config') {
$a->config[$k] = $rr['v'];
} else {
$a->config[$family][$k] = $rr['v'];
}
}
} else if ($family != 'config') {
// Negative caching
$a->config[$family] = "!<unset>!";
}
}}
/**
* @brief (Deprecated) Get a particular user's config variable given the category name
* ($family) and a key.
*
* Note: This function is deprecated. Use Config::get() instead.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $refresh
* If true the config is loaded from the db and not from the cache
* @return mixed Stored value or false if it does not exist
*/
function get_config($family, $key, $refresh = false) {
$v = Config::get($family, $key, false, $refresh);
return $v;
}
// get a particular config variable given the family name
// and key. Returns false if not set.
// $instore is only used by the set_config function
// to determine if the key already exists in the DB
// If a key is found in the DB but doesn't exist in
// local config cache, pull it into the cache so we don't have
// to hit the DB again for this item.
if(! function_exists('get_config')) {
function get_config($family, $key, $instore = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$family])) {
if($a->config[$family] === '!<unset>!') {
return false;
}
}
if(isset($a->config[$family][$key])) {
if($a->config[$family][$key] === '!<unset>!') {
return false;
}
return $a->config[$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($family."|".$key)) {
$val = apc_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_fetch") AND function_exists("xcache_isset"))
if (xcache_isset($family."|".$key)) {
$val = xcache_fetch($family."|".$key);
$a->config[$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
*/
$ret = q("SELECT `v` FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
if(count($ret)) {
// manage array value
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, '!<unset>!', 600);*/
}
return false;
}}
// Store a config value ($value) in the category ($family)
// under the key ($key)
// Return the value, or false if the database update failed
if(! function_exists('set_config')) {
/**
* @brief (Deprecated) Sets a configuration value for system config
*
* Note: This function is deprecated. Use Config::set() instead.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false if the database update failed
*/
function set_config($family,$key,$value) {
global $a;
return Config::set($family, $key, $value);
}
// If $a->config[$family] has been previously set to '!<unset>!', then
// $a->config[$family][$key] will evaluate to $a->config[$family][0], and
// $a->config[$family][$key] = $value will be equivalent to
// $a->config[$family][0] = $value[0] (this causes infuriating bugs),
// so unset the family before assigning a value to a family's key
if($a->config[$family] === '!<unset>!')
unset($a->config[$family]);
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
$dbvalue = (is_bool($dbvalue) ? intval($dbvalue) : $dbvalue);
if(get_config($family,$key,true) === false) {
$a->config[$family][$key] = $value;
$ret = q("INSERT INTO `config` ( `cat`, `k`, `v` ) VALUES ( '%s', '%s', '%s' ) ",
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `config` SET `v` = '%s' WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
dbesc($family),
dbesc($key)
);
$a->config[$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}}
if(! function_exists('load_pconfig')) {
function load_pconfig($uid,$family) {
global $a;
$r = q("SELECT `v`,`k` FROM `pconfig` WHERE `cat` = '%s' AND `uid` = %d",
dbesc($family),
intval($uid)
);
if(count($r)) {
foreach($r as $rr) {
$k = $rr['k'];
$a->config[$uid][$family][$k] = $rr['v'];
}
} else if ($family != 'config') {
// Negative caching
$a->config[$uid][$family] = "!<unset>!";
}
}}
if(! function_exists('get_pconfig')) {
function get_pconfig($uid,$family, $key, $instore = false) {
global $a;
if(! $instore) {
// Looking if the whole family isn't set
if(isset($a->config[$uid][$family])) {
if($a->config[$uid][$family] === '!<unset>!') {
return false;
}
}
if(isset($a->config[$uid][$family][$key])) {
if($a->config[$uid][$family][$key] === '!<unset>!') {
return false;
}
return $a->config[$uid][$family][$key];
}
}
// If APC is enabled then fetch the data from there, else try XCache
/*if (function_exists("apc_fetch") AND function_exists("apc_exists"))
if (apc_exists($uid."|".$family."|".$key)) {
$val = apc_fetch($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}
elseif (function_exists("xcache_get") AND function_exists("xcache_isset"))
if (xcache_isset($uid."|".$family."|".$key)) {
$val = xcache_get($uid."|".$family."|".$key);
$a->config[$uid][$family][$key] = $val;
if ($val === '!<unset>!')
return false;
else
return $val;
}*/
$ret = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s' LIMIT 1",
intval($uid),
dbesc($family),
dbesc($key)
);
if(count($ret)) {
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret[0]['v'])?unserialize( $ret[0]['v']):$ret[0]['v']);
$a->config[$uid][$family][$key] = $val;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $val, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $val, 600);*/
return $val;
}
else {
$a->config[$uid][$family][$key] = '!<unset>!';
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, '!<unset>!', 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, '!<unset>!', 600);*/
}
return false;
}}
if(! function_exists('del_config')) {
/**
* @brief (Deprecated) Deletes the given key from the system configuration.
*
* Note: This function is deprecated. Use Config::delete() instead.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
function del_config($family,$key) {
return Config::delete($family, $key);
}
global $a;
if(x($a->config[$family],$key))
unset($a->config[$family][$key]);
$ret = q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s'",
dbesc($family),
dbesc($key)
);
// If APC is enabled then delete the data from there, else try XCache
/*if (function_exists("apc_delete"))
apc_delete($family."|".$key);
elseif (function_exists("xcache_unset"))
xcache_unset($family."|".$key);*/
/**
* @brief (Deprecated) Loads all configuration values of a user's config family into a cached storage.
*
* Note: This function is deprecated. Use PConfig::load() instead.
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @return void
*/
function load_pconfig($uid,$family) {
return PConfig::load($uid, $family);
}
return $ret;
}}
/**
* @brief (Deprecated) Get a particular user's config variable given the category name
* ($family) and a key.
*
* Note: This function is deprecated. Use PConfig::get() instead.
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $refresh
* If true the config is loaded from the db and not from the cache
* @return mixed Stored value or false if it does not exist
*/
function get_pconfig($uid, $family, $key, $refresh = false) {
$v = PConfig::get($uid, $family, $key, false, $refresh);
return $v;
}
// Same as above functions except these are for personal config storage and take an
// additional $uid argument.
if(! function_exists('set_pconfig')) {
/**
* @brief (Deprecated) Sets a configuration value for a user
*
* Note: This function is deprecated. Use PConfig::set() instead.
*
* @param string $uid
* The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to set
* @param string $value
* The value to store
* @return mixed Stored $value or false
*/
function set_pconfig($uid,$family,$key,$value) {
return PConfig::set($uid, $family, $key, $value);
}
global $a;
// manage array value
$dbvalue = (is_array($value)?serialize($value):$value);
if(get_pconfig($uid,$family,$key,true) === false) {
$a->config[$uid][$family][$key] = $value;
$ret = q("INSERT INTO `pconfig` ( `uid`, `cat`, `k`, `v` ) VALUES ( %d, '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
);
if($ret)
return $value;
return $ret;
}
$ret = q("UPDATE `pconfig` SET `v` = '%s' WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
dbesc($dbvalue),
intval($uid),
dbesc($family),
dbesc($key)
);
$a->config[$uid][$family][$key] = $value;
// If APC is enabled then store the data there, else try XCache
/*if (function_exists("apc_store"))
apc_store($uid."|".$family."|".$key, $value, 600);
elseif (function_exists("xcache_set"))
xcache_set($uid."|".$family."|".$key, $value, 600);*/
if($ret)
return $value;
return $ret;
}}
if(! function_exists('del_pconfig')) {
/**
* @brief (Deprecated) Deletes the given key from the users's configuration.
*
* Note: This function is deprecated. Use PConfig::delete() instead.
*
* @param string $uid The user_id
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to delete
* @return mixed
*/
function del_pconfig($uid,$family,$key) {
global $a;
if(x($a->config[$uid][$family],$key))
unset($a->config[$uid][$family][$key]);
$ret = q("DELETE FROM `pconfig` WHERE `uid` = %d AND `cat` = '%s' AND `k` = '%s'",
intval($uid),
dbesc($family),
dbesc($key)
);
return $ret;
}}
return PConfig::delete($uid, $family, $key);
}

View file

@ -99,7 +99,7 @@ function network_to_name($s, $profile = "") {
$networkname = str_replace($search,$replace,$s);
if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora_is_redmatrix($profile)) {
if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora::is_redmatrix($profile)) {
$networkname = t("Hubzilla/Redmatrix");
$r = q("SELECT `gserver`.`platform` FROM `gcontact`

View file

@ -373,6 +373,86 @@ function visible_activity($item) {
return true;
}
/**
* @brief List of all contact fields that are needed for the conversation function
*/
function contact_fieldlist() {
$fieldlist = "`contact`.`network`, `contact`.`url`, `contact`.`name`, `contact`.`writable`,
`contact`.`self`, `contact`.`id` AS `cid`, `contact`.`alias`";
return $fieldlist;
}
/**
* @brief SQL condition for contacts
*/
function contact_condition() {
$condition = "NOT `contact`.`blocked` AND NOT `contact`.`pending`";
return $condition;
}
/**
* @brief List of all item fields that are needed for the conversation function
*/
function item_fieldlist() {
/*
These Fields are not added below (yet). They are here to for bug search.
`item`.`type`,
`item`.`extid`,
`item`.`received`,
`item`.`changed`,
`item`.`author-avatar`,
`item`.`object`,
`item`.`target-type`,
`item`.`target`,
`item`.`resource-id`,
`item`.`tag`,
`item`.`attach`,
`item`.`inform`,
`item`.`pubmail`,
`item`.`moderated`,
`item`.`visible`,
`item`.`spam`,
`item`.`starred`,
`item`.`bookmark`,
`item`.`unseen`,
`item`.`deleted`,
`item`.`origin`,
`item`.`forum_mode`,
`item`.`last-child`,
`item`.`mention`,
`item`.`global`,
`item`.`gcontact-id`,
`item`.`shadow`,
*/
$fieldlist = "`item`.`author-link`, `item`.`verb`, `item`.`id`, `item`.`parent`, `item`.`file`,
`item`.`uid`, `item`.`author-name`, `item`.`location`, `item`.`coord`,
`item`.`title`, `item`.`uri`, `item`.`created`, `item`.`app`, `item`.`guid`,
`item`.`contact-id`, `item`.`thr-parent`, `item`.`parent-uri`, `item`.`rendered-hash`,
`item`.`body`, `item`.`rendered-html`, `item`.`private`, `item`.`edited`,
`item`.`allow_cid`, `item`.`allow_gid`, `item`.`deny_cid`, `item`.`deny_gid`,
`item`.`event-id`, `item`.`object-type`, `item`.`starred`, `item`.`created`,
`item`.`postopts`, `item`.`owner-link`, `item`.`owner-name`, `item`.`owner-avatar`,
`item`.`plink`, `item`.`wall`, `item`.`commented`,
`item`.`id` AS `item_id`, `item`.`network` AS `item_network`";
return $fieldlist;
}
/**
* @brief SQL condition for items
*/
function item_condition() {
$condition = "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`";
return $condition;
}
/**
* "Render" a conversation or list of items for HTML display.
@ -389,6 +469,7 @@ if(!function_exists('conversation')) {
function conversation(&$a, $items, $mode, $update, $preview = false) {
require_once('include/bbcode.php');
require_once('include/Contact.php');
require_once('mod/proxy.php');
$ssl_state = ((local_user()) ? true : false);
@ -494,8 +575,6 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
else
$return_url = $_SESSION['return_url'] = $a->query_string;
load_contact_links(local_user());
$cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
call_hooks('conversation_start',$cb);
@ -610,11 +689,12 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
else
$profile_link = zrl($profile_link);
$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
$profile_avatar = $a->contacts[$normalised]['thumb'];
// Don't rely on the author-avatar. It is better to use the data from the contact table
$author_contact = get_contact_details_by_url($item['author-link'], $profile_owner);
if ($author_contact["thumb"])
$profile_avatar = $author_contact["thumb"];
else
$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar'])) ? $item['author-avatar'] : $item['thumb']));
$profile_avatar = $item['author-avatar'];
$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
call_hooks('render_location',$locate);
@ -668,17 +748,21 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$owner_name_e = $owner_name;
}
if ($item['item_network'] == "")
$item['item_network'] = $item['network'];
$tmp_item = array(
'template' => $tpl,
'id' => (($preview) ? 'P0' : $item['item_id']),
'network' => $item['item_network'],
'network_name' => network_to_name($item['item_network'], $profile_link),
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => $profile_name_e,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => proxy_url($profile_avatar, false, PROXY_SIZE_THUMB),
'thumb' => App::remove_baseurl(proxy_url($profile_avatar, false, PROXY_SIZE_THUMB)),
'title' => $item['title_e'],
'body' => $body_e,
'tags' => $tags_e,
@ -808,15 +892,7 @@ function best_link_url($item,&$sparkle,$ssl_state = false) {
$clean_url = normalise_link($item['author-link']);
if((local_user()) && (local_user() == $item['uid'])) {
if(isset($a->contacts) && x($a->contacts,$clean_url)) {
if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) {
$best_url = 'redir/'.$a->contacts[$clean_url]['id'];
$sparkle = true;
} else
$best_url = $a->contacts[$clean_url]['url'];
}
} elseif (local_user()) {
if (local_user()) {
$r = q("SELECT `id` FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` = '%s' LIMIT 1",
dbesc(NETWORK_DFRN), intval(local_user()), dbesc(normalise_link($clean_url)));
if ($r) {
@ -841,11 +917,9 @@ function item_photo_menu($item){
$ssl_state = false;
if(local_user()) {
if(local_user())
$ssl_state = true;
if(! count($a->contacts))
load_contact_links(local_user());
}
$sub_link="";
$poke_link="";
$contact_url="";
@ -853,6 +927,7 @@ function item_photo_menu($item){
$status_link="";
$photos_link="";
$posts_link="";
$network = "";
if((local_user()) && local_user() == $item['uid'] && $item['parent'] == $item['id'] && (! $item['self'])) {
$sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
@ -863,46 +938,32 @@ function item_photo_menu($item){
if($profile_link === 'mailbox')
$profile_link = '';
$cid = 0;
$network = "";
$rel = 0;
$r = q("SELECT `id`, `network`, `rel` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1",
intval(local_user()), dbesc(normalise_link($item['author-link'])));
if ($r) {
$cid = $r[0]["id"];
$network = $r[0]["network"];
$rel = $r[0]["rel"];
}
if($sparkle) {
$cid = intval(basename($profile_link));
$status_link = $profile_link . "?url=status";
$photos_link = $profile_link . "?url=photos";
$profile_link = $profile_link . "?url=profile";
$pm_url = 'message/new/' . $cid;
$status_link = $profile_link."?url=status";
$photos_link = $profile_link."?url=photos";
$profile_link = $profile_link."?url=profile";
$zurl = '';
}
else {
} else
$profile_link = zrl($profile_link);
if(local_user() && local_user() == $item['uid'] && link_compare($item['url'],$item['author-link'])) {
$cid = $item['contact-id'];
} else {
$r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1",
intval(local_user()), dbesc(normalise_link($item['author-link'])));
if ($r) {
$cid = $r[0]["id"];
if ($r[0]["network"] == NETWORK_DIASPORA)
$pm_url = 'message/new/' . $cid;
} else
$cid = 0;
}
}
if(($cid) && (! $item['self'])) {
$poke_link = 'poke/?f=&c=' . $cid;
$contact_url = 'contacts/' . $cid;
$posts_link = 'contacts/' . $cid . '/posts';
$clean_url = normalise_link($item['author-link']);
if((local_user()) && (local_user() == $item['uid'])) {
if(isset($a->contacts) && x($a->contacts,$clean_url)) {
if($a->contacts[$clean_url]['network'] === NETWORK_DIASPORA) {
$pm_url = 'message/new/' . $cid;
}
}
}
if($cid && !$item['self']) {
$poke_link = 'poke/?f=&c='.$cid;
$contact_url = 'contacts/'.$cid;
$posts_link = 'contacts/'.$cid.'/posts';
if (in_array($network, array(NETWORK_DFRN, NETWORK_DIASPORA)))
$pm_url = 'message/new/'.$cid;
}
if (local_user()) {
@ -916,10 +977,10 @@ function item_photo_menu($item){
t("Send PM") => $pm_url
);
if ($a->contacts[$clean_url]['network'] === NETWORK_DFRN)
if ($network == NETWORK_DFRN)
$menu[t("Poke")] = $poke_link;
if ((($cid == 0) OR ($a->contacts[$clean_url]['rel'] == CONTACT_IS_FOLLOWER)) AND
if ((($cid == 0) OR ($rel == CONTACT_IS_FOLLOWER)) AND
in_array($item['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
$menu[t("Connect/Follow")] = "follow?url=".urlencode($item['author-link']);
} else

View file

@ -35,6 +35,7 @@ function cron_run(&$argv, &$argc){
require_once('include/email.php');
require_once('include/socgraph.php');
require_once('mod/nodeinfo.php');
require_once('include/post_update.php');
load_config('config');
load_config('system');
@ -71,10 +72,6 @@ function cron_run(&$argv, &$argc){
proc_run('php',"include/queue.php");
// run diaspora photo queue process in the background
proc_run('php',"include/dsprphotoq.php");
// run the process to discover global contacts in the background
proc_run('php',"include/discover_poco.php");
@ -105,13 +102,14 @@ function cron_run(&$argv, &$argc){
// Check OStatus conversations
// Check only conversations with mentions (for a longer time)
check_conversations(true);
ostatus::check_conversations(true);
// Check every conversation
check_conversations(false);
ostatus::check_conversations(false);
// Set the gcontact-id in the item table if missing
item_set_gcontact();
// Call possible post update functions
// see include/post_update.php for more details
post_update();
// update nodeinfo data
nodeinfo_cron();
@ -339,35 +337,37 @@ function cron_clear_cache(&$a) {
if ($max_tablesize == 0)
$max_tablesize = 100 * 1000000; // Default are 100 MB
// Minimum fragmentation level in percent
$fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
if ($fragmentation_level == 0)
$fragmentation_level = 0.3; // Default value is 30%
if ($max_tablesize > 0) {
// Minimum fragmentation level in percent
$fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
if ($fragmentation_level == 0)
$fragmentation_level = 0.3; // Default value is 30%
// Optimize some tables that need to be optimized
$r = q("SHOW TABLE STATUS");
foreach($r as $table) {
// Optimize some tables that need to be optimized
$r = q("SHOW TABLE STATUS");
foreach($r as $table) {
// Don't optimize tables that are too large
if ($table["Data_length"] > $max_tablesize)
continue;
// Don't optimize tables that are too large
if ($table["Data_length"] > $max_tablesize)
continue;
// Don't optimize empty tables
if ($table["Data_length"] == 0)
continue;
// Don't optimize empty tables
if ($table["Data_length"] == 0)
continue;
// Calculate fragmentation
$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
// Calculate fragmentation
$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
// Don't optimize tables that needn't to be optimized
if ($fragmentation < $fragmentation_level)
continue;
// Don't optimize tables that needn't to be optimized
if ($fragmentation < $fragmentation_level)
continue;
// So optimize it
logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
// So optimize it
logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
}
}
set_config('system','cache_last_cleared', time());
@ -407,6 +407,15 @@ function cron_repair_database() {
// This call is very "cheap" so we can do it at any time without a problem
q("UPDATE `item` INNER JOIN `item` AS `parent` ON `parent`.`uri` = `item`.`parent-uri` AND `parent`.`uid` = `item`.`uid` SET `item`.`parent` = `parent`.`id` WHERE `item`.`parent` = 0");
// There was an issue where the nick vanishes from the contact table
q("UPDATE `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` SET `nick` = `nickname` WHERE `self` AND `nick`=''");
// Update the global contacts for local users
$r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`");
if ($r)
foreach ($r AS $user)
update_gcontact_for_user($user["uid"]);
/// @todo
/// - remove thread entries without item
/// - remove sign entries without item

View file

@ -162,7 +162,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
* @brief Wrapper for date selector, tailored for use in birthday fields.
*
* @param string $dob Date of Birth
* @return string
* @return string Formatted html
*/
function dob($dob) {
list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d');
@ -175,7 +175,18 @@ function dob($dob) {
else
$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
$o = '<input type="text" name="dob" value="' . $value . '" placeholder="' . t('YYYY-MM-DD or MM-DD') . '" />';
$age = ((intval($value)) ? age($value, $a->user["timezone"], $a->user["timezone"]) : "");
$o = replace_macros(get_markup_template("field_input.tpl"), array(
'$field' => array(
'dob',
t('Birthday:'),
$value,
(((intval($age)) > 0 ) ? t('Age: ') . $age : ""),
'',
'placeholder="' . t('YYYY-MM-DD or MM-DD') . '"'
)
));
// if ($dob && $dob != '0000-00-00')
// $o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),mktime(0,0,0,$month,$day,$year),'dob');

39
include/dbm.php Normal file
View file

@ -0,0 +1,39 @@
<?php
/**
* @brief This class contain functions for the database management
*
*/
class dbm {
/**
* @brief Return a list of database processes
*
* @return array
* 'list' => List of processes, separated in their different states
* 'amount' => Number of concurrent database processes
*/
public static function processlist() {
$r = q("SHOW PROCESSLIST");
$s = array();
$processes = 0;
$states = array();
foreach ($r AS $process) {
$state = trim($process["State"]);
// Filter out all idle processes
if (!in_array($state, array("", "init", "statistics"))) {
++$states[$state];
++$processes;
}
}
$statelist = "";
foreach ($states AS $state => $usage) {
if ($statelist != "")
$statelist .= ", ";
$statelist .= $state.": ".$usage;
}
return(array("list" => $statelist, "amount" => $processes));
}
}
?>

View file

@ -508,6 +508,7 @@ function db_definition() {
"indexes" => array(
"PRIMARY" => array("id"),
"uid" => array("uid"),
"nurl" => array("nurl"),
)
);
$database["conv"] = array(
@ -537,17 +538,6 @@ function db_definition() {
"PRIMARY" => array("id"),
)
);
$database["dsprphotoq"] = array(
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"msg" => array("type" => "mediumtext", "not null" => "1"),
"attempt" => array("type" => "tinyint(4)", "not null" => "1", "default" => "0"),
),
"indexes" => array(
"PRIMARY" => array("id"),
)
);
$database["event"] = array(
"fields" => array(
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
@ -681,6 +671,9 @@ function db_definition() {
"indexes" => array(
"PRIMARY" => array("id"),
"nurl" => array("nurl"),
"name" => array("name"),
"nick" => array("nick"),
"addr" => array("addr"),
"updated" => array("updated"),
)
);
@ -854,7 +847,7 @@ function db_definition() {
"extid" => array("extid"),
"uid_id" => array("uid","id"),
"uid_created" => array("uid","created"),
"uid_unseen" => array("uid","unseen"),
"uid_unseen_contactid" => array("uid","unseen","contact-id"),
"uid_network_received" => array("uid","network","received"),
"uid_received" => array("uid","received"),
"uid_network_commented" => array("uid","network","commented"),
@ -1246,7 +1239,6 @@ function db_definition() {
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"iid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
"retract_iid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
"signed_text" => array("type" => "mediumtext", "not null" => "1"),
"signature" => array("type" => "text", "not null" => "1"),
"signer" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1254,7 +1246,6 @@ function db_definition() {
"indexes" => array(
"PRIMARY" => array("id"),
"iid" => array("iid"),
"retract_iid" => array("retract_iid"),
)
);
$database["spam"] = array(

View file

@ -10,11 +10,11 @@ require_once("include/dfrn.php");
function delivery_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)){
if (is_null($a)){
$a = new App;
}
if(is_null($db)) {
if (is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
@ -32,12 +32,12 @@ function delivery_run(&$argv, &$argc){
load_hooks();
if($argc < 3)
if ($argc < 3)
return;
$a->set_baseurl(get_config('system','url'));
logger('delivery: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
logger('delivery: invoked: '. print_r($argv,true), LOGGER_DEBUG);
$cmd = $argv[1];
$item_id = intval($argv[2]);
@ -53,7 +53,7 @@ function delivery_run(&$argv, &$argc){
dbesc($item_id),
dbesc($contact_id)
);
if(! count($r)) {
if (!count($r)) {
continue;
}
@ -68,7 +68,7 @@ function delivery_run(&$argv, &$argc){
dbesc($contact_id)
);
if((! $item_id) || (! $contact_id))
if (!$item_id || !$contact_id)
continue;
$expire = false;
@ -84,20 +84,20 @@ function delivery_run(&$argv, &$argc){
$recipients[] = $contact_id;
if($cmd === 'mail') {
if ($cmd === 'mail') {
$normal_mode = false;
$mail = true;
$message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
if(! count($message)){
if (!count($message)){
return;
}
$uid = $message[0]['uid'];
$recipients[] = $message[0]['contact-id'];
$item = $message[0];
}
elseif($cmd === 'expire') {
elseif ($cmd === 'expire') {
$normal_mode = false;
$expire = true;
$items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
@ -106,22 +106,22 @@ function delivery_run(&$argv, &$argc){
);
$uid = $item_id;
$item_id = 0;
if(! count($items))
if (!count($items))
continue;
}
elseif($cmd === 'suggest') {
elseif ($cmd === 'suggest') {
$normal_mode = false;
$fsuggest = true;
$suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
intval($item_id)
);
if(! count($suggest))
if (!count($suggest))
return;
$uid = $suggest[0]['uid'];
$recipients[] = $suggest[0]['cid'];
$item = $suggest[0];
} elseif($cmd === 'relocate') {
} elseif ($cmd === 'relocate') {
$normal_mode = false;
$relocate = true;
$uid = $item_id;
@ -131,7 +131,7 @@ function delivery_run(&$argv, &$argc){
intval($item_id)
);
if((! count($r)) || (! intval($r[0]['parent']))) {
if ((!count($r)) || (!intval($r[0]['parent']))) {
continue;
}
@ -145,32 +145,32 @@ function delivery_run(&$argv, &$argc){
intval($parent_id)
);
if(! count($items)) {
if (!count($items)) {
continue;
}
$icontacts = null;
$contacts_arr = array();
foreach($items as $item)
if(! in_array($item['contact-id'],$contacts_arr))
if (!in_array($item['contact-id'],$contacts_arr))
$contacts_arr[] = intval($item['contact-id']);
if(count($contacts_arr)) {
if (count($contacts_arr)) {
$str_contacts = implode(',',$contacts_arr);
$icontacts = q("SELECT * FROM `contact`
WHERE `id` IN ( $str_contacts ) "
);
}
if( ! ($icontacts && count($icontacts)))
if ( !($icontacts && count($icontacts)))
continue;
// avoid race condition with deleting entries
if($items[0]['deleted']) {
if ($items[0]['deleted']) {
foreach($items as $item)
$item['deleted'] = 1;
}
if((count($items) == 1) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
if ((count($items) == 1) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
logger('delivery: top level post');
$top_level = true;
}
@ -184,7 +184,7 @@ function delivery_run(&$argv, &$argc){
intval($uid)
);
if(! count($r))
if (!count($r))
continue;
$owner = $r[0];
@ -193,7 +193,7 @@ function delivery_run(&$argv, &$argc){
$public_message = true;
if(! ($mail || $fsuggest || $relocate)) {
if (!($mail || $fsuggest || $relocate)) {
require_once('include/group.php');
$parent = $items[0];
@ -217,7 +217,7 @@ function delivery_run(&$argv, &$argc){
$localhost = $a->get_hostname();
if(strpos($localhost,':'))
if (strpos($localhost,':'))
$localhost = substr($localhost,0,strpos($localhost,':'));
/**
@ -230,20 +230,21 @@ function delivery_run(&$argv, &$argc){
$relay_to_owner = false;
if((! $top_level) && ($parent['wall'] == 0) && (! $expire) && (stristr($target_item['uri'],$localhost))) {
if (!$top_level && ($parent['wall'] == 0) && !$expire && stristr($target_item['uri'],$localhost)) {
$relay_to_owner = true;
}
if($relay_to_owner) {
if ($relay_to_owner) {
logger('followup '.$target_item["guid"], LOGGER_DEBUG);
// local followup to remote post
$followup = true;
}
if((strlen($parent['allow_cid']))
if ((strlen($parent['allow_cid']))
|| (strlen($parent['allow_gid']))
|| (strlen($parent['deny_cid']))
|| (strlen($parent['deny_gid']))) {
|| (strlen($parent['deny_gid']))
|| $parent["private"]) {
$public_message = false; // private recipients, not public
}
@ -253,10 +254,10 @@ function delivery_run(&$argv, &$argc){
intval($contact_id)
);
if(count($r))
if (count($r))
$contact = $r[0];
if($contact['self'])
if ($contact['self'])
continue;
$deliver_status = 0;
@ -266,7 +267,7 @@ function delivery_run(&$argv, &$argc){
switch($contact['network']) {
case NETWORK_DFRN:
logger('notifier: '.$target_item["guid"].' dfrndelivery: ' . $contact['name']);
logger('notifier: '.$target_item["guid"].' dfrndelivery: '.$contact['name']);
if ($mail) {
$item['body'] = fix_private_photos($item['body'],$owner['uid'],null,$message[0]['contact-id']);
@ -276,13 +277,13 @@ function delivery_run(&$argv, &$argc){
q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
} elseif ($relocate)
$atom = dfrn::relocate($owner, $uid);
elseif($followup) {
elseif ($followup) {
$msgitems = array();
foreach($items as $item) { // there is only one item
if(!$item['parent'])
if (!$item['parent'])
continue;
if($item['id'] == $item_id) {
logger('followup: item: ' . print_r($item,true), LOGGER_DATA);
if ($item['id'] == $item_id) {
logger('followup: item: '. print_r($item,true), LOGGER_DATA);
$msgitems[] = $item;
}
}
@ -290,19 +291,19 @@ function delivery_run(&$argv, &$argc){
} else {
$msgitems = array();
foreach($items as $item) {
if(!$item['parent'])
if (!$item['parent'])
continue;
// private emails may be in included in public conversations. Filter them.
if(($public_message) && $item['private'])
if ($public_message && $item['private'])
continue;
$item_contact = get_item_contact($item,$icontacts);
if(!$item_contact)
if (!$item_contact)
continue;
if($normal_mode) {
if($item_id == $item['id'] || $item['id'] == $item['parent']) {
if ($normal_mode) {
if ($item_id == $item['id'] || $item['id'] == $item['parent']) {
$item["entry:comment-allow"] = true;
$item["entry:cid"] = (($top_level) ? $contact['id'] : 0);
$msgitems[] = $item;
@ -317,15 +318,15 @@ function delivery_run(&$argv, &$argc){
logger('notifier entry: '.$contact["url"].' '.$target_item["guid"].' entry: '.$atom, LOGGER_DEBUG);
logger('notifier: ' . $atom, LOGGER_DATA);
logger('notifier: '.$atom, LOGGER_DATA);
$basepath = implode('/', array_slice(explode('/',$contact['url']),0,3));
// perform local delivery if we are on the same site
if(link_compare($basepath,$a->get_baseurl())) {
if (link_compare($basepath,$a->get_baseurl())) {
$nickname = basename($contact['url']);
if($contact['issued-id'])
if ($contact['issued-id'])
$sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id']));
else
$sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id']));
@ -347,10 +348,10 @@ function delivery_run(&$argv, &$argc){
dbesc($nickname)
);
if($x && count($x)) {
if ($x && count($x)) {
$write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false);
if((($owner['page-flags'] == PAGE_COMMUNITY) || ($write_flag)) && (! $x[0]['writable'])) {
q("update contact set writable = 1 where id = %d",
if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) {
q("UPDATE `contact` SET `writable` = 1 WHERE `id` = %d",
intval($x[0]['id'])
);
$x[0]['writable'] = 1;
@ -370,14 +371,14 @@ function delivery_run(&$argv, &$argc){
}
}
if(! was_recently_delayed($contact['id']))
if (!was_recently_delayed($contact['id']))
$deliver_status = dfrn::deliver($owner,$contact,$atom);
else
$deliver_status = (-1);
logger('notifier: dfrn_delivery to '.$contact["url"].' with guid '.$target_item["guid"].' returns '.$deliver_status);
if($deliver_status == (-1)) {
if ($deliver_status == (-1)) {
logger('notifier: delivery failed: queuing message');
add_to_queue($contact['id'],NETWORK_DFRN,$atom);
}
@ -385,9 +386,9 @@ function delivery_run(&$argv, &$argc){
case NETWORK_OSTATUS:
// Do not send to otatus if we are not configured to send to public networks
if($owner['prvnets'])
if ($owner['prvnets'])
break;
if(get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
if (get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
break;
// There is currently no code here to distribute anything to OStatus.
@ -397,67 +398,67 @@ function delivery_run(&$argv, &$argc){
case NETWORK_MAIL:
case NETWORK_MAIL2:
if(get_config('system','dfrn_only'))
if (get_config('system','dfrn_only'))
break;
// WARNING: does not currently convert to RFC2047 header encodings, etc.
$addr = $contact['addr'];
if(! strlen($addr))
if (!strlen($addr))
break;
if($cmd === 'wall-new' || $cmd === 'comment-new') {
if ($cmd === 'wall-new' || $cmd === 'comment-new') {
$it = null;
if($cmd === 'wall-new')
if ($cmd === 'wall-new')
$it = $items[0];
else {
$r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($argv[2]),
intval($uid)
);
if(count($r))
if (count($r))
$it = $r[0];
}
if(! $it)
if (!$it)
break;
$local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if(! count($local_user))
if (!count($local_user))
break;
$reply_to = '';
$r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if($r1 && $r1[0]['reply_to'])
if ($r1 && $r1[0]['reply_to'])
$reply_to = $r1[0]['reply_to'];
$subject = (($it['title']) ? email_header_encode($it['title'],'UTF-8') : t("\x28no subject\x29")) ;
// only expose our real email address to true friends
if(($contact['rel'] == CONTACT_IS_FRIEND) && (! $contact['blocked'])) {
if($reply_to) {
if (($contact['rel'] == CONTACT_IS_FRIEND) && !$contact['blocked']) {
if ($reply_to) {
$headers = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$reply_to.'>'."\n";
$headers .= 'Sender: '.$local_user[0]['email']."\n";
} else
$headers = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n";
} else
$headers = 'From: ' . email_header_encode($local_user[0]['username'],'UTF-8') . ' <' . t('noreply') . '@' . $a->get_hostname() . '>' . "\n";
$headers = 'From: '. email_header_encode($local_user[0]['username'],'UTF-8') .' <'. t('noreply') .'@'.$a->get_hostname() .'>'. "\n";
//if($reply_to)
// $headers .= 'Reply-to: ' . $reply_to . "\n";
//if ($reply_to)
// $headers .= 'Reply-to: '.$reply_to . "\n";
$headers .= 'Message-Id: <' . iri2msgid($it['uri']). '>' . "\n";
$headers .= 'Message-Id: <'. iri2msgid($it['uri']).'>'. "\n";
//logger("Mail: uri: ".$it['uri']." parent-uri ".$it['parent-uri'], LOGGER_DEBUG);
//logger("Mail: Data: ".print_r($it, true), LOGGER_DEBUG);
//logger("Mail: Data: ".print_r($it, true), LOGGER_DATA);
if($it['uri'] !== $it['parent-uri']) {
if ($it['uri'] !== $it['parent-uri']) {
$headers .= "References: <".iri2msgid($it["parent-uri"]).">";
// If Threading is enabled, write down the correct parent
@ -465,23 +466,23 @@ function delivery_run(&$argv, &$argc){
$headers .= " <".iri2msgid($it["thr-parent"]).">";
$headers .= "\n";
if(!$it['title']) {
if (!$it['title']) {
$r = q("SELECT `title` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($it['parent-uri']),
intval($uid));
if(count($r) AND ($r[0]['title'] != ''))
if (count($r) AND ($r[0]['title'] != ''))
$subject = $r[0]['title'];
else {
$r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($it['parent-uri']),
intval($uid));
if(count($r) AND ($r[0]['title'] != ''))
if (count($r) AND ($r[0]['title'] != ''))
$subject = $r[0]['title'];
}
}
if(strncasecmp($subject,'RE:',3))
if (strncasecmp($subject,'RE:',3))
$subject = 'Re: '.$subject;
}
email_send($addr, $subject, $headers, $it);
@ -489,60 +490,59 @@ function delivery_run(&$argv, &$argc){
break;
case NETWORK_DIASPORA:
if($public_message)
$loc = 'public batch ' . $contact['batch'];
if ($public_message)
$loc = 'public batch '.$contact['batch'];
else
$loc = $contact['name'];
logger('delivery: diaspora batch deliver: ' . $loc);
logger('delivery: diaspora batch deliver: '.$loc);
if(get_config('system','dfrn_only') || (!get_config('system','diaspora_enabled')))
if (get_config('system','dfrn_only') || (!get_config('system','diaspora_enabled')))
break;
if($mail) {
diaspora_send_mail($item,$owner,$contact);
if ($mail) {
diaspora::send_mail($item,$owner,$contact);
break;
}
if(!$normal_mode)
if (!$normal_mode)
break;
if((! $contact['pubkey']) && (! $public_message))
if (!$contact['pubkey'] && !$public_message)
break;
$unsupported_activities = array(ACTIVITY_DISLIKE, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE);
//don't transmit activities which are not supported by diaspora
foreach($unsupported_activities as $act) {
if(activity_match($target_item['verb'],$act)) {
if (activity_match($target_item['verb'],$act)) {
break 2;
}
}
if(($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
// top-level retraction
logger('delivery: diaspora retract: ' . $loc);
diaspora_send_retraction($target_item,$owner,$contact,$public_message);
logger('diaspora retract: '.$loc);
diaspora::send_retraction($target_item,$owner,$contact,$public_message);
break;
} elseif($followup) {
} elseif ($followup) {
// send comments and likes to owner to relay
diaspora_send_followup($target_item,$owner,$contact,$public_message);
logger('diaspora followup: '.$loc);
diaspora::send_followup($target_item,$owner,$contact,$public_message);
break;
} elseif($target_item['uri'] !== $target_item['parent-uri']) {
} elseif ($target_item['uri'] !== $target_item['parent-uri']) {
// we are the relay - send comments, likes and relayable_retractions to our conversants
logger('delivery: diaspora relay: ' . $loc);
diaspora_send_relay($target_item,$owner,$contact,$public_message);
logger('diaspora relay: '.$loc);
diaspora::send_relay($target_item,$owner,$contact,$public_message);
break;
} elseif(($top_level) && (! $walltowall)) {
} elseif ($top_level && !$walltowall) {
// currently no workable solution for sending walltowall
logger('delivery: diaspora status: ' . $loc);
diaspora_send_status($target_item,$owner,$contact,$public_message);
logger('diaspora status: '.$loc);
diaspora::send_status($target_item,$owner,$contact,$public_message);
break;
}
logger('delivery: diaspora unknown mode: ' . $contact['name']);
logger('delivery: diaspora unknown mode: '.$contact['name']);
break;

View file

@ -19,6 +19,7 @@ require_once("include/text.php");
require_once("include/oembed.php");
require_once("include/html2bbcode.php");
require_once("include/bbcode.php");
require_once("include/xml.php");
/**
* @brief This class contain functions to create and send DFRN XML files
@ -67,10 +68,11 @@ class dfrn {
* @param string $owner_nick Owner nick name
* @param string $last_update Date of the last update
* @param int $direction Can be -1, 0 or 1.
* @param boolean $onlyheader Output only the header without content? (Default is "no")
*
* @return string DFRN feed entries
*/
public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0) {
public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0, $onlyheader = false) {
$a = get_app();
@ -85,7 +87,7 @@ class dfrn {
$converse = true;
if($a->argv[$x] == 'starred')
$starred = true;
if($a->argv[$x] === 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1]))
if($a->argv[$x] == 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1]))
$category = $a->argv[$x+1];
}
}
@ -195,7 +197,6 @@ class dfrn {
`contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`,
`contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`,
`contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `contact-id`, `contact`.`uid` AS `contact-uid`,
`sign`.`signed_text`, `sign`.`signature`, `sign`.`signer`
FROM `item` $sql_post_table
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
@ -233,7 +234,7 @@ class dfrn {
// This hook can't work anymore
// call_hooks('atom_feed', $atom);
if(! count($items)) {
if (!count($items) OR $onlyheader) {
$atom = trim($doc->saveXML());
call_hooks('atom_feed_end', $atom);
@ -244,7 +245,7 @@ class dfrn {
foreach($items as $item) {
// prevent private email from leaking.
if($item['network'] === NETWORK_MAIL)
if($item['network'] == NETWORK_MAIL)
continue;
// public feeds get html, our own nodes use bbcode
@ -286,17 +287,17 @@ class dfrn {
$mail = $doc->createElement("dfrn:mail");
$sender = $doc->createElement("dfrn:sender");
xml_add_element($doc, $sender, "dfrn:name", $owner['name']);
xml_add_element($doc, $sender, "dfrn:uri", $owner['url']);
xml_add_element($doc, $sender, "dfrn:avatar", $owner['thumb']);
xml::add_element($doc, $sender, "dfrn:name", $owner['name']);
xml::add_element($doc, $sender, "dfrn:uri", $owner['url']);
xml::add_element($doc, $sender, "dfrn:avatar", $owner['thumb']);
$mail->appendChild($sender);
xml_add_element($doc, $mail, "dfrn:id", $item['uri']);
xml_add_element($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']);
xml_add_element($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME));
xml_add_element($doc, $mail, "dfrn:subject", $item['title']);
xml_add_element($doc, $mail, "dfrn:content", $item['body']);
xml::add_element($doc, $mail, "dfrn:id", $item['uri']);
xml::add_element($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']);
xml::add_element($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME));
xml::add_element($doc, $mail, "dfrn:subject", $item['title']);
xml::add_element($doc, $mail, "dfrn:content", $item['body']);
$root->appendChild($mail);
@ -319,11 +320,11 @@ class dfrn {
$suggest = $doc->createElement("dfrn:suggest");
xml_add_element($doc, $suggest, "dfrn:url", $item['url']);
xml_add_element($doc, $suggest, "dfrn:name", $item['name']);
xml_add_element($doc, $suggest, "dfrn:photo", $item['photo']);
xml_add_element($doc, $suggest, "dfrn:request", $item['request']);
xml_add_element($doc, $suggest, "dfrn:note", $item['note']);
xml::add_element($doc, $suggest, "dfrn:url", $item['url']);
xml::add_element($doc, $suggest, "dfrn:name", $item['name']);
xml::add_element($doc, $suggest, "dfrn:photo", $item['photo']);
xml::add_element($doc, $suggest, "dfrn:request", $item['request']);
xml::add_element($doc, $suggest, "dfrn:note", $item['note']);
$root->appendChild($suggest);
@ -365,16 +366,17 @@ class dfrn {
$relocate = $doc->createElement("dfrn:relocate");
xml_add_element($doc, $relocate, "dfrn:url", $owner['url']);
xml_add_element($doc, $relocate, "dfrn:name", $owner['name']);
xml_add_element($doc, $relocate, "dfrn:photo", $photos[4]);
xml_add_element($doc, $relocate, "dfrn:thumb", $photos[5]);
xml_add_element($doc, $relocate, "dfrn:micro", $photos[6]);
xml_add_element($doc, $relocate, "dfrn:request", $owner['request']);
xml_add_element($doc, $relocate, "dfrn:confirm", $owner['confirm']);
xml_add_element($doc, $relocate, "dfrn:notify", $owner['notify']);
xml_add_element($doc, $relocate, "dfrn:poll", $owner['poll']);
xml_add_element($doc, $relocate, "dfrn:sitepubkey", get_config('system','site_pubkey'));
xml::add_element($doc, $relocate, "dfrn:url", $owner['url']);
xml::add_element($doc, $relocate, "dfrn:name", $owner['name']);
xml::add_element($doc, $relocate, "dfrn:addr", $owner['addr']);
xml::add_element($doc, $relocate, "dfrn:photo", $photos[4]);
xml::add_element($doc, $relocate, "dfrn:thumb", $photos[5]);
xml::add_element($doc, $relocate, "dfrn:micro", $photos[6]);
xml::add_element($doc, $relocate, "dfrn:request", $owner['request']);
xml::add_element($doc, $relocate, "dfrn:confirm", $owner['confirm']);
xml::add_element($doc, $relocate, "dfrn:notify", $owner['notify']);
xml::add_element($doc, $relocate, "dfrn:poll", $owner['poll']);
xml::add_element($doc, $relocate, "dfrn:sitepubkey", get_config('system','site_pubkey'));
$root->appendChild($relocate);
@ -410,39 +412,39 @@ class dfrn {
$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
xml_add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
xml_add_element($doc, $root, "title", $owner["name"]);
xml::add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
xml::add_element($doc, $root, "title", $owner["name"]);
$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
xml_add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
xml::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
$attributes = array("rel" => "license", "href" => "http://creativecommons.org/licenses/by/3.0/");
xml_add_element($doc, $root, "link", "", $attributes);
xml::add_element($doc, $root, "link", "", $attributes);
$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $alternatelink);
xml_add_element($doc, $root, "link", "", $attributes);
xml::add_element($doc, $root, "link", "", $attributes);
if ($public) {
// DFRN itself doesn't uses this. But maybe someone else wants to subscribe to the public feed.
ostatus_hublinks($doc, $root);
ostatus::hublinks($doc, $root);
$attributes = array("rel" => "salmon", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
xml_add_element($doc, $root, "link", "", $attributes);
xml::add_element($doc, $root, "link", "", $attributes);
$attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-replies", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
xml_add_element($doc, $root, "link", "", $attributes);
xml::add_element($doc, $root, "link", "", $attributes);
$attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-mention", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
xml_add_element($doc, $root, "link", "", $attributes);
xml::add_element($doc, $root, "link", "", $attributes);
}
if ($owner['page-flags'] == PAGE_COMMUNITY)
xml_add_element($doc, $root, "dfrn:community", 1);
xml::add_element($doc, $root, "dfrn:community", 1);
/// @todo We need a way to transmit the different page flags like "PAGE_PRVGROUP"
xml_add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
xml::add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
$author = self::add_author($doc, $owner, $authorelement, $public);
$root->appendChild($author);
@ -461,37 +463,52 @@ class dfrn {
*/
private function add_author($doc, $owner, $authorelement, $public) {
// Is the profile hidden or shouldn't be published in the net? Then add the "hide" element
$r = q("SELECT `id` FROM `profile` INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE (`hidewall` OR NOT `net-publish`) AND `user`.`uid` = %d",
intval($owner['uid']));
if ($r)
$hidewall = true;
else
$hidewall = false;
$author = $doc->createElement($authorelement);
$namdate = datetime_convert('UTC', 'UTC', $owner['name-date'].'+00:00' , ATOM_TIME);
$namdate = datetime_convert('UTC', 'UTC', $owner['name-date'].'+00:00', ATOM_TIME);
$uridate = datetime_convert('UTC', 'UTC', $owner['uri-date'].'+00:00', ATOM_TIME);
$picdate = datetime_convert('UTC', 'UTC', $owner['avatar-date'].'+00:00', ATOM_TIME);
$attributes = array("dfrn:updated" => $namdate);
xml_add_element($doc, $author, "name", $owner["name"], $attributes);
if (!$public OR !$hidewall)
$attributes = array("dfrn:updated" => $namdate);
else
$attributes = array();
$attributes = array("dfrn:updated" => $namdate);
xml_add_element($doc, $author, "uri", app::get_baseurl().'/profile/'.$owner["nickname"], $attributes);
xml::add_element($doc, $author, "name", $owner["name"], $attributes);
xml::add_element($doc, $author, "uri", app::get_baseurl().'/profile/'.$owner["nickname"], $attributes);
xml::add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes);
$attributes = array("dfrn:updated" => $namdate);
xml_add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes);
$attributes = array("rel" => "photo", "type" => "image/jpeg", "dfrn:updated" => $picdate,
$attributes = array("rel" => "photo", "type" => "image/jpeg",
"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
xml_add_element($doc, $author, "link", "", $attributes);
$attributes = array("rel" => "avatar", "type" => "image/jpeg", "dfrn:updated" => $picdate,
"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
xml_add_element($doc, $author, "link", "", $attributes);
if (!$public OR !$hidewall)
$attributes["dfrn:updated"] = $picdate;
xml::add_element($doc, $author, "link", "", $attributes);
$attributes["rel"] = "avatar";
xml::add_element($doc, $author, "link", "", $attributes);
if ($hidewall)
xml::add_element($doc, $author, "dfrn:hide", "true");
// The following fields will only be generated if the data isn't meant for a public feed
if ($public)
return $author;
$birthday = feed_birthday($owner['uid'], $owner['timezone']);
if ($birthday)
xml_add_element($doc, $author, "dfrn:birthday", $birthday);
// The following fields will only be generated if this isn't for a public feed
if ($public)
return $author;
xml::add_element($doc, $author, "dfrn:birthday", $birthday);
// Only show contact details when we are allowed to
$r = q("SELECT `profile`.`about`, `profile`.`name`, `profile`.`homepage`, `user`.`nickname`, `user`.`timezone`,
@ -502,25 +519,25 @@ class dfrn {
intval($owner['uid']));
if ($r) {
$profile = $r[0];
xml_add_element($doc, $author, "poco:displayName", $profile["name"]);
xml_add_element($doc, $author, "poco:updated", $namdate);
xml::add_element($doc, $author, "poco:displayName", $profile["name"]);
xml::add_element($doc, $author, "poco:updated", $namdate);
if (trim($profile["dob"]) != "0000-00-00")
xml_add_element($doc, $author, "poco:birthday", "0000-".date("m-d", strtotime($profile["dob"])));
xml::add_element($doc, $author, "poco:birthday", "0000-".date("m-d", strtotime($profile["dob"])));
xml_add_element($doc, $author, "poco:note", $profile["about"]);
xml_add_element($doc, $author, "poco:preferredUsername", $profile["nickname"]);
xml::add_element($doc, $author, "poco:note", $profile["about"]);
xml::add_element($doc, $author, "poco:preferredUsername", $profile["nickname"]);
$savetz = date_default_timezone_get();
date_default_timezone_set($profile["timezone"]);
xml_add_element($doc, $author, "poco:utcOffset", date("P"));
xml::add_element($doc, $author, "poco:utcOffset", date("P"));
date_default_timezone_set($savetz);
if (trim($profile["homepage"]) != "") {
$urls = $doc->createElement("poco:urls");
xml_add_element($doc, $urls, "poco:type", "homepage");
xml_add_element($doc, $urls, "poco:value", $profile["homepage"]);
xml_add_element($doc, $urls, "poco:primary", "true");
xml::add_element($doc, $urls, "poco:type", "homepage");
xml::add_element($doc, $urls, "poco:value", $profile["homepage"]);
xml::add_element($doc, $urls, "poco:primary", "true");
$author->appendChild($urls);
}
@ -528,7 +545,7 @@ class dfrn {
$keywords = explode(",", $profile["pub_keywords"]);
foreach ($keywords AS $keyword)
xml_add_element($doc, $author, "poco:tags", trim($keyword));
xml::add_element($doc, $author, "poco:tags", trim($keyword));
}
@ -536,25 +553,25 @@ class dfrn {
$xmpp = "";
if (trim($xmpp) != "") {
$ims = $doc->createElement("poco:ims");
xml_add_element($doc, $ims, "poco:type", "xmpp");
xml_add_element($doc, $ims, "poco:value", $xmpp);
xml_add_element($doc, $ims, "poco:primary", "true");
xml::add_element($doc, $ims, "poco:type", "xmpp");
xml::add_element($doc, $ims, "poco:value", $xmpp);
xml::add_element($doc, $ims, "poco:primary", "true");
$author->appendChild($ims);
}
if (trim($profile["locality"].$profile["region"].$profile["country-name"]) != "") {
$element = $doc->createElement("poco:address");
xml_add_element($doc, $element, "poco:formatted", formatted_location($profile));
xml::add_element($doc, $element, "poco:formatted", formatted_location($profile));
if (trim($profile["locality"]) != "")
xml_add_element($doc, $element, "poco:locality", $profile["locality"]);
xml::add_element($doc, $element, "poco:locality", $profile["locality"]);
if (trim($profile["region"]) != "")
xml_add_element($doc, $element, "poco:region", $profile["region"]);
xml::add_element($doc, $element, "poco:region", $profile["region"]);
if (trim($profile["country-name"]) != "")
xml_add_element($doc, $element, "poco:country", $profile["country-name"]);
xml::add_element($doc, $element, "poco:country", $profile["country-name"]);
$author->appendChild($element);
}
@ -578,9 +595,9 @@ class dfrn {
$contact = get_contact_details_by_url($contact_url, $item["uid"]);
$author = $doc->createElement($element);
xml_add_element($doc, $author, "name", $contact["name"]);
xml_add_element($doc, $author, "uri", $contact["url"]);
xml_add_element($doc, $author, "dfrn:handle", $contact["addr"]);
xml::add_element($doc, $author, "name", $contact["name"]);
xml::add_element($doc, $author, "uri", $contact["url"]);
xml::add_element($doc, $author, "dfrn:handle", $contact["addr"]);
/// @Todo
/// - Check real image type and image size
@ -591,7 +608,7 @@ class dfrn {
"media:width" => 80,
"media:height" => 80,
"href" => $contact["photo"]);
xml_add_element($doc, $author, "link", "", $attributes);
xml::add_element($doc, $author, "link", "", $attributes);
$attributes = array(
"rel" => "avatar",
@ -599,7 +616,7 @@ class dfrn {
"media:width" => 80,
"media:height" => 80,
"href" => $contact["photo"]);
xml_add_element($doc, $author, "link", "", $attributes);
xml::add_element($doc, $author, "link", "", $attributes);
return $author;
}
@ -622,13 +639,13 @@ class dfrn {
if(!$r)
return false;
if($r->type)
xml_add_element($doc, $entry, "activity:object-type", $r->type);
xml::add_element($doc, $entry, "activity:object-type", $r->type);
if($r->id)
xml_add_element($doc, $entry, "id", $r->id);
xml::add_element($doc, $entry, "id", $r->id);
if($r->title)
xml_add_element($doc, $entry, "title", $r->title);
xml::add_element($doc, $entry, "title", $r->title);
if($r->link) {
if(substr($r->link,0,1) === '<') {
if(substr($r->link,0,1) == '<') {
if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
$r->link = str_replace('&','&amp;', $r->link);
@ -641,16 +658,16 @@ class dfrn {
$attributes = array();
foreach ($link->attributes() AS $parameter => $value)
$attributes[$parameter] = $value;
xml_add_element($doc, $entry, "link", "", $attributes);
xml::add_element($doc, $entry, "link", "", $attributes);
}
}
} else {
$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $r->link);
xml_add_element($doc, $entry, "link", "", $attributes);
xml::add_element($doc, $entry, "link", "", $attributes);
}
}
if($r->content)
xml_add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html"));
xml::add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html"));
return $entry;
}
@ -684,7 +701,7 @@ class dfrn {
if(trim($matches[4]) != "")
$attributes["title"] = trim($matches[4]);
xml_add_element($doc, $root, "link", "", $attributes);
xml::add_element($doc, $root, "link", "", $attributes);
}
}
}
@ -711,7 +728,7 @@ class dfrn {
if($item['deleted']) {
$attributes = array("ref" => $item['uri'], "when" => datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME));
return xml_create_element($doc, "at:deleted-entry", "", $attributes);
return xml::create_element($doc, "at:deleted-entry", "", $attributes);
}
$entry = $doc->createElement("entry");
@ -745,66 +762,66 @@ class dfrn {
$attributes = array("ref" => $parent_item, "type" => "text/html",
"href" => app::get_baseurl().'/display/'.$parent[0]['guid'],
"dfrn:diaspora_guid" => $parent[0]['guid']);
xml_add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
xml::add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
}
xml_add_element($doc, $entry, "id", $item["uri"]);
xml_add_element($doc, $entry, "title", $item["title"]);
xml::add_element($doc, $entry, "id", $item["uri"]);
xml::add_element($doc, $entry, "title", $item["title"]);
xml_add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
xml_add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
xml::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
xml::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
// "dfrn:env" is used to read the content
xml_add_element($doc, $entry, "dfrn:env", base64url_encode($body, true));
xml::add_element($doc, $entry, "dfrn:env", base64url_encode($body, true));
// The "content" field is not read by the receiver. We could remove it when the type is "text"
// We keep it at the moment, maybe there is some old version that doesn't read "dfrn:env"
xml_add_element($doc, $entry, "content", (($type === 'html') ? $htmlbody : $body), array("type" => $type));
xml::add_element($doc, $entry, "content", (($type == 'html') ? $htmlbody : $body), array("type" => $type));
// We save this value in "plink". Maybe we should read it from there as well?
xml_add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
xml::add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
"href" => app::get_baseurl()."/display/".$item["guid"]));
// "comment-allow" is some old fashioned stuff for old Friendica versions.
// It is included in the rewritten code for completeness
if ($comment)
xml_add_element($doc, $entry, "dfrn:comment-allow", intval($item['last-child']));
xml::add_element($doc, $entry, "dfrn:comment-allow", intval($item['last-child']));
if($item['location'])
xml_add_element($doc, $entry, "dfrn:location", $item['location']);
xml::add_element($doc, $entry, "dfrn:location", $item['location']);
if($item['coord'])
xml_add_element($doc, $entry, "georss:point", $item['coord']);
xml::add_element($doc, $entry, "georss:point", $item['coord']);
if(($item['private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
xml_add_element($doc, $entry, "dfrn:private", (($item['private']) ? $item['private'] : 1));
xml::add_element($doc, $entry, "dfrn:private", (($item['private']) ? $item['private'] : 1));
if($item['extid'])
xml_add_element($doc, $entry, "dfrn:extid", $item['extid']);
xml::add_element($doc, $entry, "dfrn:extid", $item['extid']);
if($item['bookmark'])
xml_add_element($doc, $entry, "dfrn:bookmark", "true");
xml::add_element($doc, $entry, "dfrn:bookmark", "true");
if($item['app'])
xml_add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item['id'], "source" => $item['app']));
xml::add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item['id'], "source" => $item['app']));
xml_add_element($doc, $entry, "dfrn:diaspora_guid", $item["guid"]);
xml::add_element($doc, $entry, "dfrn:diaspora_guid", $item["guid"]);
// The signed text contains the content in Markdown, the sender handle and the signatur for the content
// It is needed for relayed comments to Diaspora.
if($item['signed_text']) {
$sign = base64_encode(json_encode(array('signed_text' => $item['signed_text'],'signature' => $item['signature'],'signer' => $item['signer'])));
xml_add_element($doc, $entry, "dfrn:diaspora_signature", $sign);
xml::add_element($doc, $entry, "dfrn:diaspora_signature", $sign);
}
xml_add_element($doc, $entry, "activity:verb", construct_verb($item));
xml::add_element($doc, $entry, "activity:verb", construct_verb($item));
if ($item['object-type'] != "")
xml_add_element($doc, $entry, "activity:object-type", $item['object-type']);
xml::add_element($doc, $entry, "activity:object-type", $item['object-type']);
elseif ($item['id'] == $item['parent'])
xml_add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
else
xml_add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT);
xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT);
$actobj = self::create_activity($doc, "activity:object", $item['object']);
if ($actobj)
@ -819,7 +836,7 @@ class dfrn {
if(count($tags)) {
foreach($tags as $t)
if (($type != 'html') OR ($t[0] != "@"))
xml_add_element($doc, $entry, "category", "", array("scheme" => "X-DFRN:".$t[0].":".$t[1], "term" => $t[2]));
xml::add_element($doc, $entry, "category", "", array("scheme" => "X-DFRN:".$t[0].":".$t[1], "term" => $t[2]));
}
if(count($tags))
@ -832,11 +849,11 @@ class dfrn {
intval($owner["uid"]),
dbesc(normalise_link($mention)));
if ($r[0]["forum"] OR $r[0]["prv"])
xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
"href" => $mention));
else
xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
"href" => $mention));
}
@ -1125,7 +1142,7 @@ class dfrn {
$author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue;
$r = q("SELECT `id`, `uid`, `url`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`, `hidden`
FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
if ($r) {
@ -1209,6 +1226,16 @@ class dfrn {
/// - poco:region
/// - poco:country
// If the "hide" element is present then the profile isn't searchable.
$hide = intval($xpath->evaluate($element."/dfrn:hide/text()", $context)->item(0)->nodeValue == "true");
logger("Hidden status for contact ".$contact["url"].": ".$hide, LOGGER_DEBUG);
// If the contact isn't searchable then set the contact to "hidden".
// Problem: This can be manually overridden by the user.
if ($hide)
$contact["hidden"] = true;
// Save the keywords into the contact table
$tags = array();
$tagelements = $xpath->evaluate($element."/poco:tags/text()", $context);
@ -1261,17 +1288,17 @@ class dfrn {
unset($fields["name-date"]);
unset($fields["uri-date"]);
// Update check for this field has to be done differently
// Update check for this field has to be done differently
$datefields = array("name-date", "uri-date");
foreach ($datefields AS $field)
if (strtotime($contact[$field]) > strtotime($r[0][$field])) {
logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
logger("Difference for contact ".$contact["id"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG);
$update = true;
}
foreach ($fields AS $field => $data)
if ($contact[$field] != $r[0][$field]) {
logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
logger("Difference for contact ".$contact["id"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG);
$update = true;
}
@ -1279,13 +1306,13 @@ class dfrn {
logger("Update contact data for contact ".$contact["id"]." (".$contact["nick"].")", LOGGER_DEBUG);
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s',
`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s', `hidden` = %d,
`name-date` = '%s', `uri-date` = '%s'
WHERE `id` = %d AND `network` = '%s'",
dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
dbesc($contact["bd"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
intval($contact["id"]), dbesc($contact["network"]));
dbesc($contact["bd"]), intval($contact["hidden"]), dbesc($contact["name-date"]),
dbesc($contact["uri-date"]), intval($contact["id"]), dbesc($contact["network"]));
}
update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"],
@ -1298,6 +1325,7 @@ class dfrn {
$poco["generation"] = 2;
$poco["photo"] = $author["avatar"];
$poco["hide"] = $hide;
update_gcontact($poco);
}
@ -1323,7 +1351,7 @@ class dfrn {
$obj_element = $obj_doc->createElementNS(NAMESPACE_ATOM1, $element);
$activity_type = $xpath->query("activity:object-type/text()", $activity)->item(0)->nodeValue;
xml_add_element($obj_doc, $obj_element, "type", $activity_type);
xml::add_element($obj_doc, $obj_element, "type", $activity_type);
$id = $xpath->query("atom:id", $activity)->item(0);
if (is_object($id))
@ -1518,6 +1546,7 @@ class dfrn {
$relocate["uid"] = $importer["importer_uid"];
$relocate["cid"] = $importer["id"];
$relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue;
$relocate["addr"] = $xpath->query("dfrn:addr/text()", $relocation)->item(0)->nodeValue;
$relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue;
$relocate["photo"] = $xpath->query("dfrn:photo/text()", $relocation)->item(0)->nodeValue;
$relocate["thumb"] = $xpath->query("dfrn:thumb/text()", $relocation)->item(0)->nodeValue;
@ -1528,6 +1557,9 @@ class dfrn {
$relocate["poll"] = $xpath->query("dfrn:poll/text()", $relocation)->item(0)->nodeValue;
$relocate["sitepubkey"] = $xpath->query("dfrn:sitepubkey/text()", $relocation)->item(0)->nodeValue;
if ($relocate["addr"] == "")
$relocate["addr"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$3@$2", $relocate["url"]);
// update contact
$r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;",
intval($importer["id"]),
@ -1537,6 +1569,30 @@ class dfrn {
$old = $r[0];
// Update the gcontact entry
$relocate["server_url"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $relocate["url"]);
$x = q("UPDATE `gcontact` SET
`name` = '%s',
`photo` = '%s',
`url` = '%s',
`nurl` = '%s',
`addr` = '%s',
`connect` = '%s',
`notify` = '%s',
`server_url` = '%s'
WHERE `nurl` = '%s';",
dbesc($relocate["name"]),
dbesc($relocate["photo"]),
dbesc($relocate["url"]),
dbesc(normalise_link($relocate["url"])),
dbesc($relocate["addr"]),
dbesc($relocate["addr"]),
dbesc($relocate["notify"]),
dbesc($relocate["server_url"]),
dbesc(normalise_link($old["url"])));
// Update the contact table. We try to find every entry.
$x = q("UPDATE `contact` SET
`name` = '%s',
`photo` = '%s',
@ -1544,30 +1600,34 @@ class dfrn {
`micro` = '%s',
`url` = '%s',
`nurl` = '%s',
`addr` = '%s',
`request` = '%s',
`confirm` = '%s',
`notify` = '%s',
`poll` = '%s',
`site-pubkey` = '%s'
WHERE `id` = %d AND `uid` = %d;",
WHERE (`id` = %d AND `uid` = %d) OR (`nurl` = '%s');",
dbesc($relocate["name"]),
dbesc($relocate["photo"]),
dbesc($relocate["thumb"]),
dbesc($relocate["micro"]),
dbesc($relocate["url"]),
dbesc(normalise_link($relocate["url"])),
dbesc($relocate["addr"]),
dbesc($relocate["request"]),
dbesc($relocate["confirm"]),
dbesc($relocate["notify"]),
dbesc($relocate["poll"]),
dbesc($relocate["sitepubkey"]),
intval($importer["id"]),
intval($importer["importer_uid"]));
intval($importer["importer_uid"]),
dbesc(normalise_link($old["url"])));
if ($x === false)
return false;
// update items
/// @todo This is an extreme performance killer
$fields = array(
'owner-link' => array($old["url"], $relocate["url"]),
'author-link' => array($old["url"], $relocate["url"]),
@ -1773,6 +1833,9 @@ class dfrn {
* @return bool Should the processing of the entries be continued?
*/
private function process_verbs($entrytype, $importer, &$item, &$is_like) {
logger("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, LOGGER_DEBUG);
if (($entrytype == DFRN_TOP_LEVEL)) {
// The filling of the the "contact" variable is done for legcy reasons
// The functions below are partly used by ostatus.php as well - where we have this variable
@ -1803,11 +1866,11 @@ class dfrn {
return false;
}
} else {
if(($item["verb"] === ACTIVITY_LIKE)
|| ($item["verb"] === ACTIVITY_DISLIKE)
|| ($item["verb"] === ACTIVITY_ATTEND)
|| ($item["verb"] === ACTIVITY_ATTENDNO)
|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
if(($item["verb"] == ACTIVITY_LIKE)
|| ($item["verb"] == ACTIVITY_DISLIKE)
|| ($item["verb"] == ACTIVITY_ATTEND)
|| ($item["verb"] == ACTIVITY_ATTENDNO)
|| ($item["verb"] == ACTIVITY_ATTENDMAYBE)) {
$is_like = true;
$item["type"] = "activity";
$item["gravity"] = GRAVITY_LIKE;
@ -1833,7 +1896,7 @@ class dfrn {
} else
$is_like = false;
if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
if(($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
$xo = parse_xml_string($item["object"],false);
$xt = parse_xml_string($item["target"],false);
@ -1984,7 +2047,7 @@ class dfrn {
$item["extid"] = $xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue;
if ($xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue == "true")
if ($xpath->query("dfrn:bookmark/text()", $entry)->item(0)->nodeValue == "true")
$item["bookmark"] = true;
$notice_info = $xpath->query("statusnet:notice_info", $entry);
@ -2022,14 +2085,28 @@ class dfrn {
$categories = $xpath->query("atom:category", $entry);
if ($categories) {
foreach ($categories AS $category) {
foreach($category->attributes AS $attributes)
if ($attributes->name == "term") {
$term = "";
$scheme = "";
foreach($category->attributes AS $attributes) {
if ($attributes->name == "term")
$term = $attributes->textContent;
if ($attributes->name == "scheme")
$scheme = $attributes->textContent;
}
if (($term != "") AND ($scheme != "")) {
$parts = explode(":", $scheme);
if ((count($parts) >= 4) AND (array_shift($parts) == "X-DFRN")) {
$termhash = array_shift($parts);
$termurl = implode(":", $parts);
if(strlen($item["tag"]))
$item["tag"] .= ",";
$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
$item["tag"] .= $termhash."[url=".$termurl."]".$term."[/url]";
}
}
}
}
@ -2247,15 +2324,17 @@ class dfrn {
else
return;
if($item["object-type"] === ACTIVITY_OBJ_EVENT) {
if($item["object-type"] == ACTIVITY_OBJ_EVENT) {
logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
event_delete($item["event-id"]);
}
if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
if(($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
$xo = parse_xml_string($item["object"],false);
$xt = parse_xml_string($item["target"],false);
if($xt->type === ACTIVITY_OBJ_NOTE) {
if($xt->type == ACTIVITY_OBJ_NOTE) {
$i = q("SELECT `id`, `contact-id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($xt->id),
intval($importer["importer_uid"])

File diff suppressed because it is too large Load diff

View file

@ -1,55 +0,0 @@
<?php
require_once("boot.php");
require_once('include/diaspora.php');
function dsprphotoq_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);
};
logger("diaspora photo queue: running", LOGGER_DEBUG);
$r = q("SELECT * FROM dsprphotoq");
if(!$r)
return;
$dphotos = $r;
logger("diaspora photo queue: processing " . count($dphotos) . " photos");
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']));
if(!$r) {
logger("diaspora photo queue: user " . $dphoto['uid'] . " not found");
return;
}
$ret = diaspora_dispatch($r[0],unserialize($dphoto['msg']),$dphoto['attempt']);
q("DELETE FROM dsprphotoq WHERE id = %d",
intval($dphoto['id'])
);
}
}
if (array_search(__file__,get_included_files())===0){
dsprphotoq_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View file

@ -4,38 +4,43 @@ require_once('include/email.php');
require_once('include/bbcode.php');
require_once('include/html2bbcode.php');
/**
* @brief Creates a notification entry and possibly sends a mail
*
* @param array $params Array with the elements:
uid, item, parent, type, otype, verb, event,
link, subject, body, to_name, to_email, source_name,
source_link, activity, preamble, notify_flags,
language, show_in_notification_page
*/
function notification($params) {
#logger('notification()', LOGGER_DEBUG);
$a = get_app();
// from here on everything is in the recipients language
push_lang($params['language']);
$banner = t('Friendica Notification');
$product = FRIENDICA_PLATFORM;
$siteurl = $a->get_baseurl(true);
$thanks = t('Thank You,');
$sitename = $a->config['sitename'];
if (!x($a->config['admin_name'])) {
$site_admin = sprintf( t('%s Administrator'), $sitename);
} else {
$site_admin = sprintf( t('%1$s, %2$s Administrator'), $a->config['admin_name'], $sitename);
}
if (!x($a->config['admin_name']))
$site_admin = sprintf(t('%s Administrator'), $sitename);
else
$site_admin = sprintf(t('%1$s, %2$s Administrator'), $a->config['admin_name'], $sitename);
$nickname = "";
$sender_name = $sitename;
$hostname = $a->get_hostname();
if(strpos($hostname,':'))
$hostname = substr($hostname,0,strpos($hostname,':'));
if (strpos($hostname, ':'))
$hostname = substr($hostname, 0, strpos($hostname, ':'));
$sender_email = $a->config['sender_email'];
if (empty($sender_email)) {
$sender_email = t('noreply') . '@' . $hostname;
}
if (empty($sender_email))
$sender_email = t('noreply').'@'.$hostname;
$user = q("SELECT `nickname` FROM `user` WHERE `uid` = %d", intval($params['uid']));
if ($user)
@ -44,7 +49,7 @@ function notification($params) {
// with $params['show_in_notification_page'] == false, the notification isn't inserted into
// the database, and an email is sent if applicable.
// default, if not specified: true
$show_in_notification_page = ((x($params,'show_in_notification_page')) ? $params['show_in_notification_page']:True);
$show_in_notification_page = ((x($params, 'show_in_notification_page')) ? $params['show_in_notification_page']:True);
$additional_mail_header = "";
$additional_mail_header .= "Precedence: list\n";
@ -55,14 +60,11 @@ function notification($params) {
$additional_mail_header .= "List-ID: <notification.".$hostname.">\n";
$additional_mail_header .= "List-Archive: <".$a->get_baseurl()."/notifications/system>\n";
if(array_key_exists('item',$params)) {
if (array_key_exists('item', $params)) {
$title = $params['item']['title'];
$body = $params['item']['body'];
}
else {
} else
$title = $body = '';
}
// e.g. "your post", "David's photo", etc.
$possess_desc = t('%s <!item_type!>');
@ -77,23 +79,19 @@ function notification($params) {
else
$parent_id = 0;
if($params['type'] == NOTIFY_MAIL) {
if ($params['type'] == NOTIFY_MAIL) {
$subject = sprintf(t('[Friendica:Notify] New mail received at %s'), $sitename);
$subject = sprintf( t('[Friendica:Notify] New mail received at %s'),$sitename);
$preamble = sprintf(t('%1$s sent you a new private message at %2$s.'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s sent you %2$s.'), '[url='.$params['source_link'].']'.$params['source_name'].'[/url]', '[url=$itemlink]'.t('a private message').'[/url]');
$preamble = sprintf( t('%1$s sent you a new private message at %2$s.'),$params['source_name'],$sitename);
$epreamble = sprintf( t('%1$s sent you %2$s.'),'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]', '[url=$itemlink]' . t('a private message') . '[/url]');
$sitelink = t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf( $sitelink, $siteurl . '/message/' . $params['item']['id'] );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '/message/' . $params['item']['id'] . '">' . $sitename . '</a>');
$itemlink = $siteurl . '/message/' . $params['item']['id'];
$tsitelink = sprintf($sitelink, $siteurl.'/message/'.$params['item']['id']);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'/message/'.$params['item']['id'].'">'.$sitename.'</a>');
$itemlink = $siteurl.'/message/'.$params['item']['id'];
}
if($params['type'] == NOTIFY_COMMENT) {
// logger("notification: params = " . print_r($params, true), LOGGER_DEBUG);
//$parent_id = $params['parent'];
if ($params['type'] == NOTIFY_COMMENT) {
$p = q("SELECT `ignored` FROM `thread` WHERE `iid` = %d AND `uid` = %d LIMIT 1",
intval($parent_id),
intval($params['uid'])
@ -107,51 +105,49 @@ function notification($params) {
// If so don't create a second notification
$p = null;
$p = q("select id from notify where (type = %d or type = %d or type = %d) and link = '%s' and uid = %d limit 1",
$p = q("SELECT `id` FROM `notify` WHERE (`type` = %d OR `type` = %d OR `type` = %d) AND `link` = '%s' AND `uid` = %d LIMIT 1",
intval(NOTIFY_TAGSELF),
intval(NOTIFY_COMMENT),
intval(NOTIFY_SHARE),
dbesc($params['link']),
intval($params['uid'])
);
if($p and count($p)) {
if ($p and count($p)) {
pop_lang();
return;
}
// if it's a post figure out who's post it is.
$p = null;
if($params['otype'] === 'item' && $parent_id) {
$p = q("select * from item where id = %d and uid = %d limit 1",
if ($params['otype'] === 'item' && $parent_id) {
$p = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($parent_id),
intval($params['uid'])
);
}
$item_post_type = item_post_type($p[0]);
//$possess_desc = str_replace('<!item_type!>',$possess_desc);
// "a post"
$dest_str = sprintf(t('%1$s commented on [url=%2$s]a %3$s[/url]'),
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink,
$item_post_type);
// "George Bull's post"
if($p)
if ($p)
$dest_str = sprintf(t('%1$s commented on [url=%2$s]%3$s\'s %4$s[/url]'),
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink,
$p[0]['author-name'],
$item_post_type);
// "your post"
if($p[0]['owner-name'] == $p[0]['author-name'] && $p[0]['wall'])
if ($p[0]['owner-name'] == $p[0]['author-name'] && $p[0]['wall'])
$dest_str = sprintf(t('%1$s commented on [url=%2$s]your %3$s[/url]'),
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink,
$item_post_type);
@ -160,190 +156,200 @@ function notification($params) {
// Before this we have the name of the replier on the subject rendering
// differents subjects for messages on the same thread.
$subject = sprintf( t('[Friendica:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $params['source_name']);
$preamble = sprintf( t('%s commented on an item/conversation you have been following.'), $params['source_name']);
$subject = sprintf(t('[Friendica:Notify] Comment to conversation #%1$d by %2$s'), $parent_id, $params['source_name']);
$preamble = sprintf(t('%s commented on an item/conversation you have been following.'), $params['source_name']);
$epreamble = $dest_str;
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_WALL) {
$subject = sprintf( t('[Friendica:Notify] %s posted to your profile wall') , $params['source_name']);
if ($params['type'] == NOTIFY_WALL) {
$subject = sprintf(t('[Friendica:Notify] %s posted to your profile wall'), $params['source_name']);
$preamble = sprintf( t('%1$s posted to your profile wall at %2$s') , $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s posted to [url=%2$s]your wall[/url]') ,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$params['link']);
$preamble = sprintf(t('%1$s posted to your profile wall at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s posted to [url=%2$s]your wall[/url]'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_TAGSELF) {
$subject = sprintf( t('[Friendica:Notify] %s tagged you') , $params['source_name']);
$preamble = sprintf( t('%1$s tagged you at %2$s') , $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s [url=%2$s]tagged you[/url].') ,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$params['link']);
if ($params['type'] == NOTIFY_TAGSELF) {
$subject = sprintf(t('[Friendica:Notify] %s tagged you'), $params['source_name']);
$preamble = sprintf(t('%1$s tagged you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s [url=%2$s]tagged you[/url].'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_SHARE) {
$subject = sprintf( t('[Friendica:Notify] %s shared a new post') , $params['source_name']);
$preamble = sprintf( t('%1$s shared a new post at %2$s') , $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s [url=%2$s]shared a post[/url].') ,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$params['link']);
if ($params['type'] == NOTIFY_SHARE) {
$subject = sprintf(t('[Friendica:Notify] %s shared a new post'), $params['source_name']);
$preamble = sprintf(t('%1$s shared a new post at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s [url=%2$s]shared a post[/url].'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$params['link']);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_POKE) {
if ($params['type'] == NOTIFY_POKE) {
$subject = sprintf(t('[Friendica:Notify] %1$s poked you'), $params['source_name']);
$subject = sprintf( t('[Friendica:Notify] %1$s poked you') , $params['source_name']);
$preamble = sprintf( t('%1$s poked you at %2$s') , $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s [url=%2$s]poked you[/url].') ,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$params['link']);
$preamble = sprintf(t('%1$s poked you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s [url=%2$s]poked you[/url].'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$params['link']);
$subject = str_replace('poked', t($params['activity']), $subject);
$preamble = str_replace('poked', t($params['activity']), $preamble);
$epreamble = str_replace('poked', t($params['activity']), $epreamble);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_TAGSHARE) {
$subject = sprintf( t('[Friendica:Notify] %s tagged your post') , $params['source_name']);
$preamble = sprintf( t('%1$s tagged your post at %2$s') , $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s tagged [url=%2$s]your post[/url]') ,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink);
if ($params['type'] == NOTIFY_TAGSHARE) {
$subject = sprintf(t('[Friendica:Notify] %s tagged your post'), $params['source_name']);
$preamble = sprintf(t('%1$s tagged your post at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s tagged [url=%2$s]your post[/url]'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink);
$sitelink = t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_INTRO) {
$subject = sprintf( t('[Friendica:Notify] Introduction received'));
$preamble = sprintf( t('You\'ve received an introduction from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [url=%1$s]an introduction[/url] from %2$s.'),
$itemlink,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]');
$body = sprintf( t('You may visit their profile at %s'),$params['source_link']);
if ($params['type'] == NOTIFY_INTRO) {
$subject = sprintf(t('[Friendica:Notify] Introduction received'));
$preamble = sprintf(t('You\'ve received an introduction from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You\'ve received [url=%1$s]an introduction[/url] from %2$s.'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = sprintf(t('You may visit their profile at %s'), $params['source_link']);
$sitelink = t('Please visit %s to approve or reject the introduction.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
switch ($params['verb']) {
case ACTIVITY_FRIEND:
// someone started to share with user (mostly OStatus)
$subject = sprintf( t('[Friendica:Notify] A new person is sharing with you'));
$preamble = sprintf( t('%1$s is sharing with you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('%1$s is sharing with you at %2$s'),
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$sitename);
$subject = sprintf(t('[Friendica:Notify] A new person is sharing with you'));
$preamble = sprintf(t('%1$s is sharing with you at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%1$s is sharing with you at %2$s'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$sitename);
break;
case ACTIVITY_FOLLOW:
// someone started to follow the user (mostly OStatus)
$subject = sprintf( t('[Friendica:Notify] You have a new follower'));
$preamble = sprintf( t('You have a new follower at %2$s : %1$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('You have a new follower at %2$s : %1$s'),
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$sitename);
$subject = sprintf(t('[Friendica:Notify] You have a new follower'));
$preamble = sprintf(t('You have a new follower at %2$s : %1$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You have a new follower at %2$s : %1$s'),
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$sitename);
break;
default:
// ACTIVITY_REQ_FRIEND is default activity for notifications
break;
}
}
if($params['type'] == NOTIFY_SUGGEST) {
$subject = sprintf( t('[Friendica:Notify] Friend suggestion received'));
$preamble = sprintf( t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.'),
$itemlink,
'[url=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]');
if ($params['type'] == NOTIFY_SUGGEST) {
$subject = sprintf(t('[Friendica:Notify] Friend suggestion received'));
$body = t('Name:') . ' ' . $params['item']['name'] . "\n";
$body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n";
$body .= sprintf( t('You may visit their profile at %s'),$params['item']['url']);
$preamble = sprintf(t('You\'ve received a friend suggestion from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You\'ve received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s.'),
$itemlink,
'[url='.$params['item']['url'].']'.$params['item']['name'].'[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = t('Name:').' '.$params['item']['name']."\n";
$body .= t('Photo:').' '.$params['item']['photo']."\n";
$body .= sprintf(t('You may visit their profile at %s'), $params['item']['url']);
$sitelink = t('Please visit %s to approve or reject the suggestion.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if($params['type'] == NOTIFY_CONFIRM) {
if ($params['verb'] == ACTIVITY_FRIEND ){ // mutual connection
$subject = sprintf( t('[Friendica:Notify] Connection accepted'));
$preamble = sprintf( t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('%2$s has accepted your [url=%1$s]connection request[/url].'),
$itemlink,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]');
$body = t('You are now mutual friends and may exchange status updates, photos, and email
without restriction.');
if ($params['type'] == NOTIFY_CONFIRM) {
if ($params['verb'] == ACTIVITY_FRIEND) { // mutual connection
$subject = sprintf(t('[Friendica:Notify] Connection accepted'));
$sitelink = t('Please visit %s if you wish to make any changes to this relationship.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$preamble = sprintf(t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%2$s has accepted your [url=%1$s]connection request[/url].'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = t('You are now mutual friends and may exchange status updates, photos, and email without restriction.');
$sitelink = t('Please visit %s if you wish to make any changes to this relationship.');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
} else { // ACTIVITY_FOLLOW
$subject = sprintf( t('[Friendica:Notify] Connection accepted'));
$preamble = sprintf( t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('%2$s has accepted your [url=%1$s]connection request[/url].'),
$itemlink,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]');
$subject = sprintf(t('[Friendica:Notify] Connection accepted'));
$preamble = sprintf(t('\'%1$s\' has accepted your connection request at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('%2$s has accepted your [url=%1$s]connection request[/url].'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = sprintf(t('\'%1$s\' has chosen to accept you a "fan", which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically.'), $params['source_name']);
$body .= "\n\n";
$body .= sprintf(t('\'%1$s\' may choose to extend this into a two-way or more permissive relationship in the future. '), $params['source_name']);
$body .= sprintf(t('\'%1$s\' may choose to extend this into a two-way or more permissive relationship in the future.'), $params['source_name']);
$sitelink = t('Please visit %s if you wish to make any changes to this relationship.');
$tsitelink = sprintf( $sitelink, $siteurl );
$hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
}
if($params['type'] == NOTIFY_SYSTEM) {
if ($params['type'] == NOTIFY_SYSTEM) {
switch($params['event']) {
case "SYSTEM_REGISTER_REQUEST":
$subject = sprintf( t('[Friendica System:Notify] registration request'));
$preamble = sprintf( t('You\'ve received a registration request from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf( t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.'),
$itemlink,
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]');
$body = sprintf( t('Full Name: %1$s\nSite Location: %2$s\nLogin Name: %3$s (%4$s)'),
$subject = sprintf(t('[Friendica System:Notify] registration request'));
$preamble = sprintf(t('You\'ve received a registration request from \'%1$s\' at %2$s'), $params['source_name'], $sitename);
$epreamble = sprintf(t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.'),
$itemlink,
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]');
$body = sprintf(t('Full Name: %1$s\nSite Location: %2$s\nLogin Name: %3$s (%4$s)'),
$params['source_name'], $siteurl, $params['source_mail'], $params['source_nick']);
$sitelink = t('Please visit %s to approve or reject the request.');
$tsitelink = sprintf( $sitelink, $params['link'] );
$hsitelink = sprintf( $sitelink, '<a href="' . $params['link'] . '">' . $sitename . '</a><br><br>');
$tsitelink = sprintf($sitelink, $params['link']);
$hsitelink = sprintf($sitelink, '<a href="'.$params['link'].'">'.$sitename.'</a><br><br>');
$itemlink = $params['link'];
break;
case "SYSTEM_DB_UPDATE_FAIL":
@ -351,20 +357,23 @@ function notification($params) {
}
}
if ($params['type'] == "SYSTEM_EMAIL"){
if ($params['type'] == "SYSTEM_EMAIL") {
// not part of the notifications.
// it just send a mail to the user.
// It will be used by the system to send emails to users (like
// password reset, invitations and so) using one look (but without
// add a notification to the user, with could be inexistent)
$subject = $params['subject'];
$preamble = $params['preamble'];
$body = $params['body'];
$sitelink = "";
$tsitelink = "";
$hsitelink = "";
$itemlink = "";
$show_in_notification_page = false;
$subject = $params['subject'];
$preamble = $params['preamble'];
$body = $params['body'];
$sitelink = "";
$tsitelink = "";
$hsitelink = "";
$itemlink = "";
$show_in_notification_page = false;
}
$subject .= " (".$nickname."@".$hostname.")";
@ -381,19 +390,20 @@ function notification($params) {
'itemlink' => $itemlink
);
call_hooks('enotify',$h);
call_hooks('enotify', $h);
$subject = $h['subject'];
$preamble = $h['preamble'];
$epreamble = $h['epreamble'];
$body = $h['body'];
$sitelink = $h['sitelink'];
$tsitelink = $h['tsitelink'];
$hsitelink = $h['hsitelink'];
$itemlink = $h['itemlink'];
if ($show_in_notification_page) {
logger("adding notification entry", LOGGER_DEBUG);
do {
@ -401,11 +411,10 @@ function notification($params) {
$hash = random_string();
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1",
dbesc($hash));
if(count($r))
if (count($r))
$dups = true;
} while($dups == true);
$datarray = array();
$datarray['hash'] = $hash;
$datarray['name'] = $params['source_name'];
@ -423,15 +432,15 @@ function notification($params) {
call_hooks('enotify_store', $datarray);
if($datarray['abort']) {
if ($datarray['abort']) {
pop_lang();
return False;
}
// create notification entry in DB
$r = q("insert into notify (hash,name,url,photo,date,uid,link,iid,parent,type,verb,otype)
values('%s','%s','%s','%s','%s',%d,'%s',%d,%d,%d,'%s','%s')",
$r = q("INSERT INTO `notify` (`hash`, `name`, `url`, `photo`, `date`, `uid`, `link`, `iid`, `parent`, `type`, `verb`, `otype`)
values('%s', '%s', '%s', '%s', '%s', %d, '%s', %d, %d, %d, '%s', '%s')",
dbesc($datarray['hash']),
dbesc($datarray['name']),
dbesc($datarray['url']),
@ -446,11 +455,11 @@ function notification($params) {
dbesc($datarray['otype'])
);
$r = q("select id from notify where hash = '%s' and uid = %d limit 1",
$r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' AND `uid` = %d LIMIT 1",
dbesc($hash),
intval($params['uid'])
);
if($r)
if ($r)
$notify_id = $r[0]['id'];
else {
pop_lang();
@ -461,40 +470,39 @@ function notification($params) {
// After we've stored everything, look again to see if there are any duplicates and if so remove them
$p = null;
$p = q("select id from notify where ( type = %d or type = %d ) and link = '%s' and uid = %d order by id",
$p = q("SELECT `id` FROM `notify` WHERE (`type` = %d OR `type` = %d) AND `link` = '%s' AND `uid` = %d ORDER BY `id`",
intval(NOTIFY_TAGSELF),
intval(NOTIFY_COMMENT),
dbesc($params['link']),
intval($params['uid'])
);
if($p && (count($p) > 1)) {
if ($p && (count($p) > 1)) {
for ($d = 1; $d < count($p); $d ++) {
q("delete from notify where id = %d",
q("DELETE FROM `notify` WHERE `id` = %d",
intval($p[$d]['id'])
);
}
// only continue on if we stored the first one
if($notify_id != $p[0]['id']) {
if ($notify_id != $p[0]['id']) {
pop_lang();
return False;
}
}
$itemlink = $a->get_baseurl() . '/notify/view/' . $notify_id;
$msg = replace_macros($epreamble,array('$itemlink' => $itemlink));
$r = q("update notify set msg = '%s' where id = %d and uid = %d",
$itemlink = $a->get_baseurl().'/notify/view/'.$notify_id;
$msg = replace_macros($epreamble, array('$itemlink' => $itemlink));
$r = q("UPDATE `notify` SET `msg` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc($msg),
intval($notify_id),
intval($params['uid'])
);
}
// send email notification if notification preferences permit
if((intval($params['notify_flags']) & intval($params['type']))
if ((intval($params['notify_flags']) & intval($params['type']))
|| $params['type'] == NOTIFY_SYSTEM
|| $params['type'] == "SYSTEM_EMAIL") {
@ -505,39 +513,37 @@ function notification($params) {
// Is this the first email notification for this parent item and user?
$r = q("select `id` from `notify-threads` where `master-parent-item` = %d and `receiver-uid` = %d limit 1",
$r = q("SELECT `id` FROM `notify-threads` WHERE `master-parent-item` = %d AND `receiver-uid` = %d LIMIT 1",
intval($params['parent']),
intval($params['uid']) );
intval($params['uid']));
// If so, create the record of it and use a message-id smtp header.
if(!$r) {
if (!$r) {
logger("notify_id:".intval($notify_id).", parent: ".intval($params['parent'])."uid: ".intval($params['uid']), LOGGER_DEBUG);
$r = q("insert into `notify-threads` (`notify-id`, `master-parent-item`, `receiver-uid`, `parent-item`)
values(%d,%d,%d,%d)",
$r = q("INSERT INTO `notify-threads` (`notify-id`, `master-parent-item`, `receiver-uid`, `parent-item`)
values(%d, %d, %d, %d)",
intval($notify_id),
intval($params['parent']),
intval($params['uid']),
0 );
0);
$additional_mail_header .= "Message-ID: <${id_for_parent}>\n";
$log_msg = "include/enotify: No previous notification found for this parent:\n" .
" parent: ${params['parent']}\n" . " uid : ${params['uid']}\n";
$log_msg = "include/enotify: No previous notification found for this parent:\n".
" parent: ${params['parent']}\n"." uid : ${params['uid']}\n";
logger($log_msg, LOGGER_DEBUG);
} else {
// If not, just "follow" the thread.
$additional_mail_header .= "References: <${id_for_parent}>\nIn-Reply-To: <${id_for_parent}>\n";
logger("There's already a notification for this parent:\n" . print_r($r, true), LOGGER_DEBUG);
logger("There's already a notification for this parent:\n".print_r($r, true), LOGGER_DEBUG);
}
}
// textversion keeps linebreaks
$textversion = strip_tags(str_replace("<br>","\n",html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n"), "\n",
$body))),ENT_QUOTES,'UTF-8')));
$htmlversion = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r","\\n\\n" ,"\\n"),
"<br />\n",$body))),ENT_QUOTES,'UTF-8');
$textversion = strip_tags(str_replace("<br>", "\n", html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n"), "\n",
$body))),ENT_QUOTES, 'UTF-8')));
$htmlversion = html_entity_decode(bbcode(stripslashes(str_replace(array("\\r\\n", "\\r", "\\n\\n", "\\n"),
"<br />\n", $body))), ENT_QUOTES, 'UTF-8');
$datarray = array();
$datarray['banner'] = $banner;
@ -554,7 +560,7 @@ function notification($params) {
$datarray['username'] = $params['to_name'];
$datarray['hsitelink'] = $hsitelink;
$datarray['tsitelink'] = $tsitelink;
$datarray['hitemlink'] = '<a href="' . $itemlink . '">' . $itemlink . '</a>';
$datarray['hitemlink'] = '<a href="'.$itemlink.'">'.$itemlink.'</a>';
$datarray['titemlink'] = $itemlink;
$datarray['thanks'] = $thanks;
$datarray['site_admin'] = $site_admin;
@ -568,14 +574,14 @@ function notification($params) {
// check whether sending post content in email notifications is allowed
// always true for "SYSTEM_EMAIL"
$content_allowed = ((!get_config('system','enotify_no_content')) || ($params['type'] == "SYSTEM_EMAIL"));
$content_allowed = ((!get_config('system', 'enotify_no_content')) || ($params['type'] == "SYSTEM_EMAIL"));
// load the template for private message notifications
$tpl = get_markup_template('email_notify_html.tpl');
$email_html_body = replace_macros($tpl,array(
$email_html_body = replace_macros($tpl, array(
'$banner' => $datarray['banner'],
'$product' => $datarray['product'],
'$preamble' => str_replace("\n","<br>\n",$datarray['preamble']),
'$preamble' => str_replace("\n", "<br>\n", $datarray['preamble']),
'$sitename' => $datarray['sitename'],
'$siteurl' => $datarray['siteurl'],
'$source_name' => $datarray['source_name'],
@ -586,14 +592,14 @@ function notification($params) {
'$hitemlink' => $datarray['hitemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
'$title' => $datarray['title'],
'$title' => $datarray['title'],
'$htmlversion' => $datarray['htmlversion'],
'$content_allowed' => $content_allowed,
));
// load the template for private message notifications
$tpl = get_markup_template('email_notify_text.tpl');
$email_text_body = replace_macros($tpl,array(
$email_text_body = replace_macros($tpl, array(
'$banner' => $datarray['banner'],
'$product' => $datarray['product'],
'$preamble' => $datarray['preamble'],
@ -607,13 +613,11 @@ function notification($params) {
'$titemlink' => $datarray['titemlink'],
'$thanks' => $datarray['thanks'],
'$site_admin' => $datarray['site_admin'],
'$title' => $datarray['title'],
'$title' => $datarray['title'],
'$textversion' => $datarray['textversion'],
'$content_allowed' => $content_allowed,
));
// logger('text: ' . $email_text_body);
// use the Emailer class to send the message
return Emailer::send(array(
@ -630,7 +634,6 @@ function notification($params) {
}
return False;
}
/**
@ -647,7 +650,7 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
$profiles = $notification_data["profiles"];
$user = q("SELECT `notify-flags`, `language`, `username`, `email` FROM `user` WHERE `uid` = %d", intval($uid));
$user = q("SELECT `notify-flags`, `language`, `username`, `email`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid));
if (!$user)
return false;
@ -655,13 +658,30 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
if (!$owner)
return false;
// This is our regular URL format
$profiles[] = $owner[0]["url"];
// Notifications from Diaspora are often with an URL in the Diaspora format
$profiles[] = App::get_baseurl()."/u/".$user[0]["nickname"];
$profiles2 = array();
foreach ($profiles AS $profile) {
$profiles2[] = normalise_link($profile);
$profiles2[] = str_replace("http://", "https://", normalise_link($profile));
// Check for invalid profile urls. 13 should be the shortest possible profile length:
// http://a.bc/d
// Additionally check for invalid urls that would return the normalised value "http:"
if ((strlen($profile) >= 13) AND (normalise_link($profile) != "http:")) {
if (!in_array($profile, $profiles2))
$profiles2[] = $profile;
$profile = normalise_link($profile);
if (!in_array($profile, $profiles2))
$profiles2[] = $profile;
$profile = str_replace("http://", "https://", $profile);
if (!in_array($profile, $profiles2))
$profiles2[] = $profile;
}
}
$profiles = $profiles2;
@ -703,26 +723,26 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
$params["source_photo"] = $item[0]["author-avatar"];
if ($item[0]["parent-uri"] === $item[0]["uri"]) {
// Send a notification for every new post?
$r = q("SELECT `notify_new_posts` FROM `contact` WHERE `id` = %d AND `uid` = %d AND `notify_new_posts` LIMIT 1",
intval($item[0]['contact-id']),
intval($uid)
);
$send_notification = count($r);
// Send a notification for every new post?
$r = q("SELECT `notify_new_posts` FROM `contact` WHERE `id` = %d AND `uid` = %d AND `notify_new_posts` LIMIT 1",
intval($item[0]['contact-id']),
intval($uid)
);
$send_notification = count($r);
if (!$send_notification) {
$tags = q("SELECT `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` = %d AND `uid` = %d",
intval(TERM_OBJ_POST), intval($itemid), intval(TERM_MENTION), intval($uid));
if (!$send_notification) {
$tags = q("SELECT `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` = %d AND `uid` = %d",
intval(TERM_OBJ_POST), intval($itemid), intval(TERM_MENTION), intval($uid));
if (count($tags)) {
foreach ($tags AS $tag) {
$r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `notify_new_posts`",
normalise_link($tag["url"]), intval($uid));
if (count($r))
$send_notification = true;
}
}
}
if (count($tags)) {
foreach ($tags AS $tag) {
$r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `notify_new_posts`",
normalise_link($tag["url"]), intval($uid));
if (count($r))
$send_notification = true;
}
}
}
if ($send_notification) {
$params["type"] = NOTIFY_SHARE;

View file

@ -291,10 +291,6 @@ function event_store($arr) {
`type` = '%s',
`adjust` = %d,
`nofinish` = %d,
`allow_cid` = '%s',
`allow_gid` = '%s',
`deny_cid` = '%s',
`deny_gid` = '%s'
WHERE `id` = %d AND `uid` = %d",
dbesc($arr['edited']),
@ -306,10 +302,6 @@ function event_store($arr) {
dbesc($arr['type']),
intval($arr['adjust']),
intval($arr['nofinish']),
dbesc($arr['allow_cid']),
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid']),
intval($arr['id']),
intval($arr['uid'])
);
@ -323,22 +315,16 @@ function event_store($arr) {
$object .= '</object>' . "\n";
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `edited` = '%s', `private` = %d WHERE `id` = %d AND `uid` = %d",
q("UPDATE `item` SET `body` = '%s', `object` = '%s', `edited` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc(format_event_bbcode($arr)),
dbesc($object),
dbesc($arr['allow_cid']),
dbesc($arr['allow_gid']),
dbesc($arr['deny_cid']),
dbesc($arr['deny_gid']),
dbesc($arr['edited']),
intval($arr['private']),
intval($r[0]['id']),
intval($arr['uid'])
);
$item_id = $r[0]['id'];
}
else
} else
$item_id = 0;
call_hooks("event_updated", $arr['id']);

View file

@ -47,15 +47,17 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
}
// Is it Atom?
if ($xpath->query('/atom:feed/atom:entry')->length > 0) {
if ($xpath->query('/atom:feed')->length > 0) {
$alternate = $xpath->query("atom:link[@rel='alternate']")->item(0)->attributes;
if (is_object($alternate))
foreach($alternate AS $attributes)
if ($attributes->name == "href")
$author["author-link"] = $attributes->textContent;
$author["author-id"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
if ($author["author-link"] == "")
$author["author-link"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
$author["author-link"] = $author["author-id"];
if ($author["author-link"] == "") {
$self = $xpath->query("atom:link[@rel='self']")->item(0)->attributes;
@ -127,6 +129,7 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
// This is no field in the item table. So we have to unset it.
unset($author["author-nick"]);
unset($author["author-id"]);
}
$header = array();

View file

@ -1,6 +1,7 @@
<?php
require_once("include/Scrape.php");
require_once("include/socgraph.php");
require_once('include/group.php');
function update_contact($id) {
/*
@ -259,10 +260,8 @@ function new_contact($uid,$url,$interactive = false) {
$result['cid'] = $contact_id;
$def_gid = get_default_group($uid, $contact["network"]);
if (intval($def_gid)) {
require_once('include/group.php');
if (intval($def_gid))
group_add_member($uid, '', $contact_id, $def_gid);
}
require_once("include/Photo.php");
@ -303,8 +302,8 @@ function new_contact($uid,$url,$interactive = false) {
}
if($contact['network'] == NETWORK_DIASPORA) {
require_once('include/diaspora.php');
$ret = diaspora_share($a->user,$contact);
logger('mod_follow: diaspora_share returns: ' . $ret);
$ret = diaspora::send_share($a->user,$contact);
logger('share returns: '.$ret);
}
}

View file

@ -39,7 +39,7 @@ function gprobe_run(&$argv, &$argc){
logger("gprobe start for ".normalise_link($url), LOGGER_DEBUG);
if(! count($r)) {
if (!count($r)) {
// Is it a DDoS attempt?
$urlparts = parse_url($url);
@ -58,16 +58,18 @@ function gprobe_run(&$argv, &$argc){
if (is_null($result))
Cache::set("gprobe:".$urlparts["host"],serialize($arr));
if (!in_array($result["network"], array(NETWORK_FEED, NETWORK_PHANTOM)))
if (!in_array($arr["network"], array(NETWORK_FEED, NETWORK_PHANTOM)))
update_gcontact($arr);
$r = q("SELECT `id`, `url`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 1",
dbesc(normalise_link($url))
);
}
if(count($r))
if ($r[0]["network"] == NETWORK_DFRN)
if(count($r)) {
// Check for accessibility and do a poco discovery
if (poco_last_updated($r[0]['url'], true) AND ($r[0]["network"] == NETWORK_DFRN))
poco_load(0,0,$r[0]['id'], str_replace('/profile/','/poco/',$r[0]['url']));
}
logger("gprobe end for ".normalise_link($url), LOGGER_DEBUG);
return;

View file

@ -366,7 +366,7 @@ function groups_containing($uid,$c) {
function groups_count_unseen() {
$r = q("SELECT `group`.`id`, `group`.`name`,
(SELECT COUNT(*) FROM `item`
(SELECT COUNT(*) FROM `item` FORCE INDEX (`uid_unseen_contactid`)
WHERE `uid` = %d AND `unseen` AND
`contact-id` IN (SELECT `contact-id` FROM `group_member`
WHERE `group_member`.`gid` = `group`.`id` AND `group_member`.`uid` = %d)) AS `count`

View file

@ -246,10 +246,30 @@ function profile_sidebar($profile, $block = 0) {
else
$subscribe_feed = false;
if(get_my_url() && $profile['unkmail'] && ($profile['uid'] != local_user()))
if (remote_user() OR (get_my_url() && $profile['unkmail'] && ($profile['uid'] != local_user()))) {
$wallmessage = t('Message');
else
$wallmessage_link = "wallmessage/".$profile["nickname"];
if (remote_user()) {
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `id` = '%s' AND `rel` = %d",
intval($profile['uid']),
intval(remote_user()),
intval(CONTACT_IS_FRIEND));
} else {
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `rel` = %d",
intval($profile['uid']),
dbesc(normalise_link(get_my_url())),
intval(CONTACT_IS_FRIEND));
}
if ($r) {
$remote_url = $r[0]["url"];
$message_path = preg_replace("=(.*)/profile/(.*)=ism", "$1/message/new/", $remote_url);
$wallmessage_link = $message_path.base64_encode($profile["addr"]);
}
} else {
$wallmessage = false;
$wallmessage_link = false;
}
// show edit profile to yourself
if ($profile['uid'] == local_user() && feature_enabled(local_user(),'multi_profiles')) {
@ -325,18 +345,21 @@ function profile_sidebar($profile, $block = 0) {
? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']);
$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'],
'fullname' => $profile['name'],
'firstname' => $firstname,
'lastname' => $lastname,
'photo300' => $a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg',
'photo100' => $a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg',
'photo50' => $a->get_baseurl() . '/photo/custom/50/' . $profile['uid'] . '.jpg',
);
if ($profile['guid'] != "")
$diaspora = array(
'guid' => $profile['guid'],
'podloc' => $a->get_baseurl(),
'searchable' => (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false' ),
'nickname' => $profile['nickname'],
'fullname' => $profile['name'],
'firstname' => $firstname,
'lastname' => $lastname,
'photo300' => $a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg',
'photo100' => $a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg',
'photo50' => $a->get_baseurl() . '/photo/custom/50/' . $profile['uid'] . '.jpg',
);
else
$diaspora = false;
if (!$block){
$contact_block = contact_block();
@ -386,6 +409,7 @@ function profile_sidebar($profile, $block = 0) {
'$remoteconnect' => $remoteconnect,
'$subscribe_feed' => $subscribe_feed,
'$wallmessage' => $wallmessage,
'$wallmessage_link' => $wallmessage_link,
'$account_type' => $account_type,
'$location' => $location,
'$gender' => $gender,
@ -400,7 +424,6 @@ function profile_sidebar($profile, $block = 0) {
'$contact_block' => $contact_block,
));
$arr = array('profile' => &$profile, 'entry' => &$o);
call_hooks('profile_sidebar', $arr);

View file

@ -18,6 +18,7 @@ require_once('include/Contact.php');
require_once('mod/share.php');
require_once('include/enotify.php');
require_once('include/dfrn.php');
require_once('include/group.php');
require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
@ -160,24 +161,31 @@ function add_page_info_data($data) {
if ($no_photos AND ($data["type"] == "photo"))
return("");
// If the link contains BBCode stuff, make a short link out of this to avoid parsing problems
if (strpos($data["url"], '[') OR strpos($data["url"], ']')) {
require_once("include/network.php");
$data["url"] = short_link($data["url"]);
if (sizeof($data["images"]) > 0)
$preview = $data["images"][0];
else
$preview = "";
// Escape some bad characters
$data["url"] = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($data["url"], ENT_QUOTES, 'UTF-8', false));
$data["title"] = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($data["title"], ENT_QUOTES, 'UTF-8', false));
$text = "[attachment type='".$data["type"]."'";
if ($data["url"] != "")
$text .= " url='".$data["url"]."'";
if ($data["title"] != "")
$text .= " title='".$data["title"]."'";
if (sizeof($data["images"]) > 0) {
$preview = str_replace(array("[", "]"), array("&#91;", "&#93;"), htmlentities($data["images"][0]["src"], ENT_QUOTES, 'UTF-8', false));
// if the preview picture is larger than 500 pixels then show it in a larger mode
// But only, if the picture isn't higher than large (To prevent huge posts)
if (($data["images"][0]["width"] >= 500) AND ($data["images"][0]["width"] >= $data["images"][0]["height"]))
$text .= " image='".$preview."'";
else
$text .= " preview='".$preview."'";
}
if (($data["type"] != "photo") AND is_string($data["title"]))
$text .= "[bookmark=".$data["url"]."]".trim($data["title"])."[/bookmark]";
if (($data["type"] != "video") AND ($photo != ""))
$text .= '[img]'.$photo.'[/img]';
elseif (($data["type"] != "video") AND (sizeof($data["images"]) > 0)) {
$imagedata = $data["images"][0];
$text .= '[img]'.$imagedata["src"].'[/img]';
}
if (($data["type"] != "photo") AND is_string($data["text"]))
$text .= "[quote]".$data["text"]."[/quote]";
$text .= "]".$data["text"]."[/attachment]";
$hashtags = "";
if (isset($data["keywords"]) AND count($data["keywords"])) {
@ -191,7 +199,7 @@ function add_page_info_data($data) {
}
}
return("\n[class=type-".$data["type"]."]".$text."[/class]".$hashtags);
return "\n".$text.$hashtags;
}
function query_page_info($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "") {
@ -383,9 +391,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
// Converting the plink
if ($arr['network'] == NETWORK_OSTATUS) {
if (isset($arr['plink']))
$arr['plink'] = ostatus_convert_href($arr['plink']);
$arr['plink'] = ostatus::convert_href($arr['plink']);
elseif (isset($arr['uri']))
$arr['plink'] = ostatus_convert_href($arr['uri']);
$arr['plink'] = ostatus::convert_href($arr['uri']);
}
if(x($arr, 'gravity'))
@ -499,6 +507,13 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
$arr['inform'] = ((x($arr,'inform')) ? trim($arr['inform']) : '');
$arr['file'] = ((x($arr,'file')) ? trim($arr['file']) : '');
// Items cannot be stored before they happen ...
if ($arr['created'] > datetime_convert())
$arr['created'] = datetime_convert();
// We haven't invented time travel by now.
if ($arr['edited'] > datetime_convert())
$arr['edited'] = datetime_convert();
if (($arr['author-link'] == "") AND ($arr['owner-link'] == ""))
logger("Both author-link and owner-link are empty. Called by: ".App::callstack(), LOGGER_DEBUG);
@ -707,9 +722,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
if ($arr["uid"] == 0) {
$arr["global"] = true;
q("UPDATE `item` SET `global` = 1 WHERE `guid` = '%s'", dbesc($arr["guid"]));
q("UPDATE `item` SET `global` = 1 WHERE `uri` = '%s'", dbesc($arr["uri"]));
} else {
$isglobal = q("SELECT `global` FROM `item` WHERE `uid` = 0 AND `guid` = '%s'", dbesc($arr["guid"]));
$isglobal = q("SELECT `global` FROM `item` WHERE `uid` = 0 AND `uri` = '%s'", dbesc($arr["uri"]));
$arr["global"] = (count($isglobal) > 0);
}
@ -1243,7 +1258,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
//$tempfile = tempnam(get_temppath(), "ostatus2");
//file_put_contents($tempfile, $xml);
logger("Consume OStatus messages ", LOGGER_DEBUG);
ostatus_import($xml,$importer,$contact, $hub);
ostatus::import($xml,$importer,$contact, $hub);
}
return;
}
@ -1260,17 +1275,17 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
logger("Consume DFRN messages", LOGGER_DEBUG);
$r = q("SELECT `contact`.*, `contact`.`uid` AS `importer_uid`,
`contact`.`pubkey` AS `cpubkey`,
`contact`.`prvkey` AS `cprvkey`,
`contact`.`thumb` AS `thumb`,
`contact`.`url` as `url`,
`contact`.`name` as `senderName`,
`user`.*
FROM `contact`
LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `contact`.`id` = %d AND `user`.`uid` = %d",
dbesc($contact["id"]), dbesc($importer["uid"])
);
`contact`.`pubkey` AS `cpubkey`,
`contact`.`prvkey` AS `cprvkey`,
`contact`.`thumb` AS `thumb`,
`contact`.`url` as `url`,
`contact`.`name` as `senderName`,
`user`.*
FROM `contact`
LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `contact`.`id` = %d AND `user`.`uid` = %d",
dbesc($contact["id"]), dbesc($importer["uid"])
);
if ($r) {
logger("Now import the DFRN feed");
dfrn::import($xml,$r[0], true);
@ -1378,7 +1393,7 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
dbesc(($sharing) ? NETWORK_ZOT : NETWORK_OSTATUS),
intval(($sharing) ? CONTACT_IS_SHARING : CONTACT_IS_FOLLOWER)
);
$r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 LIMIT 1",
$r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `pending` = 1 LIMIT 1",
intval($importer['uid']),
dbesc($url)
);
@ -1415,10 +1430,10 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
);
}
if(intval($r[0]['def_gid'])) {
require_once('include/group.php');
group_add_member($r[0]['uid'],'',$contact_record['id'],$r[0]['def_gid']);
}
$def_gid = get_default_group($importer['uid'], $contact_record["network"]);
if(intval($def_gid))
group_add_member($importer['uid'],'',$contact_record['id'],$def_gid);
if(($r[0]['notify-flags'] & NOTIFY_INTRO) &&
in_array($r[0]['page-flags'], array(PAGE_NORMAL))) {
@ -1648,7 +1663,6 @@ function compare_permissions($obj1,$obj2) {
// returns an array of contact-ids that are allowed to see this object
function enumerate_permissions($obj) {
require_once('include/group.php');
$allow_people = expand_acl($obj['allow_cid']);
$allow_groups = expand_groups(expand_acl($obj['allow_gid']));
$deny_people = expand_acl($obj['deny_cid']);
@ -1980,9 +1994,6 @@ function drop_item($id,$interactive = true) {
intval($r[0]['id'])
);
}
// Add a relayable_retraction signature for Diaspora.
store_diaspora_retract_sig($item, $a->user, $a->get_baseurl());
}
$drop_id = intval($item['id']);
@ -2115,51 +2126,3 @@ function posted_date_widget($url,$uid,$wall) {
));
return $o;
}
function store_diaspora_retract_sig($item, $user, $baseurl) {
// Note that we can't add a target_author_signature
// if the comment was deleted by a remote user. That should be ok, because if a remote user is deleting
// the comment, that means we're the home of the post, and Diaspora will only
// check the parent_author_signature of retractions that it doesn't have to relay further
//
// I don't think this function gets called for an "unlike," but I'll check anyway
$enabled = intval(get_config('system','diaspora_enabled'));
if(! $enabled) {
logger('drop_item: diaspora support disabled, not storing retraction signature', LOGGER_DEBUG);
return;
}
logger('drop_item: storing diaspora retraction signature');
$signed_text = $item['guid'] . ';' . ( ($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
if(local_user() == $item['uid']) {
$handle = $user['nickname'] . '@' . substr($baseurl, strpos($baseurl,'://') + 3);
$authorsig = base64_encode(rsa_sign($signed_text,$user['prvkey'],'sha256'));
}
else {
$r = q("SELECT `nick`, `url` FROM `contact` WHERE `id` = '%d' LIMIT 1",
$item['contact-id'] // If this function gets called, drop_item() has already checked remote_user() == $item['contact-id']
);
if(count($r)) {
// The below handle only works for NETWORK_DFRN. I think that's ok, because this function
// only handles DFRN deletes
$handle_baseurl_start = strpos($r['url'],'://') + 3;
$handle_baseurl_length = strpos($r['url'],'/profile') - $handle_baseurl_start;
$handle = $r['nick'] . '@' . substr($r['url'], $handle_baseurl_start, $handle_baseurl_length);
$authorsig = '';
}
}
if(isset($handle))
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
intval($item['id']),
dbesc($signed_text),
dbesc($authorsig),
dbesc($handle)
);
return;
}

View file

@ -1,4 +1,5 @@
<?php
require_once("include/diaspora.php");
/**
* @brief add/remove activity to an item
@ -151,9 +152,6 @@ function do_like($item_id, $verb) {
intval($like_item['id'])
);
// Save the author information for the unlike in case we need to relay to Diaspora
store_diaspora_like_retract_sig($activity, $item, $like_item, $contact);
$like_item_id = $like_item['id'];
proc_run('php',"include/notifier.php","like","$like_item_id");
@ -163,7 +161,7 @@ function do_like($item_id, $verb) {
$uri = item_new_uri($a->get_hostname(),$owner_uid);
$post_type = (($item['resource-id']) ? t('photo') : t('status'));
if($item['obj_type'] === ACTIVITY_OBJ_EVENT)
if($item['object-type'] === ACTIVITY_OBJ_EVENT)
$post_type = t('event');
$objtype = (($item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
$link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . '" />' . "\n") ;
@ -196,6 +194,7 @@ EOT;
$arr = array();
$arr['guid'] = get_guid(32);
$arr['uri'] = $uri;
$arr['uid'] = $owner_uid;
$arr['contact-id'] = $contact['id'];
@ -240,7 +239,7 @@ EOT;
// Save the author information for the like in case we need to relay to Diaspora
store_diaspora_like_sig($activity, $post_type, $contact, $post_id);
diaspora::store_like_signature($contact, $post_id);
$arr['id'] = $post_id;
@ -250,149 +249,3 @@ EOT;
return true;
}
function store_diaspora_like_retract_sig($activity, $item, $like_item, $contact) {
// Note that we can only create a signature for a user of the local server. We don't have
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
// means we are the relay, and for relayable_retractions, Diaspora
// only checks the parent_author_signature if it doesn't have to relay further
//
// If $item['resource-id'] exists, it means the item is a photo. Diaspora doesn't support
// likes on photos, so don't bother.
$enabled = intval(get_config('system','diaspora_enabled'));
if(! $enabled) {
logger('mod_like: diaspora support disabled, not storing like retraction signature', LOGGER_DEBUG);
return;
}
logger('mod_like: storing diaspora like retraction signature');
if(($activity === ACTIVITY_LIKE) && (! $item['resource-id'])) {
$signed_text = $like_item['guid'] . ';' . 'Like';
// Only works for NETWORK_DFRN
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
// This code could never had worked (the return values form the queries were used in a wrong way.
// Additionally it is needlessly complicated. Either the contact is owner or not. And we have this data already.
/*
// Get contact's private key if he's a user of the local Friendica server
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
dbesc($contact['url'])
);
if( $r) {
$contact_uid = $r['uid'];
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
intval($contact_uid)
);
*/
// Is the contact the owner? Then fetch the private key
if ($contact['self'] AND ($contact['uid'] > 0)) {
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
intval($contact['uid'])
);
if($r)
$authorsig = base64_encode(rsa_sign($signed_text,$r[0]['prvkey'],'sha256'));
}
if(! isset($authorsig))
$authorsig = '';
q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
intval($like_item['id']),
dbesc($signed_text),
dbesc($authorsig),
dbesc($diaspora_handle)
);
}
return;
}
function store_diaspora_like_sig($activity, $post_type, $contact, $post_id) {
// Note that we can only create a signature for a user of the local server. We don't have
// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
// means we are the relay, and for relayable_retractions, Diaspora
// only checks the parent_author_signature if it doesn't have to relay further
$enabled = intval(get_config('system','diaspora_enabled'));
if(! $enabled) {
logger('mod_like: diaspora support disabled, not storing like signature', LOGGER_DEBUG);
return;
}
logger('mod_like: storing diaspora like signature');
if(($activity === ACTIVITY_LIKE) && ($post_type === t('status'))) {
// Only works for NETWORK_DFRN
$contact_baseurl_start = strpos($contact['url'],'://') + 3;
$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
// This code could never had worked (the return values form the queries were used in a wrong way.
// Additionally it is needlessly complicated. Either the contact is owner or not. And we have this data already.
/*
// Get contact's private key if he's a user of the local Friendica server
$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
dbesc($contact['url'])
);
if( $r) {
$contact_uid = $r['uid'];
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
intval($contact_uid)
);
if( $r)
$contact_uprvkey = $r['prvkey'];
}
*/
// Is the contact the owner? Then fetch the private key
if ($contact['self'] AND ($contact['uid'] > 0)) {
$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
intval($contact['uid'])
);
if($r)
$contact_uprvkey = $r[0]['prvkey'];
}
$r = q("SELECT guid, parent FROM `item` WHERE id = %d LIMIT 1",
intval($post_id)
);
if( $r) {
$p = q("SELECT guid FROM `item` WHERE id = %d AND parent = %d LIMIT 1",
intval($r[0]['parent']),
intval($r[0]['parent'])
);
if( $p) {
$signed_text = 'true;'.$r[0]['guid'].';Post;'.$p[0]['guid'].';'.$diaspora_handle;
if(isset($contact_uprvkey))
$authorsig = base64_encode(rsa_sign($signed_text,$contact_uprvkey,'sha256'));
else
$authorsig = '';
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
intval($post_id),
dbesc($signed_text),
dbesc($authorsig),
dbesc($diaspora_handle)
);
}
}
}
return;
}

View file

@ -2,7 +2,7 @@
function nav(&$a) {
/**
/*
*
* Build page header and site navigation bars
*
@ -11,7 +11,9 @@ function nav(&$a) {
if(!(x($a->page,'nav')))
$a->page['nav'] = '';
/**
$a->page['htmlhead'] .= replace_macros(get_markup_template('nav_head.tpl'), array());
/*
* Placeholder div for popup panel
*/
@ -19,7 +21,7 @@ function nav(&$a) {
$nav_info = nav_info($a);
/**
/*
* Build the page
*/
@ -29,12 +31,13 @@ function nav(&$a) {
'$baseurl' => $a->get_baseurl(),
'$sitelocation' => $nav_info['sitelocation'],
'$nav' => $nav_info['nav'],
'$banner' => $nav_info['banner'],
'$banner' => $nav_info['banner'],
'$emptynotifications' => t('Nothing new here'),
'$userinfo' => $nav_info['userinfo'],
'$sel' => $a->nav_sel,
'$sel' => $a->nav_sel,
'$apps' => $a->apps,
'$clear_notifs' => t('Clear notifications')
'$clear_notifs' => t('Clear notifications'),
'$search_hint' => t('@name, !forum, #tags, content')
));
call_hooks('page_header', $a->page['nav']);
@ -45,7 +48,7 @@ function nav_info(&$a) {
$ssl_state = ((local_user()) ? true : false);
/**
/*
*
* Our network is distributed, and as you visit friends some of the
* sites look exactly the same - it isn't always easy to know where you are.
@ -61,7 +64,7 @@ function nav_info(&$a) {
// nav links: array of array('href', 'text', 'extra css classes', 'title')
$nav = Array();
/**
/*
* Display login or logout
*/
@ -92,7 +95,7 @@ function nav_info(&$a) {
}
/**
/*
* "Home" should also take you home from an authenticated remote profile connection
*/
@ -115,15 +118,17 @@ function nav_info(&$a) {
if(count($a->apps)>0)
$nav['apps'] = array('apps', t('Apps'), "", t('Addon applications, utilities, games'));
$nav['search'] = array('search', t('Search'), "", t('Search site content'));
if (local_user() OR !get_config('system','local_search')) {
$nav['search'] = array('search', t('Search'), "", t('Search site content'));
$nav['searchoption'] = array(
t("Full Text"),
t("Tags"),
t("Contacts"));
$nav['searchoption'] = array(
t("Full Text"),
t("Tags"),
t("Contacts"));
if (get_config('system','poco_local_search'))
$nav['searchoption'][] = t("Forums");
if (get_config('system','poco_local_search'))
$nav['searchoption'][] = t("Forums");
}
$gdirpath = 'directory';
@ -137,13 +142,14 @@ function nav_info(&$a) {
elseif(get_config('system','community_page_style') == CP_GLOBAL_COMMUNITY)
$nav['community'] = array('community', t('Community'), "", t('Conversations on the network'));
$nav['events'] = Array('events', t('Events'), "", t('Events and Calendar'));
if(local_user())
$nav['events'] = Array('events', t('Events'), "", t('Events and Calendar'));
$nav['directory'] = array($gdirpath, t('Directory'), "", t('People directory'));
$nav['about'] = Array('friendica', t('Information'), "", t('Information about this friendica instance'));
/**
/*
*
* The following nav links are only show to logged in users
*
@ -164,7 +170,7 @@ function nav_info(&$a) {
if(in_array($_SESSION['page_flags'], array(PAGE_NORMAL, PAGE_SOAPBOX, PAGE_FREELOVE))) {
$nav['notifications'] = array('notifications', t('Notifications'), "", t('Notifications'));
$nav['notifications']['all']=array('notifications/system', t('See all notifications'), "", "");
$nav['notifications']['mark'] = array('', t('Mark all system notifications seen'), '','');
$nav['notifications']['mark'] = array('', t('Mark as seen'), '',t('Mark all system notifications seen'));
}
}
@ -187,7 +193,7 @@ function nav_info(&$a) {
$nav['contacts'] = array('contacts', t('Contacts'),"", t('Manage/edit friends and contacts'));
}
/**
/*
* Admin page
*/
if (is_site_admin()){
@ -198,7 +204,7 @@ function nav_info(&$a) {
$nav['navigation'] = array('navigation/', t('Navigation'), "", t('Site map'));
/**
/*
*
* Provide a banner/logo/whatever
*
@ -221,26 +227,26 @@ function nav_info(&$a) {
}
/*
/**
* Set a menu item in navbar as selected
*
*/
function nav_set_selected($item){
$a = get_app();
$a->nav_sel = array(
$a->nav_sel = array(
'community' => null,
'network' => null,
'home' => null,
'profiles' => null,
'network' => null,
'home' => null,
'profiles' => null,
'introductions' => null,
'notifications' => null,
'messages' => null,
'directory' => null,
'settings' => null,
'contacts' => null,
'manage' => null,
'events' => null,
'register' => null,
'messages' => null,
'directory' => null,
'settings' => null,
'contacts' => null,
'manage' => null,
'events' => null,
'register' => null,
);
$a->nav_sel[$item] = 'selected';
}

View file

@ -1,12 +1,29 @@
<?php
/**
* @file include/network.php
*/
// curl wrapper. If binary flag is true, return binary
// results.
require_once("include/xml.php");
// Set the cookiejar argument to a string (e.g. "/tmp/friendica-cookies.txt")
// to preserve cookies from one request to the next.
if(! function_exists('fetch_url')) {
/**
* @brief Curl wrapper
*
* If binary flag is true, return binary results.
* Set the cookiejar argument to a string (e.g. "/tmp/friendica-cookies.txt")
* to preserve cookies from one request to the next.
*
* @param string $url URL to fetch
* @param boolean $binary default false
* TRUE if asked to return binary results (file download)
* @param integer $redirects The recursion counter for internal use - default 0
* @param integer $timeout Timeout in seconds, default system config value or 60 seconds
* @param string $accept_content supply Accept: header with 'accept_content' as the value
* @param string $cookiejar Path to cookie jar file
*
* @return string The fetched content
*/
function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0, $accept_content=Null, $cookiejar = 0) {
$ret = z_fetch_url(
@ -19,32 +36,29 @@ function fetch_url($url,$binary = false, &$redirects = 0, $timeout = 0, $accept_
));
return($ret['body']);
}}
}
if(!function_exists('z_fetch_url')){
/**
* @brief fetches an URL.
*
* @param string $url
* URL to fetch
* @param string $url URL to fetch
* @param boolean $binary default false
* TRUE if asked to return binary results (file download)
* @param int $redirects default 0
* internal use, recursion counter
* @param int $redirects The recursion counter for internal use - default 0
* @param array $opts (optional parameters) assoziative array with:
* * \b accept_content => supply Accept: header with 'accept_content' as the value
* * \b timeout => int seconds, default system config value or 60 seconds
* * \b http_auth => username:password
* * \b novalidate => do not validate SSL certs, default is to validate using our CA list
* * \b nobody => only return the header
* * \b cookiejar => path to cookie jar file
* 'accept_content' => supply Accept: header with 'accept_content' as the value
* 'timeout' => int Timeout in seconds, default system config value or 60 seconds
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
* 'nobody' => only return the header
* 'cookiejar' => path to cookie jar file
*
* @return array an assoziative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b redirect_url => in case of redirect, content was finally retrieved from this URL
* * \e string \b header => HTTP headers
* * \e string \b body => fetched content
* int 'return_code' => HTTP return code or 0 if timeout or failure
* boolean 'success' => boolean true (if HTTP 2xx result) or false
* string 'redirect_url' => in case of redirect, content was finally retrieved from this URL
* string 'header' => HTTP headers
* string 'body' => fetched content
*/
function z_fetch_url($url,$binary = false, &$redirects = 0, $opts=array()) {
@ -66,7 +80,7 @@ function z_fetch_url($url,$binary = false, &$redirects = 0, $opts=array()) {
curl_setopt($ch, CURLOPT_COOKIEFILE, $opts["cookiejar"]);
}
// These settings aren't needed. We're following the location already.
// These settings aren't needed. We're following the location already.
// @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// @curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
@ -93,6 +107,7 @@ function z_fetch_url($url,$binary = false, &$redirects = 0, $opts=array()) {
$curl_time = intval(get_config('system','curl_timeout'));
@curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
}
// by default we will allow self-signed certs
// but you can override this
@ -192,11 +207,21 @@ function z_fetch_url($url,$binary = false, &$redirects = 0, $opts=array()) {
return($ret);
}}
}
// post request to $url. $params is an array of post variables.
if(! function_exists('post_url')) {
/**
* @brief Post request to $url
*
* @param string $url URL to post
* @param mixed $params
* @param string $headers HTTP headers
* @param integer $redirects Recursion counter for internal use - default = 0
* @param integer $timeout The timeout in seconds, default system config value or 60 seconds
*
* @return string The content
*/
function post_url($url,$params, $headers = null, &$redirects = 0, $timeout = 0) {
$stamp1 = microtime(true);
@ -294,13 +319,12 @@ function post_url($url,$params, $headers = null, &$redirects = 0, $timeout = 0)
logger("post_url: end ".$url, LOGGER_DATA);
return($body);
}}
}
// Generic XML return
// Outputs a basic dfrn XML status structure to STDOUT, with a <status> variable
// of $st and an optional text <message> of $message and terminates the current process.
if(! function_exists('xml_status')) {
function xml_status($st, $message = '') {
$xml_message = ((strlen($message)) ? "\t<message>" . xmlify($message) . "</message>\r\n" : '');
@ -312,12 +336,20 @@ function xml_status($st, $message = '') {
echo '<?xml version="1.0" encoding="UTF-8"?>'."\r\n";
echo "<result>\r\n\t<status>$st</status>\r\n$xml_message</result>\r\n";
killme();
}}
}
if(! function_exists('http_status_exit')) {
/**
* @brief Send HTTP status header and exit.
*
* @param integer $val HTTP status result value
* @param array $description optional message
* 'title' => header title
* 'description' => optional message
*/
function http_status_exit($val, $description = array()) {
$err = '';
$err = '';
if($val >= 400) {
$err = 'Error';
if (!isset($description["title"]))
@ -337,59 +369,13 @@ function http_status_exit($val, $description = array()) {
killme();
}}
// convert an XML document to a normalised, case-corrected array
// used by webfinger
if(! function_exists('convert_xml_element_to_array')) {
function convert_xml_element_to_array($xml_element, &$recursion_depth=0) {
// If we're getting too deep, bail out
if ($recursion_depth > 512) {
return(null);
}
if (!is_string($xml_element) &&
!is_array($xml_element) &&
(get_class($xml_element) == 'SimpleXMLElement')) {
$xml_element_copy = $xml_element;
$xml_element = get_object_vars($xml_element);
}
if (is_array($xml_element)) {
$result_array = array();
if (count($xml_element) <= 0) {
return (trim(strval($xml_element_copy)));
}
foreach($xml_element as $key=>$value) {
$recursion_depth++;
$result_array[strtolower($key)] =
convert_xml_element_to_array($value, $recursion_depth);
$recursion_depth--;
}
if ($recursion_depth == 0) {
$temp_array = $result_array;
$result_array = array(
strtolower($xml_element_copy->getName()) => $temp_array,
);
}
return ($result_array);
} else {
return (trim(strval($xml_element)));
}
}}
}
// Given an email style address, perform webfinger lookup and
// return the resulting DFRN profile URL, or if no DFRN profile URL
// is located, returns an OStatus subscription template (prefixed
// with the string 'stat:' to identify it as on OStatus template).
// If this isn't an email style address just return $s.
// If this isn't an email style address just return $webbie.
// Return an empty string if email-style addresses but webfinger fails,
// or if the resultant personal XRD doesn't contain a supported
// subscription/friend-request attribute.
@ -397,15 +383,14 @@ function convert_xml_element_to_array($xml_element, &$recursion_depth=0) {
// amended 7/9/2011 to return an hcard which could save potentially loading
// a lengthy content page to scrape dfrn attributes
if(! function_exists('webfinger_dfrn')) {
function webfinger_dfrn($s,&$hcard) {
if(! strstr($s,'@')) {
return $s;
function webfinger_dfrn($webbie,&$hcard) {
if(! strstr($webbie,'@')) {
return $webbie;
}
$profile_link = '';
$links = webfinger($s);
logger('webfinger_dfrn: ' . $s . ':' . print_r($links,true), LOGGER_DATA);
$links = webfinger($webbie);
logger('webfinger_dfrn: ' . $webbie . ':' . print_r($links,true), LOGGER_DATA);
if(count($links)) {
foreach($links as $link) {
if($link['@attributes']['rel'] === NAMESPACE_DFRN)
@ -417,29 +402,32 @@ function webfinger_dfrn($s,&$hcard) {
}
}
return $profile_link;
}}
}
// Given an email style address, perform webfinger lookup and
// return the array of link attributes from the personal XRD file.
// On error/failure return an empty array.
if(! function_exists('webfinger')) {
function webfinger($s, $debug = false) {
/**
* @brief Perform webfinger lookup on an email style address
*
* @param string $webbi An email style address
* @param boolean $debug
*
* @return array of link attributes from the personal XRD file
* empty array on error/failure
*/
function webfinger($webbie, $debug = false) {
$host = '';
if(strstr($s,'@')) {
$host = substr($s,strpos($s,'@') + 1);
if(strstr($webbie,'@')) {
$host = substr($webbie,strpos($webbie,'@') + 1);
}
if(strlen($host)) {
$tpl = fetch_lrdd_template($host);
logger('webfinger: lrdd template: ' . $tpl);
if(strlen($tpl)) {
$pxrd = str_replace('{uri}', urlencode('acct:' . $s), $tpl);
$pxrd = str_replace('{uri}', urlencode('acct:' . $webbie), $tpl);
logger('webfinger: pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
if(! count($links)) {
// try with double slashes
$pxrd = str_replace('{uri}', urlencode('acct://' . $s), $tpl);
$pxrd = str_replace('{uri}', urlencode('acct://' . $webbie), $tpl);
logger('webfinger: pxrd: ' . $pxrd);
$links = fetch_xrd_links($pxrd);
}
@ -447,9 +435,8 @@ function webfinger($s, $debug = false) {
}
}
return array();
}}
}
if(! function_exists('lrdd')) {
function lrdd($uri, $debug = false) {
$a = get_app();
@ -494,7 +481,7 @@ function lrdd($uri, $debug = false) {
if(! $h)
return array();
$arr = convert_xml_element_to_array($h);
$arr = xml::element_to_array($h);
if(isset($arr['xrd']['property'])) {
$property = $arr['crd']['property'];
@ -618,15 +605,12 @@ function lrdd($uri, $debug = false) {
return array();
}}
}
// Given a host name, locate the LRDD template from that
// host. Returns the LRDD template or an empty string on
// error/failure.
if(! function_exists('fetch_lrdd_template')) {
function fetch_lrdd_template($host) {
$tpl = '';
@ -648,13 +632,15 @@ function fetch_lrdd_template($host) {
if(! strpos($tpl,'{uri}'))
$tpl = '';
return $tpl;
}}
}
// Given a URL, retrieve the page as an XRD document.
// Return an array of links.
// on error/failure return empty array.
if(! function_exists('fetch_xrd_links')) {
/**
* @brief Given a URL, retrieve the page as an XRD document.
*
* @param string $url An url
* @return array of links
* return empty array on error/failure
*/
function fetch_xrd_links($url) {
$xrd_timeout = intval(get_config('system','xrd_timeout'));
@ -673,7 +659,7 @@ function fetch_xrd_links($url) {
if(! $h)
return array();
$arr = convert_xml_element_to_array($h);
$arr = xml::element_to_array($h);
$links = array();
@ -701,14 +687,17 @@ function fetch_xrd_links($url) {
return $links;
}}
}
// Take a URL from the wild, prepend http:// if necessary
// and check DNS to see if it's real (or check if is a valid IP address)
// return true if it's OK, false if something is wrong with it
if(! function_exists('validate_url')) {
/**
* @brief Check URL to se if ts's real
*
* Take a URL from the wild, prepend http:// if necessary
* and check DNS to see if it's real (or check if is a valid IP address)
*
* @param string $url The URL to be validated
* @return boolean True if it's a valid URL, fals if something wrong with it
*/
function validate_url(&$url) {
if(get_config('system','disable_url_validation'))
@ -724,11 +713,14 @@ function validate_url(&$url) {
return true;
}
return false;
}}
}
// checks that email is an actual resolvable internet address
if(! function_exists('validate_email')) {
/**
* @brief Checks that email is an actual resolvable internet address
*
* @param string $addr The email address
* @return boolean True if it's a valid email address, false if it's not
*/
function validate_email($addr) {
if(get_config('system','disable_email_validation'))
@ -742,14 +734,17 @@ function validate_email($addr) {
return true;
}
return false;
}}
}
// Check $url against our list of allowed sites,
// wildcards allowed. If allowed_sites is unset return true;
// If url is allowed, return true.
// otherwise, return false
if(! function_exists('allowed_url')) {
/**
* @brief Check if URL is allowed
*
* Check $url against our list of allowed sites,
* wildcards allowed. If allowed_sites is unset return true;
*
* @param string $url URL which get tested
* @return boolean True if url is allowed otherwise return false
*/
function allowed_url($url) {
$h = @parse_url($url);
@ -784,14 +779,17 @@ function allowed_url($url) {
}
}
return $found;
}}
}
// check if email address is allowed to register here.
// Compare against our list (wildcards allowed).
// Returns false if not allowed, true if allowed or if
// allowed list is not configured.
if(! function_exists('allowed_email')) {
/**
* @brief Check if email address is allowed to register here.
*
* Compare against our list (wildcards allowed).
*
* @param type $email
* @return boolean False if not allowed, true if allowed
* or if allowed list is not configured
*/
function allowed_email($email) {
@ -818,10 +816,8 @@ function allowed_email($email) {
}
}
return $found;
}}
}
if(! function_exists('avatar_img')) {
function avatar_img($email) {
$a = get_app();
@ -838,11 +834,11 @@ function avatar_img($email) {
logger('Avatar: ' . $avatar['email'] . ' ' . $avatar['url'], LOGGER_DEBUG);
return $avatar['url'];
}}
}
if(! function_exists('parse_xml_string')) {
function parse_xml_string($s,$strict = true) {
/// @todo Move this function to the xml class
if($strict) {
if(! strstr($s,'<?xml'))
return false;
@ -860,66 +856,8 @@ function parse_xml_string($s,$strict = true) {
libxml_clear_errors();
}
return $x;
}}
function add_fcontact($arr,$update = false) {
if($update) {
$r = q("UPDATE `fcontact` SET
`name` = '%s',
`photo` = '%s',
`request` = '%s',
`nick` = '%s',
`addr` = '%s',
`batch` = '%s',
`notify` = '%s',
`poll` = '%s',
`confirm` = '%s',
`alias` = '%s',
`pubkey` = '%s',
`updated` = '%s'
WHERE `url` = '%s' AND `network` = '%s'",
dbesc($arr['name']),
dbesc($arr['photo']),
dbesc($arr['request']),
dbesc($arr['nick']),
dbesc($arr['addr']),
dbesc($arr['batch']),
dbesc($arr['notify']),
dbesc($arr['poll']),
dbesc($arr['confirm']),
dbesc($arr['alias']),
dbesc($arr['pubkey']),
dbesc(datetime_convert()),
dbesc($arr['url']),
dbesc($arr['network'])
);
}
else {
$r = q("insert into fcontact ( `url`,`name`,`photo`,`request`,`nick`,`addr`,
`batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated` )
values('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
dbesc($arr['url']),
dbesc($arr['name']),
dbesc($arr['photo']),
dbesc($arr['request']),
dbesc($arr['nick']),
dbesc($arr['addr']),
dbesc($arr['batch']),
dbesc($arr['notify']),
dbesc($arr['poll']),
dbesc($arr['confirm']),
dbesc($arr['network']),
dbesc($arr['alias']),
dbesc($arr['pubkey']),
dbesc(datetime_convert())
);
}
return $r;
}
function scale_external_images($srctext, $include_link = true, $scale_replace = false) {
// Suppress "view full size"
@ -1030,171 +968,6 @@ function fix_contact_ssl_policy(&$contact,$new_policy) {
}
}
/**
* xml2array() will convert the given XML text to an array in the XML structure.
* Link: http://www.bin-co.com/php/scripts/xml2array/
* Portions significantly re-written by mike@macgirvin.com for Friendica (namespaces, lowercase tags, get_attribute default changed, more...)
* Arguments : $contents - The XML text
* $namespaces - true or false include namespace information in the returned array as array elements.
* $get_attributes - 1 or 0. If this is 1 the function will get the attributes as well as the tag values - this results in a different array structure in the return value.
* $priority - Can be 'tag' or 'attribute'. This will change the way the resulting array sturcture. For 'tag', the tags are given more importance.
* Return: The parsed XML in an array form. Use print_r() to see the resulting array structure.
* Examples: $array = xml2array(file_get_contents('feed.xml'));
* $array = xml2array(file_get_contents('feed.xml', true, 1, 'attribute'));
*/
function xml2array($contents, $namespaces = true, $get_attributes=1, $priority = 'attribute') {
if(!$contents) return array();
if(!function_exists('xml_parser_create')) {
logger('xml2array: parser function missing');
return array();
}
libxml_use_internal_errors(true);
libxml_clear_errors();
if($namespaces)
$parser = @xml_parser_create_ns("UTF-8",':');
else
$parser = @xml_parser_create();
if(! $parser) {
logger('xml2array: xml_parser_create: no resource');
return array();
}
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
// http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
@xml_parse_into_struct($parser, trim($contents), $xml_values);
@xml_parser_free($parser);
if(! $xml_values) {
logger('xml2array: libxml: parse error: ' . $contents, LOGGER_DATA);
foreach(libxml_get_errors() as $err)
logger('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message, LOGGER_DATA);
libxml_clear_errors();
return;
}
//Initializations
$xml_array = array();
$parents = array();
$opened_tags = array();
$arr = array();
$current = &$xml_array; // Reference
// Go through the tags.
$repeated_tag_index = array(); // Multiple tags with same name will be turned into an array
foreach($xml_values as $data) {
unset($attributes,$value); // Remove existing values, or there will be trouble
// This command will extract these variables into the foreach scope
// tag(string), type(string), level(int), attributes(array).
extract($data); // We could use the array by itself, but this cooler.
$result = array();
$attributes_data = array();
if(isset($value)) {
if($priority == 'tag') $result = $value;
else $result['value'] = $value; // Put the value in a assoc array if we are in the 'Attribute' mode
}
//Set the attributes too.
if(isset($attributes) and $get_attributes) {
foreach($attributes as $attr => $val) {
if($priority == 'tag') $attributes_data[$attr] = $val;
else $result['@attributes'][$attr] = $val; // Set all the attributes in a array called 'attr'
}
}
// See tag status and do the needed.
if($namespaces && strpos($tag,':')) {
$namespc = substr($tag,0,strrpos($tag,':'));
$tag = strtolower(substr($tag,strlen($namespc)+1));
$result['@namespace'] = $namespc;
}
$tag = strtolower($tag);
if($type == "open") { // The starting of the tag '<tag>'
$parent[$level-1] = &$current;
if(!is_array($current) or (!in_array($tag, array_keys($current)))) { // Insert New tag
$current[$tag] = $result;
if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
$repeated_tag_index[$tag.'_'.$level] = 1;
$current = &$current[$tag];
} else { // There was another element with the same tag name
if(isset($current[$tag][0])) { // If there is a 0th element it is already an array
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
$repeated_tag_index[$tag.'_'.$level]++;
} else { // This section will make the value an array if multiple tags with the same name appear together
$current[$tag] = array($current[$tag],$result); // This will combine the existing item and the new item together to make an array
$repeated_tag_index[$tag.'_'.$level] = 2;
if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
unset($current[$tag.'_attr']);
}
}
$last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;
$current = &$current[$tag][$last_item_index];
}
} elseif($type == "complete") { // Tags that ends in 1 line '<tag />'
//See if the key is already taken.
if(!isset($current[$tag])) { //New Key
$current[$tag] = $result;
$repeated_tag_index[$tag.'_'.$level] = 1;
if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;
} else { // If taken, put all things inside a list(array)
if(isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array...
// ...push the new element into that array.
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
if($priority == 'tag' and $get_attributes and $attributes_data) {
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
}
$repeated_tag_index[$tag.'_'.$level]++;
} else { // If it is not an array...
$current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
$repeated_tag_index[$tag.'_'.$level] = 1;
if($priority == 'tag' and $get_attributes) {
if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
unset($current[$tag.'_attr']);
}
if($attributes_data) {
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
}
}
$repeated_tag_index[$tag.'_'.$level]++; // 0 and 1 indexes are already taken
}
}
} elseif($type == 'close') { // End of tag '</tag>'
$current = &$parent[$level-1];
}
}
return($xml_array);
}
function original_url($url, $depth=1, $fetchbody = false) {
$a = get_app();
@ -1321,7 +1094,6 @@ function original_url($url, $depth=1, $fetchbody = false) {
return($url);
}
if (!function_exists('short_link')) {
function short_link($url) {
require_once('library/slinky.php');
$slinky = new Slinky($url);
@ -1343,4 +1115,19 @@ function short_link($url) {
$slinky->set_cascade(array(new Slinky_UR1ca(), new Slinky_Trim(), new Slinky_IsGd(), new Slinky_TinyURL()));
}
return $slinky->short();
}};
}
/**
* @brief Encodes content to json
*
* This function encodes an array to json format
* and adds an application/json HTTP header to the output.
* After finishing the process is getting killed.
*
* @param array $x The input content
*/
function json_return_and_die($x) {
header("content-type: application/json");
echo json_encode($x);
killme();
}

View file

@ -223,13 +223,13 @@ function notifier_run(&$argv, &$argc){
if(! ($mail || $fsuggest || $relocate)) {
$slap = ostatus_salmon($target_item,$owner);
$slap = ostatus::salmon($target_item,$owner);
require_once('include/group.php');
$parent = $items[0];
$thr_parent = q("SELECT `network` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
$thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
dbesc($target_item["thr-parent"]), intval($target_item["uid"]));
logger('Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG);
@ -390,6 +390,20 @@ function notifier_run(&$argv, &$argc){
logger('Some parent is OStatus for '.$target_item["guid"], LOGGER_DEBUG);
// Send a salmon to the parent author
$probed_contact = probe_url($thr_parent[0]['author-link']);
if ($probed_contact["notify"] != "") {
logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
}
// Send a salmon to the parent owner
$probed_contact = probe_url($thr_parent[0]['owner-link']);
if ($probed_contact["notify"] != "") {
logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
}
// Send a salmon notification to every person we mentioned in the post
$arr = explode(',',$target_item['tag']);
foreach($arr as $x) {
@ -535,8 +549,8 @@ function notifier_run(&$argv, &$argc){
if($public_message) {
if (!$followup AND $top_level)
$r0 = diaspora_fetch_relay();
if (!$followup)
$r0 = diaspora::relay_list();
else
$r0 = array();
@ -628,13 +642,6 @@ function notifier_run(&$argv, &$argc){
proc_run('php','include/pubsubpublish.php');
}
// If the item was deleted, clean up the `sign` table
if($target_item['deleted']) {
$r = q("DELETE FROM sign where `retract_iid` = %d",
intval($target_item['id'])
);
}
logger('notifier: calling hooks', LOGGER_DEBUG);
if($normal_mode)

View file

@ -75,10 +75,13 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){
else { //save in cache
$j = json_decode($txt);
if ($j->type != "error")
q("INSERT INTO `oembed` (`url`, `content`, `created`) VALUES ('%s', '%s', '%s')",
dbesc(normalise_link($embedurl)), dbesc($txt), dbesc(datetime_convert()));
q("INSERT INTO `oembed` (`url`, `content`, `created`) VALUES ('%s', '%s', '%s')
ON DUPLICATE KEY UPDATE `content` = '%s', `created` = '%s'",
dbesc(normalise_link($embedurl)),
dbesc($txt), dbesc(datetime_convert()),
dbesc($txt), dbesc(datetime_convert()));
Cache::set($a->videowidth . $embedurl,$txt, CACHE_DAY);
Cache::set($a->videowidth.$embedurl,$txt, CACHE_DAY);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,20 +1,27 @@
<?php
function get_attached_data($body) {
/*
- text:
- type: link, video, photo
- title:
- url:
- image:
- description:
- (thumbnail)
*/
require_once("include/Photo.php");
/**
* @brief Fetches attachment data that were generated the old way
*
* @param string $body Message body
* @return array
* 'type' -> Message type ("link", "video", "photo")
* 'text' -> Text before the shared message
* 'after' -> Text after the shared message
* 'image' -> Preview image of the message
* 'url' -> Url to the attached message
* 'title' -> Title of the attachment
* 'description' -> Description of the attachment
*/
function get_old_attachment_data($body) {
$post = array();
// Simplify image codes
$body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
$post = array();
if (preg_match_all("(\[class=(.*?)\](.*?)\[\/class\])ism",$body, $attached, PREG_SET_ORDER)) {
foreach ($attached AS $data) {
if (!in_array($data[1], array("type-link", "type-video", "type-photo")))
@ -22,14 +29,26 @@ function get_attached_data($body) {
$post["type"] = substr($data[1], 5);
$post["text"] = trim(str_replace($data[0], "", $body));
$pos = strpos($body, $data[0]);
if ($pos > 0) {
$post["text"] = trim(substr($body, 0, $pos));
$post["after"] = trim(substr($body, $pos + strlen($data[0])));
} else
$post["text"] = trim(str_replace($data[0], "", $body));
$attacheddata = $data[2];
$URLSearchString = "^\[\]";
if (preg_match("/\[img\]([$URLSearchString]*)\[\/img\]/ism", $attacheddata, $matches))
$post["image"] = $matches[1];
if (preg_match("/\[img\]([$URLSearchString]*)\[\/img\]/ism", $attacheddata, $matches)) {
$picturedata = get_photo_info($matches[1]);
if (($picturedata[0] >= 500) AND ($picturedata[0] >= $picturedata[1]))
$post["image"] = $matches[1];
else
$post["preview"] = $matches[1];
}
if (preg_match("/\[bookmark\=([$URLSearchString]*)\](.*?)\[\/bookmark\]/ism", $attacheddata, $matches)) {
$post["url"] = $matches[1];
@ -43,6 +62,123 @@ function get_attached_data($body) {
}
}
return $post;
}
/**
* @brief Fetches attachment data that were generated with the "attachment" element
*
* @param string $body Message body
* @return array
* 'type' -> Message type ("link", "video", "photo")
* 'text' -> Text before the shared message
* 'after' -> Text after the shared message
* 'image' -> Preview image of the message
* 'url' -> Url to the attached message
* 'title' -> Title of the attachment
* 'description' -> Description of the attachment
*/
function get_attachment_data($body) {
$data = array();
if (!preg_match("/(.*)\[attachment(.*)\](.*?)\[\/attachment\](.*)/ism", $body, $match))
return get_old_attachment_data($body);
$attributes = $match[2];
$data["text"] = trim($match[1]);
$type = "";
preg_match("/type='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$type = strtolower($matches[1]);
preg_match('/type="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$type = strtolower($matches[1]);
if ($type == "")
return(array());
if (!in_array($type, array("link", "audio", "photo", "video")))
return(array());
if ($type != "")
$data["type"] = $type;
$url = "";
preg_match("/url='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$url = $matches[1];
preg_match('/url="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$url = $matches[1];
if ($url != "")
$data["url"] = html_entity_decode($url, ENT_QUOTES, 'UTF-8');
$title = "";
preg_match("/title='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$title = $matches[1];
preg_match('/title="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$title = $matches[1];
if ($title != "") {
$title = bbcode(html_entity_decode($title, ENT_QUOTES, 'UTF-8'), false, false, true);
$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
$title = str_replace(array("[", "]"), array("&#91;", "&#93;"), $title);
$data["title"] = $title;
}
$image = "";
preg_match("/image='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$image = $matches[1];
preg_match('/image="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$image = $matches[1];
if ($image != "")
$data["image"] = html_entity_decode($image, ENT_QUOTES, 'UTF-8');
$preview = "";
preg_match("/preview='(.*?)'/ism", $attributes, $matches);
if ($matches[1] != "")
$preview = $matches[1];
preg_match('/preview="(.*?)"/ism', $attributes, $matches);
if ($matches[1] != "")
$preview = $matches[1];
if ($preview != "")
$data["preview"] = html_entity_decode($preview, ENT_QUOTES, 'UTF-8');
$data["description"] = trim($match[3]);
$data["after"] = trim($match[4]);
return($data);
}
function get_attached_data($body) {
/*
- text:
- type: link, video, photo
- title:
- url:
- image:
- description:
- (thumbnail)
*/
$post = get_attachment_data($body);
// if nothing is found, it maybe having an image.
if (!isset($post["type"])) {
require_once("mod/parse_url.php");
@ -53,6 +189,13 @@ function get_attached_data($body) {
if (count($pictures) == 1) {
// Checking, if the link goes to a picture
$data = parseurl_getsiteinfo_cached($pictures[0][1], true);
// Workaround:
// Sometimes photo posts to the own album are not detected at the start.
// So we seem to cannot use the cache for these cases. That's strange.
if (($data["type"] != "photo") AND strstr($pictures[0][1], "/photos/"))
$data = parseurl_getsiteinfo($pictures[0][1], true);
if ($data["type"] == "photo") {
$post["type"] = "photo";
if (isset($data["images"][0])) {
@ -207,7 +350,7 @@ function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2, $t
}
}
$html = bbcode($post["text"], false, false, $htmlmode);
$html = bbcode($post["text"].$post["after"], false, false, $htmlmode);
$msg = html2plain($html, 0, true);
$msg = trim(html_entity_decode($msg,ENT_QUOTES,'UTF-8'));

View file

@ -11,6 +11,7 @@ if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
}
require_once("boot.php");
require_once("dbm.php");
function poller_run(&$argv, &$argc){
global $a, $db;
@ -26,6 +27,20 @@ function poller_run(&$argv, &$argc){
unset($db_host, $db_user, $db_pass, $db_data);
};
$max_processes = get_config('system', 'max_processes_backend');
if (intval($max_processes) == 0)
$max_processes = 5;
$processlist = dbm::processlist();
if ($processlist["list"] != "") {
logger("Processcheck: Processes: ".$processlist["amount"]." - Processlist: ".$processlist["list"], LOGGER_DEBUG);
if ($processlist["amount"] > $max_processes) {
logger("Processcheck: Maximum number of processes for backend tasks (".$max_processes.") reached.", LOGGER_DEBUG);
return;
}
}
if (poller_max_connections_reached())
return;
@ -59,6 +74,17 @@ function poller_run(&$argv, &$argc){
while ($r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `created` LIMIT 1")) {
// Log the type of database processes
$processlist = dbm::processlist();
if ($processlist["amount"] != "") {
logger("Processcheck: Processes: ".$processlist["amount"]." - Processlist: ".$processlist["list"], LOGGER_DEBUG);
if ($processlist["amount"] > $max_processes) {
logger("Processcheck: Maximum number of processes for backend tasks (".$max_processes.") reached.", LOGGER_DEBUG);
return;
}
}
// Constantly check the number of available database connections to let the frontend be accessible at any time
if (poller_max_connections_reached())
return;
@ -125,6 +151,11 @@ function poller_max_connections_reached() {
// Fetch the max value from the config. This is needed when the system cannot detect the correct value by itself.
$max = get_config("system", "max_connections");
// Fetch the percentage level where the poller will get active
$maxlevel = get_config("system", "max_connections_level");
if ($maxlevel == 0)
$maxlevel = 75;
if ($max == 0) {
// the maximum number of possible user connections can be a system variable
$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_user_connections'");
@ -153,10 +184,10 @@ function poller_max_connections_reached() {
logger("Connection usage (user values): ".$used."/".$max, LOGGER_DEBUG);
$level = $used / $max;
$level = ($used / $max) * 100;
if ($level >= (3/4)) {
logger("Maximum level (3/4) of user connections reached: ".$used."/".$max);
if ($level >= $maxlevel) {
logger("Maximum level (".$maxlevel."%) of user connections reached: ".$used."/".$max);
return true;
}
}
@ -181,12 +212,12 @@ function poller_max_connections_reached() {
logger("Connection usage (system values): ".$used."/".$max, LOGGER_DEBUG);
$level = $used / $max;
$level = $used / $max * 100;
if ($level < (3/4))
if ($level < $maxlevel)
return false;
logger("Maximum level (3/4) of system connections reached: ".$used."/".$max);
logger("Maximum level (".$level."%) of system connections reached: ".$used."/".$max);
return true;
}

141
include/post_update.php Normal file
View file

@ -0,0 +1,141 @@
<?php
/**
* @file include/post_update.php
*/
/**
* @brief Calls the post update functions
*/
function post_update() {
if (!post_update_1192())
return;
if (!post_update_1194())
return;
}
/**
* @brief set the gcontact-id in all item entries
*
* This job has to be started multiple times until all entries are set.
* It isn't started in the update function since it would consume too much time and can be done in the background.
*
* @return bool "true" when the job is done
*/
function post_update_1192() {
// Was the script completed?
if (get_config("system", "post_update_version") >= 1192)
return true;
// Check if the first step is done (Setting "gcontact-id" in the item table)
$r = q("SELECT `author-link`, `author-name`, `author-avatar`, `uid`, `network` FROM `item` WHERE `gcontact-id` = 0 LIMIT 1000");
if (!$r) {
// Are there unfinished entries in the thread table?
$r = q("SELECT COUNT(*) AS `total` FROM `thread`
INNER JOIN `item` ON `item`.`id` =`thread`.`iid`
WHERE `thread`.`gcontact-id` = 0 AND
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
if ($r AND ($r[0]["total"] == 0)) {
set_config("system", "post_update_version", 1192);
return true;
}
// Update the thread table from the item table
q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid`
SET `thread`.`gcontact-id` = `item`.`gcontact-id`
WHERE `thread`.`gcontact-id` = 0 AND
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
return false;
}
$item_arr = array();
foreach ($r AS $item) {
$index = $item["author-link"]."-".$item["uid"];
$item_arr[$index] = array("author-link" => $item["author-link"],
"uid" => $item["uid"],
"network" => $item["network"]);
}
// Set the "gcontact-id" in the item table and add a new gcontact entry if needed
foreach($item_arr AS $item) {
$gcontact_id = get_gcontact_id(array("url" => $item['author-link'], "network" => $item['network'],
"photo" => $item['author-avatar'], "name" => $item['author-name']));
q("UPDATE `item` SET `gcontact-id` = %d WHERE `uid` = %d AND `author-link` = '%s' AND `gcontact-id` = 0",
intval($gcontact_id), intval($item["uid"]), dbesc($item["author-link"]));
}
return false;
}
/**
* @brief Updates the "global" field in the item table
*
* @return bool "true" when the job is done
*/
function post_update_1194() {
// Was the script completed?
if (get_config("system", "post_update_version") >= 1194)
return true;
logger("Start", LOGGER_DEBUG);
$end_id = get_config("system", "post_update_1194_end");
if (!$end_id) {
$r = q("SELECT `id` FROM `item` WHERE `uid` != 0 ORDER BY `id` DESC LIMIT 1");
if ($r) {
set_config("system", "post_update_1194_end", $r[0]["id"]);
$end_id = get_config("system", "post_update_1194_end");
}
}
logger("End ID: ".$end_id, LOGGER_DEBUG);
$start_id = get_config("system", "post_update_1194_start");
$query1 = "SELECT `item`.`id` FROM `item` ";
$query2 = "INNER JOIN `item` AS `shadow` ON `item`.`uri` = `shadow`.`uri` AND `shadow`.`uid` = 0 ";
$query3 = "WHERE `item`.`uid` != 0 AND `item`.`id` >= %d AND `item`.`id` <= %d
AND `item`.`visible` AND NOT `item`.`private`
AND NOT `item`.`deleted` AND NOT `item`.`moderated`
AND `item`.`network` IN ('%s', '%s', '%s', '')
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND NOT `item`.`global`";
$r = q($query1.$query2.$query3." ORDER BY `item`.`id` LIMIT 1",
intval($start_id), intval($end_id),
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
if (!$r) {
set_config("system", "post_update_version", 1194);
logger("Update is done", LOGGER_DEBUG);
return true;
} else {
set_config("system", "post_update_1194_start", $r[0]["id"]);
$start_id = get_config("system", "post_update_1194_start");
}
logger("Start ID: ".$start_id, LOGGER_DEBUG);
$r = q($query1.$query2.$query3." ORDER BY `item`.`id` LIMIT 1000,1",
intval($start_id), intval($end_id),
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
if ($r)
$pos_id = $r[0]["id"];
else
$pos_id = $end_id;
logger("Progress: Start: ".$start_id." position: ".$pos_id." end: ".$end_id, LOGGER_DEBUG);
$r = q("UPDATE `item` ".$query2." SET `item`.`global` = 1 ".$query3,
intval($start_id), intval($pos_id),
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
logger("Done", LOGGER_DEBUG);
}
?>

View file

@ -1,96 +1,6 @@
<?php
require_once('include/datetime.php');
require_once('include/diaspora.php');
require_once('include/queue_fn.php');
require_once('include/Contact.php');
function profile_change() {
$a = get_app();
if(! local_user())
return;
// $url = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
// 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'
AND `uid` = %d AND `rel` != %d ",
dbesc(NETWORK_DIASPORA),
intval(local_user()),
intval(CONTACT_IS_SHARING)
);
if(! count($recips))
return;
$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.* FROM `profile`
INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
WHERE `user`.`uid` = %d AND `profile`.`is-default` = 1 LIMIT 1",
intval(local_user())
);
if(! count($r))
return;
$profile = $r[0];
$handle = xmlify($a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3));
$first = xmlify(((strpos($profile['name'],' '))
? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']));
$last = xmlify((($first === $profile['name']) ? '' : trim(substr($profile['name'],strlen($first)))));
$large = xmlify($a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg');
$medium = xmlify($a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg');
$small = xmlify($a->get_baseurl() . '/photo/custom/50/' . $profile['uid'] . '.jpg');
$searchable = xmlify((($profile['publish'] && $profile['net-publish']) ? 'true' : 'false' ));
// $searchable = 'true';
if($searchable === 'true') {
$dob = '1000-00-00';
if(($profile['dob']) && ($profile['dob'] != '0000-00-00'))
$dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') . '-' . datetime_convert('UTC','UTC',$profile['dob'],'m-d');
$gender = xmlify($profile['gender']);
$about = xmlify($profile['about']);
require_once('include/bbcode.php');
$about = xmlify(strip_tags(bbcode($about)));
$location = formatted_location($profile);
$location = xmlify($location);
$tags = '';
if($profile['pub_keywords']) {
$kw = str_replace(',',' ',$profile['pub_keywords']);
$kw = str_replace(' ',' ',$kw);
$arr = explode(' ',$profile['pub_keywords']);
if(count($arr)) {
for($x = 0; $x < 5; $x ++) {
if(trim($arr[$x]))
$tags .= '#' . trim($arr[$x]) . ' ';
}
}
}
$tags = xmlify(trim($tags));
}
$tpl = get_markup_template('diaspora_profile.tpl');
$msg = replace_macros($tpl,array(
'$handle' => $handle,
'$first' => $first,
'$last' => $last,
'$large' => $large,
'$medium' => $medium,
'$small' => $small,
'$dob' => $dob,
'$gender' => $gender,
'$about' => $about,
'$location' => $location,
'$searchable' => $searchable,
'$tags' => $tags
));
logger('profile_change: ' . $msg, LOGGER_ALL);
foreach($recips as $recip) {
$msgtosend = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$a->user,$recip,$a->user['prvkey'],$recip['pubkey'],false)));
add_to_queue($recip['id'],NETWORK_DIASPORA,$msgtosend,false);
}
diaspora::send_profile(local_user());
}

View file

@ -16,7 +16,7 @@ function handle_pubsubhubbub() {
logger("Generate feed for user ".$rr['nickname']." - last updated ".$rr['last_update'], LOGGER_DEBUG);
$params = ostatus_feed($a, $rr['nickname'], $rr['last_update']);
$params = ostatus::feed($a, $rr['nickname'], $rr['last_update']);
$hmac_sig = hash_hmac("sha1", $params, $rr['secret']);
$headers = array("Content-type: application/atom+xml",

View file

@ -193,7 +193,7 @@ function queue_run(&$argv, &$argc){
case NETWORK_DIASPORA:
if($contact['notify']) {
logger('queue: diaspora_delivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
$deliver_status = diaspora_transmit($owner,$contact,$data,$public,true);
$deliver_status = diaspora::transmit($owner,$contact,$data,$public,true);
if($deliver_status == (-1)) {
update_queue_time($q_item['id']);

View file

@ -69,7 +69,6 @@ function ref_session_destroy ($id) {
if(! function_exists('ref_session_gc')) {
function ref_session_gc($expire) {
q("DELETE FROM `session` WHERE `expire` < %d", dbesc(time()));
q("OPTIMIZE TABLE `sess_data`");
return true;
}}

View file

@ -174,8 +174,6 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$gcid = "";
$alternate = poco_alternate_ostatus_url($profile_url);
if ($profile_url == "")
return $gcid;
@ -187,13 +185,19 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
"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)
$network = "";
// Assure that there are no parameter fragments in the profile url
if (in_array($network, array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")))
$profile_url = clean_contact_url($profile_url);
$alternate = poco_alternate_ostatus_url($profile_url);
$orig_updated = $updated;
// The global contacts should contain the original picture, not the cached one
if (($generation != 1) AND stristr(normalise_link($profile_photo), normalise_link($a->get_baseurl()."/photo/")))
$profile_photo = "";
@ -400,6 +404,11 @@ function poco_last_updated($profile, $force = false) {
else
$server_url = poco_detect_server($profile);
if (!in_array($gcontacts[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_FEED, NETWORK_OSTATUS, ""))) {
logger("Profile ".$profile.": Network type ".$gcontacts[0]["network"]." can't be checked", LOGGER_DEBUG);
return false;
}
if ($server_url != "") {
if (!poco_check_server($server_url, $gcontacts[0]["network"], $force)) {
@ -407,6 +416,7 @@ function poco_last_updated($profile, $force = false) {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
logger("Profile ".$profile.": Server ".$server_url." wasn't reachable.", LOGGER_DEBUG);
return false;
}
@ -422,7 +432,7 @@ function poco_last_updated($profile, $force = false) {
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
dbesc($server[0]["network"]), dbesc(normalise_link($profile)));
else
return;
return false;
}
// noscrape is really fast so we don't cache the call.
@ -443,8 +453,11 @@ function poco_last_updated($profile, $force = false) {
"network" => $server[0]["network"],
"generation" => $gcontacts[0]["generation"]);
$contact["name"] = $noscrape["fn"];
$contact["community"] = $noscrape["comm"];
if (isset($noscrape["fn"]))
$contact["name"] = $noscrape["fn"];
if (isset($noscrape["comm"]))
$contact["community"] = $noscrape["comm"];
if (isset($noscrape["tags"])) {
$keywords = implode(" ", $noscrape["tags"]);
@ -456,7 +469,8 @@ function poco_last_updated($profile, $force = false) {
if ($location)
$contact["location"] = $location;
$contact["notify"] = $noscrape["dfrn-notify"];
if (isset($noscrape["dfrn-notify"]))
$contact["notify"] = $noscrape["dfrn-notify"];
// Remove all fields that are not present in the gcontact table
unset($noscrape["fn"]);
@ -473,19 +487,32 @@ function poco_last_updated($profile, $force = false) {
unset($noscrape["dfrn-notify"]);
unset($noscrape["dfrn-poll"]);
// Set the date of the last contact
/// @todo By now the function "update_gcontact" doesn't work with this field
//$contact["last_contact"] = datetime_convert();
$contact = array_merge($contact, $noscrape);
update_gcontact($contact);
return $noscrape["updated"];
if (trim($noscrape["updated"]) != "") {
q("UPDATE `gcontact` SET `last_contact` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
logger("Profile ".$profile." was last updated at ".$noscrape["updated"]." (noscrape)", LOGGER_DEBUG);
return $noscrape["updated"];
}
}
}
}
}
// If we only can poll the feed, then we only do this once a while
if (!$force AND !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"]))
if (!$force AND !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) {
logger("Profile ".$profile." was last updated at ".$gcontacts[0]["updated"]." (cached)", LOGGER_DEBUG);
return $gcontacts[0]["updated"];
}
$data = probe_url($profile);
@ -504,12 +531,15 @@ function poco_last_updated($profile, $force = false) {
poco_last_updated($data["url"], $force);
logger("Profile ".$profile." was deleted", LOGGER_DEBUG);
return false;
}
if (($data["poll"] == "") OR (in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM)))) {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
logger("Profile ".$profile." wasn't reachable (profile)", LOGGER_DEBUG);
return false;
}
@ -535,6 +565,8 @@ function poco_last_updated($profile, $force = false) {
if (!$feedret["success"]) {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
logger("Profile ".$profile." wasn't reachable (no feed)", LOGGER_DEBUG);
return false;
}
@ -571,6 +603,8 @@ function poco_last_updated($profile, $force = false) {
q("UPDATE `gcontact` SET `generation` = 9 WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
logger("Profile ".$profile." was last updated at ".$last_updated, LOGGER_DEBUG);
return($last_updated);
}
@ -1354,6 +1388,50 @@ function poco_discover_server($data, $default_generation = 0) {
return $success;
}
/**
* @brief Removes unwanted parts from a contact url
*
* @param string $url Contact url
* @return string Contact url with the wanted parts
*/
function clean_contact_url($url) {
$parts = parse_url($url);
if (!isset($parts["scheme"]) OR !isset($parts["host"]))
return $url;
$new_url = $parts["scheme"]."://".$parts["host"];
if (isset($parts["port"]))
$new_url .= ":".$parts["port"];
if (isset($parts["path"]))
$new_url .= $parts["path"];
if ($new_url != $url)
logger("Cleaned contact url ".$url." to ".$new_url." - Called by: ".App::callstack(), LOGGER_DEBUG);
return $new_url;
}
/**
* @brief Replace alternate OStatus user format with the primary one
*
* @param arr $contact contact array (called by reference)
*/
function fix_alternate_contact_address(&$contact) {
if (($contact["network"] == NETWORK_OSTATUS) AND poco_alternate_ostatus_url($contact["url"])) {
$data = probe_url($contact["url"]);
if ($contact["network"] == NETWORK_OSTATUS) {
logger("Fix primary url from ".$contact["url"]." to ".$data["url"]." - Called by: ".App::callstack(), LOGGER_DEBUG);
$contact["url"] = $data["url"];
$contact["addr"] = $data["addr"];
$contact["alias"] = $data["alias"];
$contact["server_url"] = $data["baseurl"];
}
}
}
/**
* @brief Fetch the gcontact id, add an entry if not existed
*
@ -1363,18 +1441,44 @@ function poco_discover_server($data, $default_generation = 0) {
function get_gcontact_id($contact) {
$gcontact_id = 0;
$doprobing = false;
if (in_array($contact["network"], array(NETWORK_PHANTOM))) {
logger("Invalid network for contact url ".$contact["url"]." - Called by: ".App::callstack(), LOGGER_DEBUG);
return false;
}
if ($contact["network"] == NETWORK_STATUSNET)
$contact["network"] = NETWORK_OSTATUS;
$r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2",
// All new contacts are hidden by default
if (!isset($contact["hide"]))
$contact["hide"] = true;
// Replace alternate OStatus user format with the primary one
fix_alternate_contact_address($contact);
// Remove unwanted parts from the contact url (e.g. "?zrl=...")
if (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
$contact["url"] = clean_contact_url($contact["url"]);
$r = q("SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2",
dbesc(normalise_link($contact["url"])));
if ($r)
if ($r) {
$gcontact_id = $r[0]["id"];
else {
q("INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
// Update every 90 days
if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) {
$last_failure_str = $r[0]["last_failure"];
$last_failure = strtotime($r[0]["last_failure"]);
$last_contact_str = $r[0]["last_contact"];
$last_contact = strtotime($r[0]["last_contact"]);
$doprobing = (((time() - $last_contact) > (90 * 86400)) AND ((time() - $last_failure) > (90 * 86400)));
}
} else {
q("INSERT INTO `gcontact` (`name`, `nick`, `addr` , `network`, `url`, `nurl`, `photo`, `created`, `updated`, `location`, `about`, `hide`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
dbesc($contact["name"]),
dbesc($contact["nick"]),
dbesc($contact["addr"]),
@ -1386,14 +1490,23 @@ function get_gcontact_id($contact) {
dbesc(datetime_convert()),
dbesc($contact["location"]),
dbesc($contact["about"]),
intval($contact["hide"]),
intval($contact["generation"])
);
$r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2",
$r = q("SELECT `id`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2",
dbesc(normalise_link($contact["url"])));
if ($r)
if ($r) {
$gcontact_id = $r[0]["id"];
$doprobing = in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""));
}
}
if ($doprobing) {
logger("Last Contact: ". $last_contact_str." - Last Failure: ".$last_failure_str." - Checking: ".$contact["url"], LOGGER_DEBUG);
proc_run('php', 'include/gprobe.php', bin2hex($contact["url"]));
}
if ((count($r) > 1) AND ($gcontact_id > 0) AND ($contact["url"] != ""))
@ -1431,6 +1544,7 @@ function update_gcontact($contact) {
unset($fields["url"]);
unset($fields["updated"]);
unset($fields["hide"]);
// Bugfix: We had an error in the storing of keywords which lead to the "0"
// This value is still transmitted via poco.
@ -1445,9 +1559,17 @@ function update_gcontact($contact) {
if (!isset($contact[$field]) OR ($contact[$field] == ""))
$contact[$field] = $r[0][$field];
if (!isset($contact["hide"]))
$contact["hide"] = $r[0]["hide"];
$fields["hide"] = $r[0]["hide"];
if ($contact["network"] == NETWORK_STATUSNET)
$contact["network"] = NETWORK_OSTATUS;
// Replace alternate OStatus user format with the primary one
fix_alternate_contact_address($contact);
if (!isset($contact["updated"]))
$contact["updated"] = datetime_convert();
@ -1542,12 +1664,52 @@ function update_gcontact($contact) {
function update_gcontact_from_probe($url) {
$data = probe_url($url);
if ($data["network"] == NETWORK_PHANTOM)
if (in_array($data["network"], array(NETWORK_PHANTOM))) {
logger("Invalid network for contact url ".$data["url"]." - Called by: ".App::callstack(), LOGGER_DEBUG);
return;
}
update_gcontact($data);
}
/**
* @brief Update the gcontact entry for a given user id
*
* @param int $uid User ID
*/
function update_gcontact_for_user($uid) {
$r = q("SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`,
`profile`.`name`, `profile`.`about`, `profile`.`gender`,
`profile`.`pub_keywords`, `profile`.`dob`, `profile`.`photo`,
`profile`.`net-publish`, `user`.`nickname`, `user`.`hidewall`,
`contact`.`notify`, `contact`.`url`, `contact`.`addr`
FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid`
WHERE `profile`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self`",
intval($uid));
$location = formatted_location(array("locality" => $r[0]["locality"], "region" => $r[0]["region"],
"country-name" => $r[0]["country-name"]));
// The "addr" field was added in 3.4.3 so it can be empty for older users
if ($r[0]["addr"] != "")
$addr = $r[0]["nickname"].'@'.str_replace(array("http://", "https://"), "", App::get_baseurl());
else
$addr = $r[0]["addr"];
$gcontact = array("name" => $r[0]["name"], "location" => $location, "about" => $r[0]["about"],
"gender" => $r[0]["gender"], "keywords" => $r[0]["pub_keywords"],
"birthday" => $r[0]["dob"], "photo" => $r[0]["photo"],
"notify" => $r[0]["notify"], "url" => $r[0]["url"],
"hide" => ($r[0]["hidewall"] OR !$r[0]["net-publish"]),
"nick" => $r[0]["nickname"], "addr" => $addr,
"connect" => $addr, "server_url" => App::get_baseurl(),
"generation" => 1, "network" => NETWORK_DFRN);
update_gcontact($gcontact);
}
/**
* @brief Fetches users of given GNU Social server
*

View file

@ -2,6 +2,7 @@
require_once("include/template_processor.php");
require_once("include/friendica_smarty.php");
require_once("include/Smilies.php");
require_once("include/map.php");
require_once("mod/proxy.php");
@ -974,6 +975,7 @@ function search($s,$id='search-box',$url='search',$save = false, $aside = true)
'$search_label' => t('Search'),
'$save_label' => t('Save'),
'$savedsearch' => feature_enabled(local_user(),'savedsearch'),
'$search_hint' => t('@name, !forum, #tags, content'),
);
if (!$aside) {
@ -1079,160 +1081,6 @@ function get_mood_verbs() {
return $arr;
}
if(! function_exists('smilies')) {
/**
* Replaces text emoticons with graphical images
*
* It is expected that this function will be called using HTML text.
* We will escape text between HTML pre and code blocks from being
* processed.
*
* At a higher level, the bbcode [nosmile] tag can be used to prevent this
* function from being executed by the prepare_text() routine when preparing
* bbcode source for HTML display
*
* @param string $s
* @param boolean $sample
* @return string
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array, 'string' => $s)
*/
function smilies($s, $sample = false) {
$a = get_app();
if(intval(get_config('system','no_smilies'))
|| (local_user() && intval(get_pconfig(local_user(),'system','no_smilies'))))
return $s;
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_encode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_encode',$s);
$texts = array(
'&lt;3',
'&lt;/3',
'&lt;\\3',
':-)',
';-)',
':-(',
':-P',
':-p',
':-"',
':-&quot;',
':-x',
':-X',
':-D',
'8-|',
'8-O',
':-O',
'\\o/',
'o.O',
'O.o',
'o_O',
'O_o',
":'(",
":-!",
":-/",
":-[",
"8-)",
':beer',
':homebrew',
':coffee',
':facepalm',
':like',
':dislike',
'~friendica',
'red#',
'red#matrix'
);
$icons = array(
'<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;/3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-smile.gif" alt=":-)" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-wink.gif" alt=";-)" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-frown.gif" alt=":-(" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-P" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-p" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-x" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-X" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-laughing.gif" alt=":-D" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-|" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt=":-O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-thumbsup.gif" alt="\\o/" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o.O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O.o" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o_O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O_o" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-cry.gif" alt=":\'(" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-foot-in-mouth.gif" alt=":-!" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-undecided.gif" alt=":-/" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-embarassed.gif" alt=":-[" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-cool.gif" alt="8-)" />',
'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":beer" />',
'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":homebrew" />',
'<img class="smiley" src="' . z_root() . '/images/coffee.gif" alt=":coffee" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-facepalm.gif" alt=":facepalm" />',
'<img class="smiley" src="' . z_root() . '/images/like.gif" alt=":like" />',
'<img class="smiley" src="' . z_root() . '/images/dislike.gif" alt=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . z_root() . '/images/friendica-16.png" alt="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red" />matrix</a>'
);
$params = array('texts' => $texts, 'icons' => $icons, 'string' => $s);
call_hooks('smilie', $params);
if($sample) {
$s = '<div class="smiley-sample">';
for($x = 0; $x < count($params['texts']); $x ++) {
$s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>';
}
}
else {
$params['string'] = preg_replace_callback('/&lt;(3+)/','preg_heart',$params['string']);
$s = str_replace($params['texts'],$params['icons'],$params['string']);
}
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_decode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_decode',$s);
return $s;
}}
function smile_encode($m) {
return(str_replace($m[1],base64url_encode($m[1]),$m[0]));
}
function smile_decode($m) {
return(str_replace($m[1],base64url_decode($m[1]),$m[0]));
}
/**
* expand <3333 to the correct number of hearts
*
* @param string $x
* @return string
*/
function preg_heart($x) {
$a = get_app();
if(strlen($x[1]) == 1)
return $x[0];
$t = '';
for($cnt = 0; $cnt < strlen($x[1]); $cnt ++)
$t .= '<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" />';
$r = str_replace($x[0],$t,$x[0]);
return $r;
}
if(! function_exists('day_translate')) {
/**
* Translate days and months names
@ -1549,7 +1397,7 @@ function prepare_text($text) {
if(stristr($text,'[nosmile]'))
$s = bbcode($text);
else
$s = smilies(bbcode($text));
$s = Smilies::replace(bbcode($text));
return trim($s);
}}

353
include/xml.php Normal file
View file

@ -0,0 +1,353 @@
<?php
/**
* @file include/xml.php
*/
/**
* @brief This class contain functions to work with XML data
*
*/
class xml {
/**
* @brief Creates an XML structure out of a given array
*
* @param array $array The array of the XML structure that will be generated
* @param object $xml The createdXML will be returned by reference
* @param bool $remove_header Should the XML header be removed or not?
* @param array $namespaces List of namespaces
* @param bool $root - interally used parameter. Mustn't be used from outside.
*
* @return string The created XML
*/
public static function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
if ($root) {
foreach($array as $key => $value) {
foreach ($namespaces AS $nskey => $nsvalue)
$key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"';
$root = new SimpleXMLElement("<".$key."/>");
self::from_array($value, $root, $remove_header, $namespaces, false);
$dom = dom_import_simplexml($root)->ownerDocument;
$dom->formatOutput = true;
$xml = $dom;
$xml_text = $dom->saveXML();
if ($remove_header)
$xml_text = trim(substr($xml_text, 21));
return $xml_text;
}
}
foreach($array as $key => $value) {
if ($key == "@attributes") {
if (!isset($element) OR !is_array($value))
continue;
foreach ($value as $attr_key => $attr_value) {
$element_parts = explode(":", $attr_key);
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
$namespace = $namespaces[$element_parts[0]];
else
$namespace = NULL;
$element->addAttribute ($attr_key, $attr_value, $namespace);
}
continue;
}
$element_parts = explode(":", $key);
if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
$namespace = $namespaces[$element_parts[0]];
else
$namespace = NULL;
if (!is_array($value))
$element = $xml->addChild($key, xmlify($value), $namespace);
elseif (is_array($value)) {
$element = $xml->addChild($key, NULL, $namespace);
self::from_array($value, $element, $remove_header, $namespaces, false);
}
}
}
/**
* @brief Copies an XML object
*
* @param object $source The XML source
* @param object $target The XML target
* @param string $elementname Name of the XML element of the target
*/
public static function copy(&$source, &$target, $elementname) {
if (count($source->children()) == 0)
$target->addChild($elementname, xmlify($source));
else {
$child = $target->addChild($elementname);
foreach ($source->children() AS $childfield => $childentry)
self::copy($childentry, $child, $childfield);
}
}
/**
* @brief Create an XML element
*
* @param object $doc XML root
* @param string $element XML element name
* @param string $value XML value
* @param array $attributes array containing the attributes
*
* @return object XML element object
*/
public static function create_element($doc, $element, $value = "", $attributes = array()) {
$element = $doc->createElement($element, xmlify($value));
foreach ($attributes AS $key => $value) {
$attribute = $doc->createAttribute($key);
$attribute->value = xmlify($value);
$element->appendChild($attribute);
}
return $element;
}
/**
* @brief Create an XML and append it to the parent object
*
* @param object $doc XML root
* @param object $parent parent object
* @param string $element XML element name
* @param string $value XML value
* @param array $attributes array containing the attributes
*/
public static function add_element($doc, $parent, $element, $value = "", $attributes = array()) {
$element = self::create_element($doc, $element, $value, $attributes);
$parent->appendChild($element);
}
/**
* @brief Convert an XML document to a normalised, case-corrected array
* used by webfinger
*
* @param object $xml_element The XML document
* @param integer $recursion_depth recursion counter for internal use - default 0
* internal use, recursion counter
*
* @return array | sring The array from the xml element or the string
*/
public static function element_to_array($xml_element, &$recursion_depth=0) {
// If we're getting too deep, bail out
if ($recursion_depth > 512) {
return(null);
}
if (!is_string($xml_element) &&
!is_array($xml_element) &&
(get_class($xml_element) == 'SimpleXMLElement')) {
$xml_element_copy = $xml_element;
$xml_element = get_object_vars($xml_element);
}
if (is_array($xml_element)) {
$result_array = array();
if (count($xml_element) <= 0) {
return (trim(strval($xml_element_copy)));
}
foreach($xml_element as $key=>$value) {
$recursion_depth++;
$result_array[strtolower($key)] =
self::element_to_array($value, $recursion_depth);
$recursion_depth--;
}
if ($recursion_depth == 0) {
$temp_array = $result_array;
$result_array = array(
strtolower($xml_element_copy->getName()) => $temp_array,
);
}
return ($result_array);
} else {
return (trim(strval($xml_element)));
}
}
/**
* @brief Convert the given XML text to an array in the XML structure.
*
* xml::to_array() will convert the given XML text to an array in the XML structure.
* Link: http://www.bin-co.com/php/scripts/xml2array/
* Portions significantly re-written by mike@macgirvin.com for Friendica
* (namespaces, lowercase tags, get_attribute default changed, more...)
*
* Examples: $array = xml::to_array(file_get_contents('feed.xml'));
* $array = xml::to_array(file_get_contents('feed.xml', true, 1, 'attribute'));
*
* @param object $contents The XML text
* @param boolean $namespaces True or false include namespace information
* in the returned array as array elements.
* @param integer $get_attributes 1 or 0. If this is 1 the function will get the attributes as well as the tag values -
* this results in a different array structure in the return value.
* @param string $priority Can be 'tag' or 'attribute'. This will change the way the resulting
* array sturcture. For 'tag', the tags are given more importance.
*
* @return array The parsed XML in an array form. Use print_r() to see the resulting array structure.
*/
public static function to_array($contents, $namespaces = true, $get_attributes=1, $priority = 'attribute') {
if(!$contents) return array();
if(!function_exists('xml_parser_create')) {
logger('xml::to_array: parser function missing');
return array();
}
libxml_use_internal_errors(true);
libxml_clear_errors();
if($namespaces)
$parser = @xml_parser_create_ns("UTF-8",':');
else
$parser = @xml_parser_create();
if(! $parser) {
logger('xml::to_array: xml_parser_create: no resource');
return array();
}
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8");
// http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
@xml_parse_into_struct($parser, trim($contents), $xml_values);
@xml_parser_free($parser);
if(! $xml_values) {
logger('xml::to_array: libxml: parse error: ' . $contents, LOGGER_DATA);
foreach(libxml_get_errors() as $err)
logger('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message, LOGGER_DATA);
libxml_clear_errors();
return;
}
//Initializations
$xml_array = array();
$parents = array();
$opened_tags = array();
$arr = array();
$current = &$xml_array; // Reference
// Go through the tags.
$repeated_tag_index = array(); // Multiple tags with same name will be turned into an array
foreach($xml_values as $data) {
unset($attributes,$value); // Remove existing values, or there will be trouble
// This command will extract these variables into the foreach scope
// tag(string), type(string), level(int), attributes(array).
extract($data); // We could use the array by itself, but this cooler.
$result = array();
$attributes_data = array();
if(isset($value)) {
if($priority == 'tag') $result = $value;
else $result['value'] = $value; // Put the value in a assoc array if we are in the 'Attribute' mode
}
//Set the attributes too.
if(isset($attributes) and $get_attributes) {
foreach($attributes as $attr => $val) {
if($priority == 'tag') $attributes_data[$attr] = $val;
else $result['@attributes'][$attr] = $val; // Set all the attributes in a array called 'attr'
}
}
// See tag status and do the needed.
if($namespaces && strpos($tag,':')) {
$namespc = substr($tag,0,strrpos($tag,':'));
$tag = strtolower(substr($tag,strlen($namespc)+1));
$result['@namespace'] = $namespc;
}
$tag = strtolower($tag);
if($type == "open") { // The starting of the tag '<tag>'
$parent[$level-1] = &$current;
if(!is_array($current) or (!in_array($tag, array_keys($current)))) { // Insert New tag
$current[$tag] = $result;
if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
$repeated_tag_index[$tag.'_'.$level] = 1;
$current = &$current[$tag];
} else { // There was another element with the same tag name
if(isset($current[$tag][0])) { // If there is a 0th element it is already an array
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
$repeated_tag_index[$tag.'_'.$level]++;
} else { // This section will make the value an array if multiple tags with the same name appear together
$current[$tag] = array($current[$tag],$result); // This will combine the existing item and the new item together to make an array
$repeated_tag_index[$tag.'_'.$level] = 2;
if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
unset($current[$tag.'_attr']);
}
}
$last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;
$current = &$current[$tag][$last_item_index];
}
} elseif($type == "complete") { // Tags that ends in 1 line '<tag />'
//See if the key is already taken.
if(!isset($current[$tag])) { //New Key
$current[$tag] = $result;
$repeated_tag_index[$tag.'_'.$level] = 1;
if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;
} else { // If taken, put all things inside a list(array)
if(isset($current[$tag][0]) and is_array($current[$tag])) { // If it is already an array...
// ...push the new element into that array.
$current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
if($priority == 'tag' and $get_attributes and $attributes_data) {
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
}
$repeated_tag_index[$tag.'_'.$level]++;
} else { // If it is not an array...
$current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
$repeated_tag_index[$tag.'_'.$level] = 1;
if($priority == 'tag' and $get_attributes) {
if(isset($current[$tag.'_attr'])) { // The attribute of the last(0th) tag must be moved as well
$current[$tag]['0_attr'] = $current[$tag.'_attr'];
unset($current[$tag.'_attr']);
}
if($attributes_data) {
$current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
}
}
$repeated_tag_index[$tag.'_'.$level]++; // 0 and 1 indexes are already taken
}
}
} elseif($type == 'close') { // End of tag '</tag>'
$current = &$parent[$level-1];
}
}
return($xml_array);
}
}
?>

110
index.php
View file

@ -41,10 +41,11 @@ $install = ((file_exists('.htconfig.php') && filesize('.htconfig.php')) ? false
*/
require_once("include/dba.php");
require_once("include/dbm.php");
if(!$install) {
$db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
unset($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
/**
* Load configs from db. Overwrite configs from .htconfig.php
@ -53,6 +54,21 @@ if(!$install) {
load_config('config');
load_config('system');
$processlist = dbm::processlist();
if ($processlist["list"] != "") {
logger("Processcheck: Processes: ".$processlist["amount"]." - Processlist: ".$processlist["list"], LOGGER_DEBUG);
$max_processes = get_config('system', 'max_processes_frontend');
if (intval($max_processes) == 0)
$max_processes = 20;
if ($processlist["amount"] > $max_processes) {
logger("Processcheck: Maximum number of processes for frontend tasks (".$max_processes.") reached.", LOGGER_DEBUG);
system_unavailable();
}
}
$maxsysload_frontend = intval(get_config('system','maxloadavg_frontend'));
if($maxsysload_frontend < 1)
$maxsysload_frontend = 50;
@ -98,7 +114,9 @@ load_translation_table($lang);
*
*/
$stamp1 = microtime(true);
session_start();
$a->save_timestamp($stamp1, "parser");
/**
* Language was set earlier, but we can over-ride it in the session.
@ -117,9 +135,21 @@ if((x($_SESSION,'language')) && ($_SESSION['language'] !== $lang)) {
}
if((x($_GET,'zrl')) && (!$install && !$maintenance)) {
$_SESSION['my_url'] = $_GET['zrl'];
$a->query_string = preg_replace('/[\?&]zrl=(.*?)([\?&]|$)/is','',$a->query_string);
zrl_init($a);
// Only continue when the given profile link seems valid
// Valid profile links contain a path with "/profile/" and no query parameters
if ((parse_url($_GET['zrl'], PHP_URL_QUERY) == "") AND
strstr(parse_url($_GET['zrl'], PHP_URL_PATH), "/profile/")) {
$_SESSION['my_url'] = $_GET['zrl'];
$a->query_string = preg_replace('/[\?&]zrl=(.*?)([\?&]|$)/is','',$a->query_string);
zrl_init($a);
} else {
// Someone came with an invalid parameter, maybe as a DDoS attempt
// We simply stop processing here
logger("Invalid ZRL parameter ".$_GET['zrl'], LOGGER_DEBUG);
header('HTTP/1.1 403 Forbidden');
echo "<h1>403 Forbidden</h1>";
killme();
}
}
/**
@ -135,7 +165,7 @@ if((x($_GET,'zrl')) && (!$install && !$maintenance)) {
// header('Link: <' . $a->get_baseurl() . '/amcd>; rel="acct-mgmt";');
if((x($_SESSION,'authenticated')) || (x($_POST,'auth-params')) || ($a->module === 'login'))
if(x($_COOKIE["Friendica"]) || (x($_SESSION,'authenticated')) || (x($_POST,'auth-params')) || ($a->module === 'login'))
require("include/auth.php");
if(! x($_SESSION,'authenticated'))
@ -430,9 +460,9 @@ if($a->is_mobile || $a->is_tablet) {
$link = 'toggle_mobile?off=1&address=' . curPageURL();
}
$a->page['footer'] = replace_macros(get_markup_template("toggle_mobile_footer.tpl"), array(
'$toggle_link' => $link,
'$toggle_text' => t('toggle mobile')
));
'$toggle_link' => $link,
'$toggle_text' => t('toggle mobile')
));
}
/**
@ -479,70 +509,6 @@ if (isset($_GET["mode"]) AND ($_GET["mode"] == "raw")) {
session_write_close();
exit;
} elseif (get_pconfig(local_user(),'system','infinite_scroll')
AND ($a->module == "network") AND ($_GET["mode"] != "minimal")) {
if (is_string($_GET["page"]))
$pageno = $_GET["page"];
else
$pageno = 1;
$reload_uri = "";
foreach ($_GET AS $param => $value)
if (($param != "page") AND ($param != "q"))
$reload_uri .= "&".$param."=".urlencode($value);
if (($a->page_offset != "") AND !strstr($reload_uri, "&offset="))
$reload_uri .= "&offset=".urlencode($a->page_offset);
$a->page['htmlhead'] .= <<< EOT
<script type="text/javascript">
$(document).ready(function() {
num = $pageno;
});
function loadcontent() {
if (lockLoadContent) return;
lockLoadContent = true;
$("#scroll-loader").fadeIn('normal');
num+=1;
console.log('Loading page ' + num);
$.get('/network?mode=raw$reload_uri&page=' + num, function(data) {
$("#scroll-loader").hide();
if ($(data).length > 0) {
$(data).insertBefore('#conversation-end');
lockLoadContent = false;
} else {
$("#scroll-end").fadeIn('normal');
}
});
}
var num = $pageno;
var lockLoadContent = false;
$(window).scroll(function(e){
if ($(document).height() != $(window).height()) {
// First method that is expected to work - but has problems with Chrome
if ($(window).scrollTop() > ($(document).height() - $(window).height() * 1.5))
loadcontent();
} else {
// This method works with Chrome - but seems to be much slower in Firefox
if ($(window).scrollTop() > (($("section").height() + $("header").height() + $("footer").height()) - $(window).height() * 1.5))
loadcontent();
}
});
</script>
EOT;
}
$page = $a->page;

506
js/autocomplete.js Normal file
View file

@ -0,0 +1,506 @@
/**
* @brief Friendica people autocomplete
*
* require jQuery, jquery.textcomplete
*
* for further documentation look at:
* http://yuku-t.com/jquery-textcomplete/
*
* https://github.com/yuku-t/jquery-textcomplete/blob/master/doc/how_to_use.md
*/
function contact_search(term, callback, backend_url, type, mode) {
// Check if there is a conversation id to include the unkonwn contacts of the conversation
var conv_id = document.activeElement.id.match(/\d+$/);
// Check if there is a cached result that contains the same information we would get with a full server-side search
var bt = backend_url+type;
if(!(bt in contact_search.cache)) contact_search.cache[bt] = {};
var lterm = term.toLowerCase(); // Ignore case
for(var t in contact_search.cache[bt]) {
if(lterm.indexOf(t) >= 0) { // A more broad search has been performed already, so use those results
// Filter old results locally
var matching = contact_search.cache[bt][t].filter(function (x) { return (x.name.toLowerCase().indexOf(lterm) >= 0 || (typeof x.nick !== 'undefined' && x.nick.toLowerCase().indexOf(lterm) >= 0)); }); // Need to check that nick exists because groups don't have one
matching.unshift({forum:false, text: term, replace: term});
setTimeout(function() { callback(matching); } , 1); // Use "pseudo-thread" to avoid some problems
return;
}
}
var postdata = {
start:0,
count:100,
search:term,
type:type,
};
if(conv_id !== null)
postdata['conversation'] = conv_id[0];
if(mode !== null)
postdata['mode'] = mode;
$.ajax({
type:'POST',
url: backend_url,
data: postdata,
dataType: 'json',
success: function(data){
// Cache results if we got them all (more information would not improve results)
// data.count represents the maximum number of items
if(data.items.length -1 < data.count) {
contact_search.cache[bt][lterm] = data.items;
}
var items = data.items.slice(0);
items.unshift({taggable:false, text: term, replace: term});
callback(items);
},
}).fail(function () {callback([]); }); // Callback must be invoked even if something went wrong.
}
contact_search.cache = {};
function contact_format(item) {
// Show contact information if not explicitly told to show something else
if(typeof item.text === 'undefined') {
var desc = ((item.label) ? item.nick + ' ' + item.label : item.nick);
var forum = ((item.forum) ? 'forum' : '');
if(typeof desc === 'undefined') desc = '';
if(desc) desc = ' ('+desc+')';
return "<div class='{0}' title='{4}'><img class='acpopup-img' src='{1}'><span class='acpopup-contactname'>{2}</span><span class='acpopup-sub-text'>{3}</span><div class='clear'></div></div>".format(forum, item.photo, item.name, desc, item.link);
}
else
return "<div>" + item.text + "</div>";
}
function editor_replace(item) {
if(typeof item.replace !== 'undefined') {
return '$1$2' + item.replace;
}
// $2 ensures that prefix (@,@!) is preserved
var id = item.id;
// don't add the id if it is empty (the id empty eg. if there are unknow contacts in thread)
if(id.length < 1)
return '$1$2' + item.nick.replace(' ', '') + ' ';
// 16 chars of hash should be enough. Full hash could be used if it can be done in a visually appealing way.
// 16 chars is also the minimum length in the backend (otherwise it's interpreted as a local id).
if(id.length > 16)
id = item.id.substring(0,16);
return '$1$2' + item.nick.replace(' ', '') + '+' + id + ' ';
}
function basic_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.name+' ';
}
function webbie_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.nick+' ';
}
function trim_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.name;
}
function submit_form(e) {
$(e).parents('form').submit();
}
function getWord(text, caretPos) {
var index = text.indexOf(caretPos);
var postText = text.substring(caretPos, caretPos+8);
if ((postText.indexOf("[/list]") > 0) || postText.indexOf("[/ul]") > 0 || postText.indexOf("[/ol]") > 0) {
return postText;
}
}
function getCaretPosition(ctrl) {
var CaretPos = 0; // IE Support
if (document.selection) {
ctrl.focus();
var Sel = document.selection.createRange();
Sel.moveStart('character', -ctrl.value.length);
CaretPos = Sel.text.length;
}
// Firefox support
else if (ctrl.selectionStart || ctrl.selectionStart == '0')
CaretPos = ctrl.selectionStart;
return (CaretPos);
}
function setCaretPosition(ctrl, pos){
if(ctrl.setSelectionRange) {
ctrl.focus();
ctrl.setSelectionRange(pos,pos);
}
else if (ctrl.createTextRange) {
var range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
function listNewLineAutocomplete(id) {
var text = document.getElementById(id);
var caretPos = getCaretPosition(text)
var word = getWord(text.value, caretPos);
if (word != null) {
var textBefore = text.value.substring(0, caretPos);
var textAfter = text.value.substring(caretPos, text.length);
$('#' + id).val(textBefore + '\r\n[*] ' + textAfter);
setCaretPosition(text, caretPos + 5);
return true;
}
else {
return false;
}
}
function string2bb(element) {
if(element == 'bold') return 'b';
else if(element == 'italic') return 'i';
else if(element == 'underline') return 'u';
else if(element == 'overline') return 'o';
else if(element == 'strike') return 's';
else return element;
}
/**
* jQuery plugin 'editor_autocomplete'
*/
(function( $ ) {
$.fn.editor_autocomplete = function(backend_url) {
// Autocomplete contacts
contacts = {
match: /(^|\s)(@\!*)([^ \n]+)$/,
index: 3,
search: function(term, callback) { contact_search(term, callback, backend_url, 'c'); },
replace: editor_replace,
template: contact_format,
};
// Autocomplete smilies e.g. ":like"
smilies = {
match: /(^|\s)(:[a-z]{2,})$/,
index: 2,
search: function(term, callback) { $.getJSON('smilies/json').done(function(data) { callback($.map(data, function(entry) { return entry.text.indexOf(term) === 0 ? entry : null; })); }); },
template: function(item) { return item.icon + ' ' + item.text; },
replace: function(item) { return "$1" + item.text + ' '; },
};
this.attr('autocomplete','off');
this.textcomplete([contacts,smilies], {className:'acpopup', zIndex:10000});
};
})( jQuery );
/**
* jQuery plugin 'search_autocomplete'
*/
(function( $ ) {
$.fn.search_autocomplete = function(backend_url) {
// Autocomplete contacts
contacts = {
match: /(^@)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x', 'contact'); },
replace: webbie_replace,
template: contact_format,
};
// Autocomplete forum accounts
community = {
match: /(^!)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x', 'community'); },
replace: webbie_replace,
template: contact_format,
};
this.attr('autocomplete', 'off');
var a = this.textcomplete([contacts, community], {className:'acpopup', maxCount:100, zIndex: 10000, appendTo:'nav'});
a.on('textComplete:select', function(e, value, strategy) { submit_form(this); });
};
})( jQuery );
(function( $ ) {
$.fn.contact_autocomplete = function(backend_url, typ, autosubmit, onselect) {
if(typeof typ === 'undefined') typ = '';
if(typeof autosubmit === 'undefined') autosubmit = false;
// Autocomplete contacts
contacts = {
match: /(^)([^\n]+)$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
replace: basic_replace,
template: contact_format,
};
this.attr('autocomplete','off');
var a = this.textcomplete([contacts], {className:'acpopup', zIndex:10000});
if(autosubmit)
a.on('textComplete:select', function(e,value,strategy) { submit_form(this); });
if(typeof onselect !== 'undefined')
a.on('textComplete:select', function(e, value, strategy) { onselect(value); });
};
})( jQuery );
(function( $ ) {
$.fn.name_autocomplete = function(backend_url, typ, autosubmit, onselect) {
if(typeof typ === 'undefined') typ = '';
if(typeof autosubmit === 'undefined') autosubmit = false;
// Autocomplete contacts
names = {
match: /(^)([^\n]+)$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
replace: trim_replace,
template: contact_format,
};
this.attr('autocomplete','off');
var a = this.textcomplete([names], {className:'acpopup', zIndex:10000});
if(autosubmit)
a.on('textComplete:select', function(e,value,strategy) { submit_form(this); });
if(typeof onselect !== 'undefined')
a.on('textComplete:select', function(e, value, strategy) { onselect(value); });
};
})( jQuery );
(function( $ ) {
$.fn.bbco_autocomplete = function(type) {
if(type=='bbcode') {
var open_close_elements = ['bold', 'italic', 'underline', 'overline', 'strike', 'quote', 'code', 'spoiler', 'map', 'img', 'url', 'audio', 'video', 'youtube', 'vimeo', 'list', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'center', 'color', 'font', 'size', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'nobb', 'noparse', 'pre', 'abstract'];
var open_elements = ['*', 'hr'];
var elements = open_close_elements.concat(open_elements);
}
bbco = {
match: /\[(\w*\**)$/,
search: function (term, callback) {
callback($.map(elements, function (element) {
return element.indexOf(term) === 0 ? element : null;
}));
},
index: 1,
replace: function (element) {
element = string2bb(element);
if(open_elements.indexOf(element) < 0) {
if(element === 'list' || element === 'ol' || element === 'ul') {
return ['\[' + element + '\]' + '\n\[*\] ', '\n\[/' + element + '\]'];
}
else if(element === 'table') {
return ['\[' + element + '\]' + '\n\[tr\]', '\[/tr\]\n\[/' + element + '\]'];
}
else {
return ['\[' + element + '\]', '\[/' + element + '\]'];
}
}
else {
return '\[' + element + '\] ';
}
}
};
this.attr('autocomplete','off');
var a = this.textcomplete([bbco], {className:'acpopup', zIndex:10000});
a.on('textComplete:select', function(e, value, strategy) { value; });
a.keypress(function(e){
if (e.keyCode == 13) {
var x = listNewLineAutocomplete(this.id);
if(x) {
e.stopImmediatePropagation();
e.preventDefault();
}
}
});
};
})( jQuery );
/**
* Friendica people autocomplete legacy
* code which is needed for tinymce
*
* require jQuery, jquery.textareas
*/
function ACPopup(elm,backend_url){
this.idsel=-1;
this.element = elm;
this.searchText="";
this.ready=true;
this.kp_timer = false;
this.url = backend_url;
this.conversation_id = null;
var conv_id = this.element.id.match(/\d+$/);
if (conv_id) this.conversation_id = conv_id[0];
console.log("ACPopup elm id",this.element.id,"conversation",this.conversation_id);
var w = 530;
var h = 130;
if(tinyMCE.activeEditor == null) {
style = $(elm).offset();
w = $(elm).width();
h = $(elm).height();
}
else {
// I can't find an "official" way to get the element who get all
// this fraking thing that is tinyMCE.
// This code will broke again at some point...
var container = $(tinyMCE.activeEditor.getContainer()).find("table");
style = $(container).offset();
w = $(container).width();
h = $(container).height();
}
style.top=style.top+h;
style.width = w;
style.position = 'absolute';
/* style['max-height'] = '150px';
style.border = '1px solid red';
style.background = '#cccccc';
style.overflow = 'auto';
style['z-index'] = '100000';
*/
style.display = 'none';
this.cont = $("<div class='acpopup-mce'></div>");
this.cont.css(style);
$("body").append(this.cont);
}
ACPopup.prototype.close = function(){
$(this.cont).remove();
this.ready=false;
}
ACPopup.prototype.search = function(text){
var that = this;
this.searchText=text;
if (this.kp_timer) clearTimeout(this.kp_timer);
this.kp_timer = setTimeout( function(){that._search();}, 500);
}
ACPopup.prototype._search = function(){
console.log("_search");
var that = this;
var postdata = {
start:0,
count:100,
search:this.searchText,
type:'c',
conversation: this.conversation_id,
}
$.ajax({
type:'POST',
url: this.url,
data: postdata,
dataType: 'json',
success:function(data){
that.cont.html("");
if (data.tot>0){
that.cont.show();
$(data.items).each(function(){
var html = "<img src='{0}' height='16px' width='16px'>{1} ({2})".format(this.photo, this.name, this.nick);
var nick = this.nick.replace(' ','');
if (this.id!=='') nick += '+' + this.id;
that.add(html, nick + ' - ' + this.link);
});
} else {
that.cont.hide();
}
}
});
}
ACPopup.prototype.add = function(label, value){
var that=this;
var elm = $("<div class='acpopupitem' title='"+value+"'>"+label+"</div>");
elm.click(function(e){
t = $(this).attr('title').replace(new RegExp(' \- .*'),'');
if(typeof(that.element.container) === "undefined") {
el=$(that.element);
sel = el.getSelection();
sel.start = sel.start- that.searchText.length;
el.setSelection(sel.start,sel.end).replaceSelectedText(t+' ').collapseSelection(false);
that.close();
}
else {
txt = tinyMCE.activeEditor.getContent();
// alert(that.searchText + ':' + t);
newtxt = txt.replace('@' + that.searchText,'@' + t +' ');
tinyMCE.activeEditor.setContent(newtxt);
tinyMCE.activeEditor.focus();
that.close();
}
});
$(this.cont).append(elm);
}
ACPopup.prototype.onkey = function(event){
if (event.keyCode == '13') {
if(this.idsel>-1) {
this.cont.children()[this.idsel].click();
event.preventDefault();
}
else
this.close();
}
if (event.keyCode == '38') { //cursor up
cmax = this.cont.children().size()-1;
this.idsel--;
if (this.idsel<0) this.idsel=cmax;
event.preventDefault();
}
if (event.keyCode == '40' || event.keyCode == '9') { //cursor down
cmax = this.cont.children().size()-1;
this.idsel++;
if (this.idsel>cmax) this.idsel=0;
event.preventDefault();
}
if (event.keyCode == '38' || event.keyCode == '40' || event.keyCode == '9') {
this.cont.children().removeClass('selected');
$(this.cont.children()[this.idsel]).addClass('selected');
}
if (event.keyCode == '27') { //ESC
this.close();
}
}

View file

@ -1,203 +0,0 @@
/**
* Friendica people autocomplete
*
* require jQuery, jquery.textareas
*/
function ACPopup(elm,backend_url){
this.idsel=-1;
this.element = elm;
this.searchText="";
this.ready=true;
this.kp_timer = false;
this.url = backend_url;
this.conversation_id = null;
var conv_id = this.element.id.match(/\d+$/);
if (conv_id) this.conversation_id = conv_id[0];
console.log("ACPopup elm id",this.element.id,"conversation",this.conversation_id);
var w = 530;
var h = 130;
if(tinyMCE.activeEditor == null) {
style = $(elm).offset();
w = $(elm).width();
h = $(elm).height();
}
else {
// I can't find an "official" way to get the element who get all
// this fraking thing that is tinyMCE.
// This code will broke again at some point...
var container = $(tinyMCE.activeEditor.getContainer()).find("table");
style = $(container).offset();
w = $(container).width();
h = $(container).height();
}
style.top=style.top+h;
style.width = w;
style.position = 'absolute';
/* style['max-height'] = '150px';
style.border = '1px solid red';
style.background = '#cccccc';
style.overflow = 'auto';
style['z-index'] = '100000';
*/
style.display = 'none';
this.cont = $("<div class='acpopup'></div>");
this.cont.css(style);
$("body").append(this.cont);
}
ACPopup.prototype.close = function(){
$(this.cont).remove();
this.ready=false;
}
ACPopup.prototype.search = function(text){
var that = this;
this.searchText=text;
if (this.kp_timer) clearTimeout(this.kp_timer);
this.kp_timer = setTimeout( function(){that._search();}, 500);
}
ACPopup.prototype._search = function(){
console.log("_search");
var that = this;
var postdata = {
start:0,
count:100,
search:this.searchText,
type:'c',
conversation: this.conversation_id,
}
$.ajax({
type:'POST',
url: this.url,
data: postdata,
dataType: 'json',
success:function(data){
that.cont.html("");
if (data.tot>0){
that.cont.show();
$(data.items).each(function(){
var html = "<img src='{0}' height='16px' width='16px'>{1} ({2})".format(this.photo, this.name, this.nick);
var nick = this.nick.replace(' ','');
if (this.id!=='') nick += '+' + this.id;
that.add(html, nick + ' - ' + this.link);
});
} else {
that.cont.hide();
}
}
});
}
ACPopup.prototype.add = function(label, value){
var that=this;
var elm = $("<div class='acpopupitem' title='"+value+"'>"+label+"</div>");
elm.click(function(e){
t = $(this).attr('title').replace(new RegExp(' \- .*'),'');
if(typeof(that.element.container) === "undefined") {
el=$(that.element);
sel = el.getSelection();
sel.start = sel.start- that.searchText.length;
el.setSelection(sel.start,sel.end).replaceSelectedText(t+' ').collapseSelection(false);
that.close();
}
else {
txt = tinyMCE.activeEditor.getContent();
// alert(that.searchText + ':' + t);
newtxt = txt.replace('@' + that.searchText,'@' + t +' ');
tinyMCE.activeEditor.setContent(newtxt);
tinyMCE.activeEditor.focus();
that.close();
}
});
$(this.cont).append(elm);
}
ACPopup.prototype.onkey = function(event){
if (event.keyCode == '13') {
if(this.idsel>-1) {
this.cont.children()[this.idsel].click();
event.preventDefault();
}
else
this.close();
}
if (event.keyCode == '38') { //cursor up
cmax = this.cont.children().size()-1;
this.idsel--;
if (this.idsel<0) this.idsel=cmax;
event.preventDefault();
}
if (event.keyCode == '40' || event.keyCode == '9') { //cursor down
cmax = this.cont.children().size()-1;
this.idsel++;
if (this.idsel>cmax) this.idsel=0;
event.preventDefault();
}
if (event.keyCode == '38' || event.keyCode == '40' || event.keyCode == '9') {
this.cont.children().removeClass('selected');
$(this.cont.children()[this.idsel]).addClass('selected');
}
if (event.keyCode == '27') { //ESC
this.close();
}
}
function ContactAutocomplete(element,backend_url){
this.pattern=/@([^ \n]+)$/;
this.popup=null;
var that = this;
$(element).unbind('keydown');
$(element).unbind('keyup');
$(element).keydown(function(event){
if (that.popup!==null) that.popup.onkey(event);
});
$(element).keyup(function(event){
cpos = $(this).getSelection();
if (cpos.start==cpos.end){
match = $(this).val().substring(0,cpos.start).match(that.pattern);
if (match!==null){
if (that.popup===null){
that.popup = new ACPopup(this, backend_url);
}
if (that.popup.ready && match[1]!==that.popup.searchText) that.popup.search(match[1]);
if (!that.popup.ready) that.popup=null;
} else {
if (that.popup!==null) {that.popup.close(); that.popup=null;}
}
}
});
}
/**
* jQuery plugin 'contact_autocomplete'
*/
(function( $ ){
$.fn.contact_autocomplete = function(backend_url) {
this.each(function(){
new ContactAutocomplete(this, backend_url);
});
};
})( jQuery );

View file

@ -51,6 +51,7 @@
var commentBusy = false;
var last_popup_menu = null;
var last_popup_button = null;
var lockLoadContent = false;
$(function() {
$.ajaxSetup({cache: false});
@ -349,6 +350,21 @@
}
});
// Set an event listener for infinite scroll
if(typeof infinite_scroll !== 'undefined') {
$(window).scroll(function(e){
if ($(document).height() != $(window).height()) {
// First method that is expected to work - but has problems with Chrome
if ($(window).scrollTop() > ($(document).height() - $(window).height() * 1.5))
loadScrollContent();
} else {
// This method works with Chrome - but seems to be much slower in Firefox
if ($(window).scrollTop() > (($("section").height() + $("header").height() + $("footer").height()) - $(window).height() * 1.5))
loadScrollContent();
}
});
}
});
@ -494,8 +510,10 @@
$('body').css('cursor', 'auto');
}
/* autocomplete @nicknames */
$(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
/* autocomplete bbcode */
$(".comment-edit-form textarea").bbco_autocomplete('bbcode');
// setup videos, since VideoJS won't take care of any loaded via AJAX
if(typeof videojs != 'undefined') videojs.autoSetup();
});
@ -707,6 +725,31 @@
$('#pause').html('');
}
// load more network content (used for infinite scroll)
function loadScrollContent() {
if (lockLoadContent) return;
lockLoadContent = true;
$("#scroll-loader").fadeIn('normal');
// the page number to load is one higher than the actual
// page number
infinite_scroll.pageno+=1;
console.log('Loading page ' + infinite_scroll.pageno);
// get the raw content from the next page and insert this content
// right before "#conversation-end"
$.get('network?mode=raw' + infinite_scroll.reload_uri + '&page=' + infinite_scroll.pageno, function(data) {
$("#scroll-loader").hide();
if ($(data).length > 0) {
$(data).insertBefore('#conversation-end');
lockLoadContent = false;
} else {
$("#scroll-end").fadeIn('normal');
}
});
}
function bin2hex(s){
// Converts the binary representation of data to hex

View file

@ -0,0 +1,340 @@
# Change Log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/) by version 1.0.0.
This change log adheres to [keepachangelog.com](http://keepachangelog.com).
## [Unreleased]
## [1.3.4] - 2016-04-20
### Fixed
- Fix endless loop when RTL ([#247](https://github.com/yuku-t/jquery-textcomplete/pull/247))
## [1.3.3] - 2016-04-04
### Fixed
- Fix uncaught TypeError.
## [1.3.2] - 2016-03-27
### Fixed
- Fix dropdown position problem with `line-height: normal`.
## [1.3.1] - 2016-03-23
### Fixed
- Fix `input[type=search]` support.
## [1.3.0] - 2016-03-20
### Added
- Add optional "id" strategy parameter.
## [1.2.2] - 2016-03-19
### Fixed
- Remove dropdown element after `textcomplete('destroy')`.
- Skip search after pressing tab.
- Fix dropdown-menu positioning problem using textarea-caret package.
## [1.2.1] - 2016-03-14
### Fixed
- Build dist files.
## [1.2.0] - 2016-03-14
### Added
- Support `input[type=search]` ([#236](https://github.com/yuku-t/jquery-textcomplete/pull/236))
## [1.1.0] - 2016-03-10
### Added
- Add the ability to insert HTML into a "contenteditable" field. ([#217](https://github.com/yuku-t/jquery-textcomplete/pull/217))
### Fixed
- Position relative to appendTo element. ([#234](https://github.com/yuku-t/jquery-textcomplete/pull/234))
- Avoid dropdown bumping into right edge of window. ([#235](https://github.com/yuku-t/jquery-textcomplete/pull/235))
- Fix top position issue when window is scrolled up and parents has fix position. ([#229](https://github.com/yuku-t/jquery-textcomplete/pull/229))
## [1.0.0] - 2016-02-29
### Changed
- Adheres keepachangelog.com.
## [0.8.2] - 2016-02-29
### Added
- Add deactivate method to Completer. ([#233](https://github.com/yuku-t/jquery-textcomplete/pull/233))
## [0.8.1] - 2015-10-22
### Added
- Add condition to ignore skipUnchangedTerm for empty text. ([#210](https://github.com/yuku-t/jquery-textcomplete/pull/210))
## [0.8.0] - 2015-08-31
### Changed
- If undefined is returned from a replace callback dont replace the text. ([#204](https://github.com/yuku-t/jquery-textcomplete/pull/204))
## [0.7.3] - 2015-08-27
### Added
- Add `Strategy#el` and `Strategy#$el` which returns current input/textarea element and corresponding jquery object respectively.
## [0.7.2] - 2015-08-26
### Fixed
- Reset \_term after selected ([#170](https://github.com/yuku-t/jquery-textcomplete/pull/170))
## [0.7.1] - 2015-08-19
### Changed
- Remove RTL support because of some bugs.
## [0.7.0] - 2015-07-02
### Add
- Add support for a "no results" message like the header/footer. ([#179](https://github.com/yuku-t/jquery-textcomplete/pull/179))
- Yield the search term to the template function. ([#177](https://github.com/yuku-t/jquery-textcomplete/pull/177))
- Add amd wrapper. ([#167](https://github.com/yuku-t/jquery-textcomplete/pull/167))
- Add touch devices support. ([#163](https://github.com/yuku-t/jquery-textcomplete/pull/163))
### Changed
- Stop sharing a dropdown element.
## [0.6.1] - 2015-06-30
### Fixed
- Fix bug that Dropdown.\_fitToBottom does not consider window scroll
## [0.6.0] - 2015-06-30
### Added
- Now dropdown elements have "textcomplete-dropdown" class.
## [0.5.2] - 2015-06-29
### Fixed
- Keep dropdown list in browser window. ([#172](https://github.com/yuku-t/jquery-textcomplete/pull/172))
## [0.5.1] - 2015-06-08
### Changed
- Now a replace function is invoked with a user event.
## [0.5.0] - 2015-06-08
### Added
- Support `onKeydown` option.
## [0.4.0] - 2015-03-10
### Added
- Publish to [npmjs](https://www.npmjs.com/package/jquery-textcomplete).
- Support giving a function which returns a regexp to `match` option for dynamic matching.
## [0.3.9] - 2015-03-03
### Fixed
- Deactivate dropdown on escape. ([#155](https://github.com/yuku-t/jquery-textcomplete/pull/155))
## [0.3.8] - 2015-02-26
### Fixed
- Fix completion with enter key. ([#154](https://github.com/yuku-t/jquery-textcomplete/pull/154))
- Fix empty span node is inserted. ([#153](https://github.com/yuku-t/jquery-textcomplete/pull/153))
## [0.3.7] - 2015-01-21
### Added
- Support input([type=text]. [#149](https://github.com/yuku-t/jquery-textcomplete/pull/149))
## [0.3.6] - 2014-12-11
### Added
- Support element.contentEditable compatibility check. ([#147](https://github.com/yuku-t/jquery-textcomplete/pull/147))
### Fixed
- Fixes the fire function for events with additional parameters. ([#145](https://github.com/yuku-t/jquery-textcomplete/pull/145))
## [0.3.5] - 2014-12-11
### Added
- Adds functionality to complete selection on space key. ([#141](https://github.com/yuku-t/jquery-textcomplete/pull/141))
### Fixed
- Loading script in head and destroy method bugfixes. ([#143](https://github.com/yuku-t/jquery-textcomplete/pull/143))
## [0.3.4] - 2014-12-03
### Fixed
- Fix error when destroy is called before the field is focused. ([#138](https://github.com/yuku-t/jquery-textcomplete/pull/138))
- Fix IE bug where it would only trigger when tha carrot was at the end of the line. ([#133](https://github.com/yuku-t/jquery-textcomplete/pull/133))
## [0.3.3] - 2014-09-25
### Added
- Add `className` option.
- Add `match` as the third argument of a search function.
### Fixed
- Ignore `.textcomplete('destory')` on non-initialized elements. ([#118](https://github.com/yuku-t/jquery-textcomplete/pull/118))
- Trigger completer with the current text by default. ([#119](https://github.com/yuku-t/jquery-textcomplete/pull/119))
- Hide dropdown before destroying it. ([#120](https://github.com/yuku-t/jquery-textcomplete/pull/120))
- Don't throw an exception even if a jquery click event is manually triggered. ([#121](https://github.com/yuku-t/jquery-textcomplete/pull/121))
## [0.3.2] - 2014-09-16
### Added
- Add `IETextarea` adapter which supports IE8
- Add `idProperty` option.
- Add `adapter` option.
### Changed
- Rename `Input` as `Adapter`.
## [0.3.1] - 2014-09-10
### Added
- Add `context` strategy option.
- Add `debounce` option.
### Changed
- Recycle `.dropdown-menu` element if available.
## [0.3.0] - 2014-09-10
### Added
- Consider the `tab-size` of textarea.
- Add `zIndex` option.
### Fixed
- Revive `header` and `footer` options.
- Revive `height` option.
## [0.3.0-beta2] - 2014-09-09
### Fixed
- Make sure that all demos work fine.
## [0.3.0-beta1] - 2014-08-31
### Fixed
- Huge refactoring.
## [0.2.6] - 2014-08-16
### Fixed
- Repair contenteditable.
## [0.2.5] - 2014-08-07
### Added
- Enhance contenteditable support. ([#98](https://github.com/yuku-t/jquery-textcomplete/pull/98))
- Support absolute left/right placement. ([#96](https://github.com/yuku-t/jquery-textcomplete/pull/96))
- Support absolute height, scrollbar, pageup and pagedown. ([#87](https://github.com/yuku-t/jquery-textcomplete/pull/87))
## [0.2.4] - 2014-07-02
### Fixed
- Fix horizonal position on contentEditable elements. ([#92](https://github.com/yuku-t/jquery-textcomplete/pull/92))
## [0.2.3] - 2014-06-24
### Added
- Option to supply list view position function. ([#88](https://github.com/yuku-t/jquery-textcomplete/pull/88))
## [0.2.2] - 2014-06-08
### Added
- Append dropdown element to body element by default.
- Tiny refactoring. [#84]
- Ignore tab key when modifier keys are being pushed. ([#85](https://github.com/yuku-t/jquery-textcomplete/pull/85))
- Manual triggering.
## [0.2.1] - 2014-05-15
### Added
- Support `appendTo` option.
- `header` and `footer` supports a function.
### Changed
- Remove textcomplate-wrapper element.
## [0.2.0] - 2014-05-02
### Added
- Contenteditable support.
- Several bugfixes.
- Support `header` and `footer` setting.
## [0.1.4.1] - 2014-04-04
### Added
- Support placement option.
- Emacs-style prev/next keybindings.
- Replay searchFunc for the last term on slow network env.
### Fixed
- Several bugfixes.
## [0.1.3] - 2014-04-07
### Added
- Support RTL positioning.
### Fixed
- Several bugfixes.
## [0.1.2] - 2014-02-08
### Added
- Enable to append strategies on the fly.
- Enable to stop autocompleting.
- Enable to apply multiple textareas at once.
- Don't show popup on pressing arrow up and down keys.
- Hide dropdown by pressing ESC key.
- Prevent showing a dropdown when it just autocompleted.
## [0.1.1] - 2014-02-02
### Added
- Introduce `textComplete:show`, `textComplete:hide` and `textComplete:select` events.
## [0.1.0] - 2013-10-28
### Added
- Now strategies argument is an Array of strategy objects.
## [0.0.4] - 2013-10-28
### Added
- Up and Down arrows cycle instead of exit.
- Support Zepto.
- Support jQuery.overlay.
### Fixed
- Several bugfixes.
## [0.0.3] - 2013-09-11
### Added
- Some performance improvement.
- Implement lazy callbacking on search function.
## [0.0.2] - 2013-09-08
### Added
- Support IE8.
- Some performance improvement.
- Implement cache option.
## 0.0.1 - 2013-09-02
### Added
- Initial release.
[Unreleased]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.4...HEAD
[1.3.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.3...v1.3.4
[1.3.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.2...v1.3.3
[1.3.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.1...v1.3.2
[1.3.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.0...v1.3.1
[1.3.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.2.2...v1.3.0
[1.2.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.2.1...v1.2.2
[1.2.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.2.0...v1.2.1
[1.2.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.8.2...v1.0.0
[0.8.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.8.1...v0.8.2
[0.8.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.8.0...v0.8.1
[0.8.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.3...v0.8.0
[0.7.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.2...v0.7.3
[0.7.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.6.1...v0.7.0
[0.6.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.5.2...v0.6.0
[0.5.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.9...v0.4.0
[0.3.9]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.8...v0.3.9
[0.3.8]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.7...v0.3.8
[0.3.7]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.6...v0.3.7
[0.3.6]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.4...v0.3.5
[0.3.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.3...v0.3.4
[0.3.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.0-beta2...v0.3.0
[0.3.0-beta2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.0-beta1...v0.3.0-beta2
[0.3.0-beta1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.6...v0.3.0-beta1
[0.2.6]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.4.1...v0.2.0
[0.1.4.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.3...v0.1.4.1
[0.1.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.4...v0.1.0
[0.0.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.3...v0.0.4
[0.0.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.2...v0.0.3
[0.0.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.1...v0.0.2

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2014 Yuku Takahashi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,46 @@
# Autocomplete for Textarea
[![npm version](https://badge.fury.io/js/jquery-textcomplete.svg)](http://badge.fury.io/js/jquery-textcomplete)
[![Bower version](https://badge.fury.io/bo/jquery-textcomplete.svg)](http://badge.fury.io/bo/jquery-textcomplete)
[![Analytics](https://ga-beacon.appspot.com/UA-4932407-14/jquery-textcomplete/readme)](https://github.com/igrigorik/ga-beacon)
Introduces autocompleting power to textareas, like a GitHub comment form has.
![Demo](http://yuku-t.com/jquery-textcomplete/media/images/demo.gif)
[Demo](http://yuku-t.com/jquery-textcomplete/).
## Synopsis
```js
$('textarea').textcomplete([{
match: /(^|\b)(\w{2,})$/,
search: function (term, callback) {
var words = ['google', 'facebook', 'github', 'microsoft', 'yahoo'];
callback($.map(words, function (word) {
return word.indexOf(term) === 0 ? word : null;
}));
},
replace: function (word) {
return word + ' ';
}
}]);
```
## Dependencies
- jQuery (>= 1.7.0) OR Zepto (>= 1.0)
## Documents
See [doc](https://github.com/yuku-t/jquery-textcomplete/tree/master/doc) dir.
## License
Licensed under the MIT License.
## Contributors
Patches and code improvements were contributed by:
https://github.com/yuku-t/jquery-textcomplete/graphs/contributors

View file

@ -0,0 +1,33 @@
/* Sample */
.dropdown-menu {
border: 1px solid #ddd;
background-color: white;
}
.dropdown-menu li {
border-top: 1px solid #ddd;
padding: 2px 5px;
}
.dropdown-menu li:first-child {
border-top: none;
}
.dropdown-menu li:hover,
.dropdown-menu .active {
background-color: rgb(110, 183, 219);
}
/* SHOULD not modify */
.dropdown-menu {
list-style: none;
padding: 0;
margin: 0;
}
.dropdown-menu a:hover {
cursor: pointer;
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +0,0 @@
This is jquery.autocomplete from
http://www.devbridge.com/projects/autocomplete/jquery/

View file

@ -1,395 +0,0 @@
/**
* Ajax Autocomplete for jQuery, version 1.1.3
* (c) 2010 Tomas Kirda
*
* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
* For details, see the web site: http://www.devbridge.com/projects/autocomplete/jquery/
*
* Last Review: 04/19/2010
* Heavily modified for contact completion in Friendica (add photos, hover tips. etc.) 11-May-2012 mike@macgirvin.com
*/
/*jslint onevar: true, evil: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
/*global window: true, document: true, clearInterval: true, setInterval: true, jQuery: true */
(function($) {
var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');
function fnFormatResult(value, data, currentValue) {
var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
return value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
}
function Autocomplete(el, options) {
this.el = $(el);
this.el.attr('autocomplete', 'off');
this.suggestions = [];
this.data = [];
this.badQueries = [];
this.selectedIndex = -1;
this.currentValue = this.el.val();
this.intervalId = 0;
this.cachedResponse = [];
this.onChangeInterval = null;
this.ignoreValueChange = false;
this.serviceUrl = options.serviceUrl;
this.isLocal = false;
this.options = {
autoSubmit: false,
minChars: 1,
maxHeight: 300,
deferRequestBy: 0,
width: 0,
highlight: true,
params: {},
fnFormatResult: fnFormatResult,
delimiter: null,
zIndex: 9999
};
this.initialize();
this.setOptions(options);
}
$.fn.autocomplete = function(options) {
return new Autocomplete(this.get(0)||$('<input />'), options);
};
Autocomplete.prototype = {
killerFn: null,
initialize: function() {
var me, uid, autocompleteElId;
me = this;
uid = Math.floor(Math.random()*0x100000).toString(16);
autocompleteElId = 'Autocomplete_' + uid;
this.killerFn = function(e) {
if ($(e.target).parents('.autocomplete').size() === 0) {
me.killSuggestions();
me.disableKillerFn();
}
};
if (!this.options.width) { this.options.width = this.el.width(); }
this.mainContainerId = 'AutocompleteContainter_' + uid;
$('<div id="' + this.mainContainerId + '" style="position:absolute;z-index:9999;"><div class="autocomplete-w1"><div class="autocomplete" id="' + autocompleteElId + '" style="display:none; width:300px;"></div></div></div>').appendTo('body');
this.container = $('#' + autocompleteElId);
this.fixPosition();
if (window.opera) {
this.el.keypress(function(e) { me.onKeyPress(e); });
} else {
this.el.keydown(function(e) { me.onKeyPress(e); });
}
this.el.keyup(function(e) { me.onKeyUp(e); });
this.el.blur(function() { me.enableKillerFn(); });
this.el.focus(function() { me.fixPosition(); });
},
setOptions: function(options){
var o = this.options;
$.extend(o, options);
if(o.lookup){
this.isLocal = true;
if($.isArray(o.lookup)){ o.lookup = { suggestions:o.lookup, data:[] }; }
}
$('#'+this.mainContainerId).css({ zIndex:o.zIndex });
this.container.css({ maxHeight: o.maxHeight + 'px', width:o.width });
},
clearCache: function(){
this.cachedResponse = [];
this.badQueries = [];
},
disable: function(){
this.disabled = true;
},
enable: function(){
this.disabled = false;
},
fixPosition: function() {
var offset = this.el.offset();
$('#' + this.mainContainerId).css({ top: (offset.top + this.el.innerHeight()) + 'px', left: offset.left + 'px' });
},
enableKillerFn: function() {
var me = this;
$(document).bind('click', me.killerFn);
},
disableKillerFn: function() {
var me = this;
$(document).unbind('click', me.killerFn);
},
killSuggestions: function() {
var me = this;
this.stopKillSuggestions();
this.intervalId = window.setInterval(function() { me.hide(); me.stopKillSuggestions(); }, 300);
},
stopKillSuggestions: function() {
window.clearInterval(this.intervalId);
},
onKeyPress: function(e) {
if (this.disabled || !this.enabled) { return; }
// return will exit the function
// and event will not be prevented
switch (e.keyCode) {
case 27: //KEY_ESC:
this.el.val(this.currentValue);
this.hide();
break;
case 9: //KEY_TAB:
case 13: //KEY_RETURN:
if (this.selectedIndex === -1) {
this.hide();
return;
}
this.select(this.selectedIndex);
if(e.keyCode === 9){ return; }
break;
case 38: //KEY_UP:
this.moveUp();
break;
case 40: //KEY_DOWN:
this.moveDown();
break;
default:
return;
}
e.stopImmediatePropagation();
e.preventDefault();
},
onKeyUp: function(e) {
if(this.disabled){ return; }
switch (e.keyCode) {
case 38: //KEY_UP:
case 40: //KEY_DOWN:
return;
}
clearInterval(this.onChangeInterval);
if (this.currentValue !== this.el.val()) {
if (this.options.deferRequestBy > 0) {
// Defer lookup in case when value changes very quickly:
var me = this;
this.onChangeInterval = setInterval(function() { me.onValueChange(); }, this.options.deferRequestBy);
} else {
this.onValueChange();
}
}
},
onValueChange: function() {
clearInterval(this.onChangeInterval);
this.currentValue = this.el.val();
var q = this.getQuery(this.currentValue);
this.selectedIndex = -1;
if (this.ignoreValueChange) {
this.ignoreValueChange = false;
return;
}
if (q === '' || q.length < this.options.minChars) {
this.hide();
} else {
this.getSuggestions(q);
}
},
getQuery: function(val) {
var d, arr;
d = this.options.delimiter;
if (!d) { return $.trim(val); }
arr = val.split(d);
return $.trim(arr[arr.length - 1]);
},
getSuggestionsLocal: function(q) {
var ret, arr, len, val, i;
arr = this.options.lookup;
len = arr.suggestions.length;
ret = { suggestions:[], data:[] };
q = q.toLowerCase();
for(i=0; i< len; i++){
val = arr.suggestions[i];
if(val.toLowerCase().indexOf(q) === 0){
ret.suggestions.push(val);
ret.data.push(arr.data[i]);
}
}
return ret;
},
getSuggestions: function(q) {
var cr, me;
cr = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q];
if (cr && $.isArray(cr.suggestions)) {
this.suggestions = cr.suggestions;
this.data = cr.data;
this.suggest();
} else if (!this.isBadQuery(q)) {
me = this;
me.options.params.query = q;
$.get(this.serviceUrl, me.options.params, function(txt) { me.processResponse(txt); }, 'text');
}
},
isBadQuery: function(q) {
var i = this.badQueries.length;
while (i--) {
if (q.indexOf(this.badQueries[i]) === 0) { return true; }
}
return false;
},
hide: function() {
this.enabled = false;
this.selectedIndex = -1;
this.container.hide();
},
suggest: function() {
if (this.suggestions.length === 0) {
this.hide();
return;
}
var me, len, div, f, v, i, s, mOver, mClick, l, img;
me = this;
len = this.suggestions.length;
f = this.options.fnFormatResult;
v = this.getQuery(this.currentValue);
mOver = function(xi) { return function() { me.activate(xi); }; };
mClick = function(xi) { return function() { me.select(xi); }; };
this.container.hide().empty();
for (i = 0; i < len; i++) {
s = this.suggestions[i];
l = this.links[i];
img = '<img height="24" width="24" src="' + this.photos[i] + '" alt="' + s + '" />&nbsp;';
div = $((me.selectedIndex === i ? '<div class="selected"' : '<div') + ' title="' + l + '">' + img + f(s, this.data[i], v) + '</div>');
div.mouseover(mOver(i));
div.click(mClick(i));
this.container.append(div);
}
this.enabled = true;
this.container.show();
},
processResponse: function(text) {
var response;
try {
response = eval('(' + text + ')');
} catch (err) { return; }
if (!$.isArray(response.data)) { response.data = []; }
if(!this.options.noCache){
this.cachedResponse[response.query] = response;
if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
}
if (response.query === this.getQuery(this.currentValue)) {
this.photos = response.photos;
this.links = response.links;
this.suggestions = response.suggestions;
this.data = response.data;
this.suggest();
}
},
activate: function(index) {
var divs, activeItem;
divs = this.container.children();
// Clear previous selection:
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
$(divs.get(this.selectedIndex)).removeClass();
}
this.selectedIndex = index;
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
activeItem = divs.get(this.selectedIndex);
$(activeItem).addClass('selected');
}
return activeItem;
},
deactivate: function(div, index) {
div.className = '';
if (this.selectedIndex === index) { this.selectedIndex = -1; }
},
select: function(i) {
var selectedValue, f;
selectedValue = this.suggestions[i];
if (selectedValue) {
this.el.val(selectedValue);
if (this.options.autoSubmit) {
f = this.el.parents('form');
if (f.length > 0) { f.get(0).submit(); }
}
this.ignoreValueChange = true;
this.hide();
this.onSelect(i);
}
},
moveUp: function() {
if (this.selectedIndex === -1) { return; }
if (this.selectedIndex === 0) {
this.container.children().get(0).className = '';
this.selectedIndex = -1;
this.el.val(this.currentValue);
return;
}
this.adjustScroll(this.selectedIndex - 1);
},
moveDown: function() {
if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
this.adjustScroll(this.selectedIndex + 1);
},
adjustScroll: function(i) {
var activeItem, offsetTop, upperBound, lowerBound;
activeItem = this.activate(i);
offsetTop = activeItem.offsetTop;
upperBound = this.container.scrollTop();
lowerBound = upperBound + this.options.maxHeight - 25;
if (offsetTop < upperBound) {
this.container.scrollTop(offsetTop);
} else if (offsetTop > lowerBound) {
this.container.scrollTop(offsetTop - this.options.maxHeight + 25);
}
this.el.val(this.getValue(this.suggestions[i]));
},
onSelect: function(i) {
var me, fn, s, d;
me = this;
fn = me.options.onSelect;
s = me.suggestions[i];
d = me.data[i];
me.el.val(me.getValue(s));
if ($.isFunction(fn)) { fn(s, d, me.el); }
},
getValue: function(value){
var del, currVal, arr, me;
me = this;
del = me.options.delimiter;
if (!del) { return value; }
currVal = me.currentValue;
arr = currVal.split(del);
if (arr.length === 1) { return value; }
return currVal.substr(0, currVal.length - arr[arr.length - 1].length) + value;
}
};
}(jQuery));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,390 +0,0 @@
/**
* Ajax Autocomplete for jQuery, version 1.1.3
* (c) 2010 Tomas Kirda
*
* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
* For details, see the web site: http://www.devbridge.com/projects/autocomplete/jquery/
*
* Last Review: 04/19/2010
*/
/*jslint onevar: true, evil: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
/*global window: true, document: true, clearInterval: true, setInterval: true, jQuery: true */
(function($) {
var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');
function fnFormatResult(value, data, currentValue) {
var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
return value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
}
function Autocomplete(el, options) {
this.el = $(el);
this.el.attr('autocomplete', 'off');
this.suggestions = [];
this.data = [];
this.badQueries = [];
this.selectedIndex = -1;
this.currentValue = this.el.val();
this.intervalId = 0;
this.cachedResponse = [];
this.onChangeInterval = null;
this.ignoreValueChange = false;
this.serviceUrl = options.serviceUrl;
this.isLocal = false;
this.options = {
autoSubmit: false,
minChars: 1,
maxHeight: 300,
deferRequestBy: 0,
width: 0,
highlight: true,
params: {},
fnFormatResult: fnFormatResult,
delimiter: null,
zIndex: 9999
};
this.initialize();
this.setOptions(options);
}
$.fn.autocomplete = function(options) {
return new Autocomplete(this.get(0)||$('<input />'), options);
};
Autocomplete.prototype = {
killerFn: null,
initialize: function() {
var me, uid, autocompleteElId;
me = this;
uid = Math.floor(Math.random()*0x100000).toString(16);
autocompleteElId = 'Autocomplete_' + uid;
this.killerFn = function(e) {
if ($(e.target).parents('.autocomplete').size() === 0) {
me.killSuggestions();
me.disableKillerFn();
}
};
if (!this.options.width) { this.options.width = this.el.width(); }
this.mainContainerId = 'AutocompleteContainter_' + uid;
$('<div id="' + this.mainContainerId + '" style="position:absolute;z-index:9999;"><div class="autocomplete-w1"><div class="autocomplete" id="' + autocompleteElId + '" style="display:none; width:300px;"></div></div></div>').appendTo('body');
this.container = $('#' + autocompleteElId);
this.fixPosition();
if (window.opera) {
this.el.keypress(function(e) { me.onKeyPress(e); });
} else {
this.el.keydown(function(e) { me.onKeyPress(e); });
}
this.el.keyup(function(e) { me.onKeyUp(e); });
this.el.blur(function() { me.enableKillerFn(); });
this.el.focus(function() { me.fixPosition(); });
},
setOptions: function(options){
var o = this.options;
$.extend(o, options);
if(o.lookup){
this.isLocal = true;
if($.isArray(o.lookup)){ o.lookup = { suggestions:o.lookup, data:[] }; }
}
$('#'+this.mainContainerId).css({ zIndex:o.zIndex });
this.container.css({ maxHeight: o.maxHeight + 'px', width:o.width });
},
clearCache: function(){
this.cachedResponse = [];
this.badQueries = [];
},
disable: function(){
this.disabled = true;
},
enable: function(){
this.disabled = false;
},
fixPosition: function() {
var offset = this.el.offset();
$('#' + this.mainContainerId).css({ top: (offset.top + this.el.innerHeight()) + 'px', left: offset.left + 'px' });
},
enableKillerFn: function() {
var me = this;
$(document).bind('click', me.killerFn);
},
disableKillerFn: function() {
var me = this;
$(document).unbind('click', me.killerFn);
},
killSuggestions: function() {
var me = this;
this.stopKillSuggestions();
this.intervalId = window.setInterval(function() { me.hide(); me.stopKillSuggestions(); }, 300);
},
stopKillSuggestions: function() {
window.clearInterval(this.intervalId);
},
onKeyPress: function(e) {
if (this.disabled || !this.enabled) { return; }
// return will exit the function
// and event will not be prevented
switch (e.keyCode) {
case 27: //KEY_ESC:
this.el.val(this.currentValue);
this.hide();
break;
case 9: //KEY_TAB:
case 13: //KEY_RETURN:
if (this.selectedIndex === -1) {
this.hide();
return;
}
this.select(this.selectedIndex);
if(e.keyCode === 9){ return; }
break;
case 38: //KEY_UP:
this.moveUp();
break;
case 40: //KEY_DOWN:
this.moveDown();
break;
default:
return;
}
e.stopImmediatePropagation();
e.preventDefault();
},
onKeyUp: function(e) {
if(this.disabled){ return; }
switch (e.keyCode) {
case 38: //KEY_UP:
case 40: //KEY_DOWN:
return;
}
clearInterval(this.onChangeInterval);
if (this.currentValue !== this.el.val()) {
if (this.options.deferRequestBy > 0) {
// Defer lookup in case when value changes very quickly:
var me = this;
this.onChangeInterval = setInterval(function() { me.onValueChange(); }, this.options.deferRequestBy);
} else {
this.onValueChange();
}
}
},
onValueChange: function() {
clearInterval(this.onChangeInterval);
this.currentValue = this.el.val();
var q = this.getQuery(this.currentValue);
this.selectedIndex = -1;
if (this.ignoreValueChange) {
this.ignoreValueChange = false;
return;
}
if (q === '' || q.length < this.options.minChars) {
this.hide();
} else {
this.getSuggestions(q);
}
},
getQuery: function(val) {
var d, arr;
d = this.options.delimiter;
if (!d) { return $.trim(val); }
arr = val.split(d);
return $.trim(arr[arr.length - 1]);
},
getSuggestionsLocal: function(q) {
var ret, arr, len, val, i;
arr = this.options.lookup;
len = arr.suggestions.length;
ret = { suggestions:[], data:[] };
q = q.toLowerCase();
for(i=0; i< len; i++){
val = arr.suggestions[i];
if(val.toLowerCase().indexOf(q) === 0){
ret.suggestions.push(val);
ret.data.push(arr.data[i]);
}
}
return ret;
},
getSuggestions: function(q) {
var cr, me;
cr = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q];
if (cr && $.isArray(cr.suggestions)) {
this.suggestions = cr.suggestions;
this.data = cr.data;
this.suggest();
} else if (!this.isBadQuery(q)) {
me = this;
me.options.params.query = q;
$.get(this.serviceUrl, me.options.params, function(txt) { me.processResponse(txt); }, 'text');
}
},
isBadQuery: function(q) {
var i = this.badQueries.length;
while (i--) {
if (q.indexOf(this.badQueries[i]) === 0) { return true; }
}
return false;
},
hide: function() {
this.enabled = false;
this.selectedIndex = -1;
this.container.hide();
},
suggest: function() {
if (this.suggestions.length === 0) {
this.hide();
return;
}
var me, len, div, f, v, i, s, mOver, mClick;
me = this;
len = this.suggestions.length;
f = this.options.fnFormatResult;
v = this.getQuery(this.currentValue);
mOver = function(xi) { return function() { me.activate(xi); }; };
mClick = function(xi) { return function() { me.select(xi); }; };
this.container.hide().empty();
for (i = 0; i < len; i++) {
s = this.suggestions[i];
div = $((me.selectedIndex === i ? '<div class="selected"' : '<div') + ' title="' + s + '">' + f(s, this.data[i], v) + '</div>');
div.mouseover(mOver(i));
div.click(mClick(i));
this.container.append(div);
}
this.enabled = true;
this.container.show();
},
processResponse: function(text) {
var response;
try {
response = eval('(' + text + ')');
} catch (err) { return; }
if (!$.isArray(response.data)) { response.data = []; }
if(!this.options.noCache){
this.cachedResponse[response.query] = response;
if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
}
if (response.query === this.getQuery(this.currentValue)) {
this.suggestions = response.suggestions;
this.data = response.data;
this.suggest();
}
},
activate: function(index) {
var divs, activeItem;
divs = this.container.children();
// Clear previous selection:
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
$(divs.get(this.selectedIndex)).removeClass();
}
this.selectedIndex = index;
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
activeItem = divs.get(this.selectedIndex);
$(activeItem).addClass('selected');
}
return activeItem;
},
deactivate: function(div, index) {
div.className = '';
if (this.selectedIndex === index) { this.selectedIndex = -1; }
},
select: function(i) {
var selectedValue, f;
selectedValue = this.suggestions[i];
if (selectedValue) {
this.el.val(selectedValue);
if (this.options.autoSubmit) {
f = this.el.parents('form');
if (f.length > 0) { f.get(0).submit(); }
}
this.ignoreValueChange = true;
this.hide();
this.onSelect(i);
}
},
moveUp: function() {
if (this.selectedIndex === -1) { return; }
if (this.selectedIndex === 0) {
this.container.children().get(0).className = '';
this.selectedIndex = -1;
this.el.val(this.currentValue);
return;
}
this.adjustScroll(this.selectedIndex - 1);
},
moveDown: function() {
if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
this.adjustScroll(this.selectedIndex + 1);
},
adjustScroll: function(i) {
var activeItem, offsetTop, upperBound, lowerBound;
activeItem = this.activate(i);
offsetTop = activeItem.offsetTop;
upperBound = this.container.scrollTop();
lowerBound = upperBound + this.options.maxHeight - 25;
if (offsetTop < upperBound) {
this.container.scrollTop(offsetTop);
} else if (offsetTop > lowerBound) {
this.container.scrollTop(offsetTop - this.options.maxHeight + 25);
}
this.el.val(this.getValue(this.suggestions[i]));
},
onSelect: function(i) {
var me, fn, s, d;
me = this;
fn = me.options.onSelect;
s = me.suggestions[i];
d = me.data[i];
me.el.val(me.getValue(s));
if ($.isFunction(fn)) { fn(s, d, me.el); }
},
getValue: function(value){
var del, currVal, arr, me;
me = this;
del = me.options.delimiter;
if (!del) { return value; }
currVal = me.currentValue;
arr = currVal.split(del);
if (arr.length === 1) { return value; }
return currVal.substr(0, currVal.length - arr[arr.length - 1].length) + value;
}
};
}(jQuery));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -1,6 +0,0 @@

.autocomplete-w1 { background:url(img/shadow.png) no-repeat bottom right; position:absolute; top:0px; left:0px; margin:8px 0 0 6px; /* IE6 fix: */ _background:none; _margin:0; }
.autocomplete { border:1px solid #999; background:#FFF; cursor:default; text-align:left; max-height:350px; overflow:auto; margin:-6px 6px 6px -6px; /* IE6 specific: */ _height:350px; _margin:0; _overflow-x:hidden; }
.autocomplete .selected { background:#F0F0F0; }
.autocomplete div { padding:2px 5px; white-space:nowrap; }
.autocomplete strong { font-weight:normal; color:#3399FF; }

View file

@ -375,7 +375,7 @@ class LightOpenID
$server = $server[1];
if (isset($delegate[2])) $this->identity = trim($delegate[2]);
$this->version = 2;
logger('Server: ' . $server);
#logger('Server: ' . $server);
$this->server = $server;
return $server;
}

View file

@ -165,7 +165,7 @@ function admin_content(&$a) {
/* get plugins admin page */
$r = q("SELECT `name` FROM `addon` WHERE `plugin_admin`=1 ORDER BY `name`");
$r = q("SELECT `name` FROM `addon` WHERE `plugin_admin` = 1 ORDER BY `name`");
$aside_tools['plugins_admin']=array();
foreach ($r as $h){
$plugin =$h['name'];
@ -271,7 +271,7 @@ function admin_page_federation(&$a) {
// displayed on the stats page.
$platforms = array('Friendica', 'Diaspora', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet');
$colors = array('Friendica' => '#ffc018', // orange from the logo
'Diaspora' => '#a1a1a1', // logo is black and white, makes a gray
'Diaspora' => '#a1a1a1', // logo is black and white, makes a gray
'%%red%%' => '#c50001', // fire red from the logo
'Hubzilla' => '#43488a', // blue from the logo
'GNU Social'=> '#a22430', // dark red from the logo
@ -282,17 +282,17 @@ function admin_page_federation(&$a) {
foreach ($platforms as $p) {
// get a total count for the platform, the name and version of the
// highest version and the protocol tpe
$c = q('SELECT count(*) AS total, platform, network, version FROM gserver
WHERE platform LIKE "%s" AND last_contact > last_failure AND `version` != ""
ORDER BY version ASC;', $p);
$c = q('SELECT COUNT(*) AS `total`, `platform`, `network`, `version` FROM `gserver`
WHERE `platform` LIKE "%s" AND `last_contact` > `last_failure` AND `version` != ""
ORDER BY `version` ASC;', $p);
$total = $total + $c[0]['total'];
// what versions for that platform do we know at all?
// again only the active nodes
$v = q('SELECT count(*) AS total, version FROM gserver
WHERE last_contact > last_failure AND platform LIKE "%s" AND `version` != ""
GROUP BY version
ORDER BY version;', $p);
$v = q('SELECT COUNT(*) AS `total`, `version` FROM `gserver`
WHERE `last_contact` > `last_failure` AND `platform` LIKE "%s" AND `version` != ""
GROUP BY `version`
ORDER BY `version`;', $p);
//
// clean up version numbers
@ -386,7 +386,10 @@ function admin_page_federation(&$a) {
*/
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;");
$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(
@ -416,7 +419,7 @@ function admin_page_queue(&$a) {
* @return string
*/
function admin_page_summary(&$a) {
$r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
$r = q("SELECT `page-flags`, COUNT(`uid`) AS `count` FROM `user` GROUP BY `page-flags`");
$accounts = array(
array(t('Normal Account'), 0),
array(t('Soapbox Account'), 0),
@ -431,18 +434,25 @@ function admin_page_summary(&$a) {
logger('accounts: '.print_r($accounts,true),LOGGER_DATA);
$r = q("SELECT COUNT(id) as `count` FROM `register`");
$r = q("SELECT COUNT(`id`) AS `count` FROM `register`");
$pending = $r[0]['count'];
$r = q("select count(*) as total from deliverq where 1");
$r = q("SELECT COUNT(*) AS `total` FROM `deliverq` WHERE 1");
$deliverq = (($r) ? $r[0]['total'] : 0);
$r = q("select count(*) as total from queue where 1");
$r = q("SELECT COUNT(*) AS `total` FROM `queue` WHERE 1");
$queue = (($r) ? $r[0]['total'] : 0);
if (get_config('system','worker')) {
$r = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE 1");
$workerqueue = (($r) ? $r[0]['total'] : 0);
} else {
$workerqueue = 0;
}
// We can do better, but this is a quick queue status
$queues = array('label' => t('Message queues'), 'deliverq' => $deliverq, 'queue' => $queue);
$queues = array('label' => t('Message queues'), 'deliverq' => $deliverq, 'queue' => $queue, 'workerq' => $workerqueue);
$t = get_markup_template("admin_summary.tpl");
@ -492,6 +502,10 @@ function admin_page_site_post(&$a) {
$old_url = $a->get_baseurl(true);
// Generate host names for relocation the addresses in the format user@address.tld
$new_host = str_replace("http://", "@", normalise_link($new_url));
$old_host = str_replace("http://", "@", normalise_link($old_url));
function update_table($table_name, $fields, $old_url, $new_url) {
global $db, $a;
@ -516,18 +530,23 @@ function admin_page_site_post(&$a) {
}
// update tables
// update profile links in the format "http://server.tld"
update_table("profile", array('photo', 'thumb'), $old_url, $new_url);
update_table("term", array('url'), $old_url, $new_url);
update_table("contact", array('photo','thumb','micro','url','nurl','request','notify','poll','confirm','poco'), $old_url, $new_url);
update_table("gcontact", array('photo','url','nurl','server_url'), $old_url, $new_url);
update_table("item", array('owner-link','owner-avatar','author-name','author-link','author-avatar','body','plink','tag'), $old_url, $new_url);
update_table("contact", array('photo','thumb','micro','url','nurl','alias','request','notify','poll','confirm','poco', 'avatar'), $old_url, $new_url);
update_table("gcontact", array('url','nurl','photo','server_url','notify','alias'), $old_url, $new_url);
update_table("item", array('owner-link','owner-avatar','author-link','author-avatar','body','plink','tag'), $old_url, $new_url);
// update profile addresses in the format "user@server.tld"
update_table("contact", array('addr'), $old_host, $new_host);
update_table("gcontact", array('connect','addr'), $old_host, $new_host);
// update config
$a->set_baseurl($new_url);
set_config('system','url',$new_url);
// send relocate
$users = q("SELECT uid FROM user WHERE account_removed = 0 AND account_expired = 0");
$users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0");
foreach ($users as $user) {
proc_run('php', 'include/notifier.php', 'relocate', $user['uid']);
@ -542,10 +561,10 @@ function admin_page_site_post(&$a) {
$sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : '');
$hostname = ((x($_POST,'hostname')) ? notags(trim($_POST['hostname'])) : '');
$sender_email = ((x($_POST,'sender_email')) ? notags(trim($_POST['sender_email'])) : '');
$banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false);
$banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false);
$shortcut_icon = ((x($_POST,'shortcut_icon')) ? notags(trim($_POST['shortcut_icon'])) : '');
$touch_icon = ((x($_POST,'touch_icon')) ? notags(trim($_POST['touch_icon'])) : '');
$info = ((x($_POST,'info')) ? trim($_POST['info']) : false);
$info = ((x($_POST,'info')) ? trim($_POST['info']) : false);
$language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : '');
$theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : '');
$theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : '');
@ -631,41 +650,41 @@ function admin_page_site_post(&$a) {
if($ssl_policy != intval(get_config('system','ssl_policy'))) {
if($ssl_policy == SSL_POLICY_FULL) {
q("update `contact` set
`url` = replace(`url` , 'http:' , 'https:'),
`photo` = replace(`photo` , 'http:' , 'https:'),
`thumb` = replace(`thumb` , 'http:' , 'https:'),
`micro` = replace(`micro` , 'http:' , 'https:'),
`request` = replace(`request`, 'http:' , 'https:'),
`notify` = replace(`notify` , 'http:' , 'https:'),
`poll` = replace(`poll` , 'http:' , 'https:'),
`confirm` = replace(`confirm`, 'http:' , 'https:'),
`poco` = replace(`poco` , 'http:' , 'https:')
where `self` = 1"
q("UPDATE `contact` SET
`url` = REPLACE(`url` , 'http:' , 'https:'),
`photo` = REPLACE(`photo` , 'http:' , 'https:'),
`thumb` = REPLACE(`thumb` , 'http:' , 'https:'),
`micro` = REPLACE(`micro` , 'http:' , 'https:'),
`request` = REPLACE(`request`, 'http:' , 'https:'),
`notify` = REPLACE(`notify` , 'http:' , 'https:'),
`poll` = REPLACE(`poll` , 'http:' , 'https:'),
`confirm` = REPLACE(`confirm`, 'http:' , 'https:'),
`poco` = REPLACE(`poco` , 'http:' , 'https:')
WHERE `self` = 1"
);
q("update `profile` set
`photo` = replace(`photo` , 'http:' , 'https:'),
`thumb` = replace(`thumb` , 'http:' , 'https:')
where 1 "
q("UPDATE `profile` SET
`photo` = REPLACE(`photo` , 'http:' , 'https:'),
`thumb` = REPLACE(`thumb` , 'http:' , 'https:')
WHERE 1 "
);
}
elseif($ssl_policy == SSL_POLICY_SELFSIGN) {
q("update `contact` set
`url` = replace(`url` , 'https:' , 'http:'),
`photo` = replace(`photo` , 'https:' , 'http:'),
`thumb` = replace(`thumb` , 'https:' , 'http:'),
`micro` = replace(`micro` , 'https:' , 'http:'),
`request` = replace(`request`, 'https:' , 'http:'),
`notify` = replace(`notify` , 'https:' , 'http:'),
`poll` = replace(`poll` , 'https:' , 'http:'),
`confirm` = replace(`confirm`, 'https:' , 'http:'),
`poco` = replace(`poco` , 'https:' , 'http:')
where `self` = 1"
q("UPDATE `contact` SET
`url` = REPLACE(`url` , 'https:' , 'http:'),
`photo` = REPLACE(`photo` , 'https:' , 'http:'),
`thumb` = REPLACE(`thumb` , 'https:' , 'http:'),
`micro` = REPLACE(`micro` , 'https:' , 'http:'),
`request` = REPLACE(`request`, 'https:' , 'http:'),
`notify` = REPLACE(`notify` , 'https:' , 'http:'),
`poll` = REPLACE(`poll` , 'https:' , 'http:'),
`confirm` = REPLACE(`confirm`, 'https:' , 'http:'),
`poco` = REPLACE(`poco` , 'https:' , 'http:')
WHERE `self` = 1"
);
q("update `profile` set
`photo` = replace(`photo` , 'https:' , 'http:'),
`thumb` = replace(`thumb` , 'https:' , 'http:')
where 1 "
q("UPDATE `profile` SET
`photo` = REPLACE(`photo` , 'https:' , 'http:'),
`thumb` = REPLACE(`thumb` , 'https:' , 'http:')
WHERE 1 "
);
}
}
@ -860,7 +879,7 @@ function admin_page_site(&$a) {
/* get user names to make the install a personal install of X */
$user_names = array();
$user_names['---'] = t('Multi user instance');
$users = q("SELECT username, nickname FROM `user`");
$users = q("SELECT `username`, `nickname` FROM `user`");
foreach ($users as $user) {
$user_names[$user['nickname']] = $user['username'];
}
@ -1068,7 +1087,7 @@ function admin_page_dbsync(&$a) {
}
$failed = array();
$r = q("select k, v from config where `cat` = 'database' ");
$r = q("SELECT `k`, `v` FROM `config` WHERE `cat` = 'database' ");
if(count($r)) {
foreach($r as $rr) {
$upd = intval(substr($rr['k'],7));
@ -1107,7 +1126,7 @@ function admin_page_users_post(&$a){
$pending = (x($_POST, 'pending') ? $_POST['pending'] : array());
$users = (x($_POST, 'user') ? $_POST['user'] : array());
$nu_name = (x($_POST, 'new_user_name') ? $_POST['new_user_name'] : '');
$nu_nickname = (x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : '');
$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('/admin/users', 'admin_users');
@ -1164,7 +1183,7 @@ function admin_page_users_post(&$a){
if(x($_POST,'page_users_block')) {
foreach($users as $uid){
q("UPDATE `user` SET `blocked`=1-`blocked` WHERE `uid`=%s",
q("UPDATE `user` SET `blocked` = 1-`blocked` WHERE `uid` = %s",
intval($uid)
);
}
@ -1209,7 +1228,7 @@ function admin_page_users_post(&$a){
function admin_page_users(&$a){
if($a->argc>2) {
$uid = $a->argv[3];
$user = q("SELECT username, blocked FROM `user` WHERE `uid`=%d", intval($uid));
$user = q("SELECT `username`, `blocked` FROM `user` WHERE `uid` = %d", intval($uid));
if(count($user)==0) {
notice('User not found'.EOL);
goaway('admin/users');
@ -1226,7 +1245,7 @@ function admin_page_users(&$a){
}; break;
case "block":{
check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
q("UPDATE `user` SET `blocked`=%d WHERE `uid`=%s",
q("UPDATE `user` SET `blocked` = %d WHERE `uid` = %s",
intval(1-$user[0]['blocked']),
intval($uid)
);
@ -1246,12 +1265,42 @@ function admin_page_users(&$a){
/* get users */
$total = q("SELECT count(*) as total FROM `user` where 1");
$total = q("SELECT COUNT(*) AS `total` FROM `user` WHERE 1");
if(count($total)) {
$a->set_pager_total($total[0]['total']);
$a->set_pager_itemspage(100);
}
/* ordering */
$valid_orders = array(
'contact.name',
'user.email',
'user.register_date',
'user.login_date',
'lastitem.lastitem_date',
'user.page-flags'
);
$order = "contact.name";
$order_direction = "+";
if (x($_GET,'o')){
$new_order = $_GET['o'];
if ($new_order[0]==="-") {
$order_direction = "-";
$new_order = substr($new_order,1);
}
if (in_array($new_order, $valid_orders)){
$order = $new_order;
}
if (x($_GET,'d')){
$new_direction = $_GET['d'];
}
}
$sql_order = "`".str_replace('.','`.`',$order)."`";
$sql_order_direction = ($order_direction==="+")?"ASC":"DESC";
$users = q("SELECT `user`.* , `contact`.`name` , `contact`.`url` , `contact`.`micro`, `lastitem`.`lastitem_date`, `user`.`account_expired`
FROM
(SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid`
@ -1264,12 +1313,14 @@ function admin_page_users(&$a){
`user`.`uid` = `contact`.`uid`
AND `user`.`verified` =1
AND `contact`.`self` =1
ORDER BY `contact`.`name` LIMIT %d, %d
ORDER BY $sql_order $sql_order_direction LIMIT %d, %d
",
intval($a->pager['start']),
intval($a->pager['itemspage'])
);
//echo "<pre>$users"; killme();
$adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
$_setup_users = function ($e) use ($adminlist){
$accounts = array(
@ -1316,6 +1367,11 @@ function admin_page_users(&$a){
array_push($users, array_pop($tmp_users));
}
$th_users = array_map(null,
array(t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Account')),
$valid_orders
);
$t = get_markup_template("admin_users.tpl");
$o = replace_macros($t, array(
// strings //
@ -1338,7 +1394,9 @@ function admin_page_users(&$a){
'$h_users' => t('Users'),
'$h_newuser' => t('New User'),
'$th_deleted' => array(t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Deleted since')),
'$th_users' => array(t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Account')),
'$th_users' => $th_users,
'$order_users' => $order,
'$order_direction_users' => $order_direction,
'$confirm_delete_multi' => t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'),
'$confirm_delete' => t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'),
@ -1800,11 +1858,11 @@ function admin_page_logs_post(&$a) {
function admin_page_logs(&$a){
$log_choices = array(
LOGGER_NORMAL => 'Normal',
LOGGER_TRACE => 'Trace',
LOGGER_DEBUG => 'Debug',
LOGGER_DATA => 'Data',
LOGGER_ALL => 'All'
LOGGER_NORMAL => 'Normal',
LOGGER_TRACE => 'Trace',
LOGGER_DEBUG => 'Debug',
LOGGER_DATA => 'Data',
LOGGER_ALL => 'All'
);
$t = get_markup_template("admin_logs.tpl");

View file

@ -49,7 +49,7 @@ function allfriends_content(&$a) {
foreach($r as $rr) {
//get further details of the contact
$contact_details = get_contact_details_by_url($rr['url'], $uid);
$contact_details = get_contact_details_by_url($rr['url'], $uid, $rr);
$photo_menu = '';
@ -61,16 +61,18 @@ function allfriends_content(&$a) {
}
else {
$connlnk = $a->get_baseurl() . '/follow/?url=' . $rr['url'];
$photo_menu = array(array(t("View Profile"), zrl($rr['url'])));
$photo_menu[] = array(t("Connect/Follow"), $connlnk);
$photo_menu = array(
'profile' => array(t("View Profile"), zrl($rr['url'])),
'follow' => array(t("Connect/Follow"), $connlnk)
);
}
$entry = array(
'url' => $rr['url'],
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $rr['url']),
'name' => htmlentities($rr['name']),
'thumb' => proxy_url($rr['photo'], false, PROXY_SIZE_THUMB),
'img_hover' => htmlentities($rr['name']),
'name' => htmlentities($contact_details['name']),
'thumb' => proxy_url($contact_details['thumb'], false, PROXY_SIZE_THUMB),
'img_hover' => htmlentities($contact_details['name']),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],

View file

@ -109,14 +109,14 @@ function common_content(&$a) {
$rr[id] = $rr[cid];
$photo_menu = '';
$photo_menu = contact_photo_menu ($rr);
$photo_menu = contact_photo_menu($rr);
$entry = array(
'url' => $rr['url'],
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $rr['url']),
'name' => $rr['name'],
'thumb' => proxy_url($rr['photo'], false, PROXY_SIZE_THUMB),
'img_hover' => htmlentities($rr['name']),
'name' => $contact_details['name'],
'thumb' => proxy_url($contact_details['thumb'], false, PROXY_SIZE_THUMB),
'img_hover' => htmlentities($contact_details['name']),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],

View file

@ -120,23 +120,20 @@ function community_getitems($start, $itemspage) {
if (get_config('system','community_page_style') == CP_GLOBAL_COMMUNITY)
return(community_getpublicitems($start, $itemspage));
$r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`,
`user`.`nickname`, `user`.`hidewall`
$r = q("SELECT %s, %s, `user`.`nickname`
FROM `thread` FORCE INDEX (`wall_private_received`)
INNER JOIN `user` ON `user`.`uid` = `thread`.`uid` AND `user`.`hidewall` = 0
INNER JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall`
INNER JOIN `item` ON `item`.`id` = `thread`.`iid`
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
INNER JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `contact`.`self`
WHERE `thread`.`visible` = 1 AND `thread`.`deleted` = 0 and `thread`.`moderated` = 0
AND `thread`.`private` = 0 AND `thread`.`wall` = 1
ORDER BY `thread`.`received` DESC LIMIT %d, %d ",
intval($start),
intval($itemspage)
AND %s AND `contact`.`self`
WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
AND NOT `thread`.`private` AND `thread`.`wall`
ORDER BY `thread`.`received` DESC LIMIT %d, %d",
item_fieldlist(), contact_fieldlist(),
contact_condition(),
intval($start), intval($itemspage)
);
return($r);
@ -144,14 +141,14 @@ function community_getitems($start, $itemspage) {
}
function community_getpublicitems($start, $itemspage) {
$r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
`author-name` AS `name`, `owner-avatar` AS `photo`,
$r = q("SELECT %s, `author-name` AS `name`, `owner-avatar` AS `photo`,
`owner-link` AS `url`, `owner-avatar` AS `thumb`
FROM `thread`
INNER JOIN `item` ON `item`.`id` = `thread`.`iid`
WHERE `thread`.`uid` = 0
ORDER BY `thread`.`created` DESC LIMIT %d, %d",
intval($start),
item_fieldlist(), intval($start),
intval($itemspage)
);

View file

@ -787,7 +787,7 @@ function contacts_content(&$a) {
'$total' => $total,
'$search' => $search_hdr,
'$desc' => t('Search your contacts'),
'$finding' => (($searching) ? t('Finding: ') . "'" . $search . "'" : ""),
'$finding' => (($searching) ? sprintf(t('Results for: %s'),$search) : ""),
'$submit' => t('Find'),
'$cmd' => $a->cmd,
'$contacts' => $contacts,

View file

@ -217,7 +217,7 @@ function content_content(&$a, $update = 0) {
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, `contact`.`writable`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM $sql_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`uid` = %d AND `item`.`visible` = 1
AND `item`.`deleted` = 0 and `item`.`moderated` = 0
@ -268,7 +268,7 @@ function content_content(&$a, $update = 0) {
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`rel`, `contact`.`writable`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
`contact`.`id` AS `cid`
FROM $sql_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
AND `item`.`moderated` = 0
@ -319,6 +319,15 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
$previewing = (($preview) ? ' preview ' : '');
$edited = false;
if (strcmp($item['created'], $item['edited'])<>0) {
$edited = array(
'label' => t('This entry was edited'),
'date' => datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r'),
'relative' => relative_date($item['edited'])
);
}
if($mode === 'network') {
$profile_owner = local_user();
$page_writeable = true;
@ -349,8 +358,6 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
else
$return_url = $_SESSION['return_url'] = $a->query_string;
load_contact_links(local_user());
$cb = array('items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview);
call_hooks('conversation_start',$cb);
@ -361,8 +368,10 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
$wallwall = 'wallwall_item.tpl';
$hide_comments_tpl = get_markup_template('hide_comments.tpl');
$alike = array();
$dlike = array();
$conv_responses = array(
'like' => array('title' => t('Likes','title')), 'dislike' => array('title' => t('Dislikes','title')),
'attendyes' => array('title' => t('Attending','title')), 'attendno' => array('title' => t('Not attending','title')), 'attendmaybe' => array('title' => t('Might attend','title'))
);
// array with html for each thread (parent+comments)
@ -389,7 +398,11 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
$sparkle = '';
if($mode === 'search' || $mode === 'community') {
if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
if(((activity_match($item['verb'],ACTIVITY_LIKE))
|| (activity_match($item['verb'],ACTIVITY_DISLIKE))
|| activity_match($item['verb'],ACTIVITY_ATTEND)
|| activity_match($item['verb'],ACTIVITY_ATTENDNO)
|| activity_match($item['verb'],ACTIVITY_ATTENDMAYBE))
&& ($item['id'] != $item['parent']))
continue;
$nickname = $item['nickname'];
@ -416,11 +429,12 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
else
$profile_link = zrl($profile_link);
$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
$profile_avatar = $a->contacts[$normalised]['thumb'];
// Don't rely on the author-avatar. It is better to use the data from the contact table
$author_contact = get_contact_details_by_url($item['author-link'], $profile_owner);
if ($author_contact["thumb"])
$profile_avatar = $author_contact["thumb"];
else
$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar'])) ? $item['author-avatar'] : $item['thumb']));
$profile_avatar = $item['author-avatar'];
$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
call_hooks('render_location',$locate);
@ -530,12 +544,11 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
$comments[$item['parent']] = 0; // avoid notices later on
}
// map all the like/dislike activities for each parent item
// map all the like/dislike/attendance activities for each parent item
// Store these in the $alike and $dlike arrays
foreach($items as $item) {
like_puller($a,$item,$alike,'like');
like_puller($a,$item,$dlike,'dislike');
builtin_activity_puller($item, $conv_responses);
}
$comments_collapsed = false;
@ -557,7 +570,10 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
// We've already parsed out like/dislike for special treatment. We can ignore them now
if(((activity_match($item['verb'],ACTIVITY_LIKE))
|| (activity_match($item['verb'],ACTIVITY_DISLIKE)))
|| (activity_match($item['verb'],ACTIVITY_DISLIKE)
|| activity_match($item['verb'],ACTIVITY_ATTEND)
|| activity_match($item['verb'],ACTIVITY_ATTENDNO)
|| activity_match($item['verb'],ACTIVITY_ATTENDMAYBE)))
&& ($item['id'] != $item['parent']))
continue;
@ -761,6 +777,28 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'tagger' => t("add tag"),
'classtagger' => "",
);
$r = q("SELECT `ignored` FROM `thread` WHERE `uid` = %d AND `iid` = %d LIMIT 1",
intval($item['uid']),
intval($item['id'])
);
if (count($r)) {
$ignore = array(
'do' => t("ignore thread"),
'undo' => t("unignore thread"),
'toggle' => t("toggle ignore status"),
'classdo' => (($r[0]['ignored']) ? "hidden" : ""),
'classundo' => (($r[0]['ignored']) ? "" : "hidden"),
'ignored' => t('ignored'),
);
}
$tagger = '';
if(feature_enabled($profile_owner,'commtag')) {
$tagger = array(
'add' => t("add tag"),
'class' => "",
);
}
}
$filer = t("save to folder");
}
@ -787,14 +825,30 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
else
$profile_link = zrl($profile_link);
$normalised = normalise_link((strlen($item['author-link'])) ? $item['author-link'] : $item['url']);
if(($normalised != 'mailbox') && (x($a->contacts,$normalised)))
$profile_avatar = $a->contacts[$normalised]['thumb'];
// Don't rely on the author-avatar. It is better to use the data from the contact table
$author_contact = get_contact_details_by_url($item['author-link'], $profile_owner);
if ($author_contact["thumb"])
$profile_avatar = $author_contact["thumb"];
else
$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar']) && $diff_author) ? $item['author-avatar'] : $thumb));
$profile_avatar = $item['author-avatar'];
$like = ((x($alike,$item['uri'])) ? format_like($alike[$item['uri']],$alike[$item['uri'] . '-l'],'like',$item['uri']) : '');
$dislike = ((x($dlike,$item['uri'])) ? format_like($dlike[$item['uri']],$dlike[$item['uri'] . '-l'],'dislike',$item['uri']) : '');
$like = ((x($conv_responses['like'],$item['uri'])) ? format_like($conv_responses['like'][$item['uri']],$conv_responses['like'][$item['uri'] . '-l'],'like',$item['uri']) : '');
$dislike = ((x($conv_responses['dislike'],$item['uri'])) ? format_like($conv_responses['dislike'][$item['uri']],$conv_responses['dislike'][$item['uri'] . '-l'],'dislike',$item['uri']) : '');
// process action responses - e.g. like/dislike/attend/agree/whatever
$response_verbs = array('like');
if(feature_enabled($profile_owner,'dislike'))
$response_verbs[] = 'dislike';
if($item['object-type'] === ACTIVITY_OBJ_EVENT) {
$response_verbs[] = 'attendyes';
$response_verbs[] = 'attendno';
$response_verbs[] = 'attendmaybe';
if($page_writeable) {
$isevent = true;
$attend = array( t('I will attend'), t('I will not attend'), t('I might attend'));
}
}
$responses = get_responses($conv_responses,$response_verbs,'',$item);
$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
call_hooks('render_location',$locate);
@ -805,9 +859,9 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
$shiny = "";
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
$shiny = 'shiny';
$shiny = 'shiny';
//
//
localize_item($item);
@ -851,6 +905,8 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'body' => $body_e,
'text' => $text_e,
'id' => $item['item_id'],
'isevent' => $isevent,
'attend' => $attend,
'linktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'olinktitle' => sprintf( t('View %s\'s profile @ %s'), $profile_name, ((strlen($item['owner-link'])) ? $item['owner-link'] : $item['url'])),
'to' => t('to'),
@ -863,7 +919,10 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => $title_e,
'localtime' => datetime_convert('UTC', date_default_timezone_get(), $item['created'], 'r'),
'ago' => (($item['app']) ? sprintf( t('%s from %s'),relative_date($item['created']),$item['app']) : relative_date($item['created'])),
'app' => $item['app'],
'created' => relative_date($item['created']),
'lock' => $lock,
'location' => $location_e,
'indent' => $indent,
@ -875,14 +934,21 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'edpost' => $edpost,
'isstarred' => $isstarred,
'star' => $star,
'filer' => $filer,
'ignore' => ((feature_enabled($profile_owner,'ignore_posts')) ? $ignore : ''),
'tagger' => $tagger,
'filer' => ((feature_enabled($profile_owner,'filing')) ? $filer : ''),
'drop' => $drop,
'vote' => $likebuttons,
'responses' => $responses,
'like' => $like,
'dislike' => $dislike,
'switchcomment' => t('Comment'),
'comment' => $comment,
'previewing' => $previewing,
'wait' => t('Please wait'),
'edited' => $edited,
'network' => $item["item_network"],
'network_name' => network_to_name($item['network'], $profile_link),
);

View file

@ -15,6 +15,7 @@
*/
require_once('include/enotify.php');
require_once('include/group.php');
function dfrn_confirm_post(&$a,$handsfree = null) {
@ -427,8 +428,8 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
if(($contact) && ($contact['network'] === NETWORK_DIASPORA)) {
require_once('include/diaspora.php');
$ret = diaspora_share($user[0],$r[0]);
logger('mod_follow: diaspora_share returns: ' . $ret);
$ret = diaspora::send_share($user[0],$r[0]);
logger('share returns: ' . $ret);
}
// Send a new friend post if we are allowed to...
@ -448,6 +449,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
if(count($self)) {
$arr = array();
$arr['guid'] = get_guid(32);
$arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $uid);
$arr['uid'] = $uid;
$arr['contact-id'] = $self[0]['id'];
@ -466,7 +468,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
$BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]';
$arr['verb'] = ACTIVITY_FRIEND;
$arr['object-type'] = ACTIVITY_OBJ_PERSON;
$arr['object-type'] = ACTIVITY_OBJ_PERSON;
$arr['body'] = sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$BPhoto;
$arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>'
@ -490,10 +492,8 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
}
$def_gid = get_default_group($uid, $contact["network"]);
if($contact && intval($def_gid)) {
require_once('include/group.php');
if($contact && intval($def_gid))
group_add_member($uid, '', $contact['id'], $def_gid);
}
// Let's send our user to the contact editor in case they want to
// do anything special with this new friend.

View file

@ -25,6 +25,8 @@ function dfrn_poll_init(&$a) {
$dfrn_id = substr($dfrn_id,2);
}
$hidewall = false;
if(($dfrn_id === '') && (! x($_POST,'dfrn_id'))) {
if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
http_status_exit(403);
@ -35,16 +37,17 @@ function dfrn_poll_init(&$a) {
$r = q("SELECT `hidewall`,`nickname` FROM `user` WHERE `user`.`nickname` = '%s' LIMIT 1",
dbesc($a->argv[1])
);
if(! $r)
if (!$r)
http_status_exit(404);
if(($r[0]['hidewall']) && (! local_user()))
http_status_exit(403);
$hidewall = ($r[0]['hidewall'] && !local_user());
$user = $r[0]['nickname'];
}
logger('dfrn_poll: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $user);
header("Content-type: application/atom+xml");
echo dfrn::feed('', $user,$last_update);
echo dfrn::feed('', $user,$last_update, 0, $hidewall);
killme();
}

View file

@ -11,6 +11,7 @@
require_once('include/enotify.php');
require_once('include/Scrape.php');
require_once('include/group.php');
if(! function_exists('dfrn_request_init')) {
function dfrn_request_init(&$a) {
@ -181,10 +182,9 @@ function dfrn_request_post(&$a) {
);
if(count($r)) {
$def_gid = get_default_group(local_user(), $r[0]["network"]);
if(intval($def_gid)) {
require_once('include/group.php');
if(intval($def_gid))
group_add_member(local_user(), '', $r[0]['id'], $def_gid);
}
$forwardurl = $a->get_baseurl()."/contacts/".$r[0]['id'];
} else
$forwardurl = $a->get_baseurl()."/contacts";
@ -394,10 +394,8 @@ function dfrn_request_post(&$a) {
$contact_id = $r[0]['id'];
$def_gid = get_default_group($uid, $r[0]["network"]);
if (intval($def_gid)) {
require_once('include/group.php');
if (intval($def_gid))
group_add_member($uid, '', $contact_id, $def_gid);
}
$photo = avatar_img($addr);

View file

@ -159,7 +159,9 @@ function directory_content(&$a) {
$location_e = $location;
}
$photo_menu = array(array(t("View Profile"), zrl($profile_link)));
$photo_menu = array(
'profile' => array(t("View Profile"), zrl($profile_link))
);
$entry = array(
'id' => $rr['id'],
@ -204,7 +206,7 @@ function directory_content(&$a) {
'$gdirpath' => $gdirpath,
'$desc' => t('Find on this site'),
'$contacts' => $entries,
'$finding' => t('Finding:'),
'$finding' => t('Results for:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => t('Site Directory'),
'$submit' => t('Find'),

View file

@ -33,6 +33,7 @@ function dirfind_content(&$a, $prefix = "") {
if(strpos($search,'@') === 0) {
$search = substr($search,1);
$header = sprintf( t('People Search - %s'), $search);
if ((valid_email($search) AND validate_email($search)) OR
(substr(normalise_link($search), 0, 7) == "http://")) {
$user_data = probe_url($search);
@ -43,6 +44,7 @@ function dirfind_content(&$a, $prefix = "") {
if(strpos($search,'!') === 0) {
$search = substr($search,1);
$community = true;
$header = sprintf( t('Forum Search - %s'), $search);
}
$o = '';
@ -64,16 +66,15 @@ function dirfind_content(&$a, $prefix = "") {
$objresult->tags = "";
$objresult->network = $user_data["network"];
$contact = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc(normalise_link($user_data["url"])), intval(local_user()));
if ($contact)
$objresult->cid = $contact[0]["id"];
$contact = get_contact_details_by_url($user_data["url"], local_user());
$objresult->cid = $contact["cid"];
$j->results[] = $objresult;
poco_check($user_data["url"], $user_data["name"], $user_data["network"], $user_data["photo"],
"", "", "", "", "", datetime_convert(), 0);
// Add the contact to the global contacts if it isn't already in our system
if (($contact["cid"] == 0) AND ($contact["zid"] == 0) AND ($contact["gid"] == 0))
poco_check($user_data["url"], $user_data["name"], $user_data["network"], $user_data["photo"],
"", "", "", "", "", datetime_convert(), 0);
} elseif ($local) {
if ($community)
@ -94,34 +95,38 @@ function dirfind_content(&$a, $prefix = "") {
else
$ostatus = NETWORK_DFRN;
$search2 = "%".$search."%";
$count = q("SELECT count(*) AS `total` FROM `gcontact`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
AND `contact`.`network` = `gcontact`.`network`
AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
WHERE (`contact`.`id` > 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND
(`gcontact`.`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",
(`gcontact`.`url` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`location` LIKE '%s' OR
`gcontact`.`addr` LIKE '%s' OR `gcontact`.`about` LIKE '%s' OR `gcontact`.`keywords` LIKE '%s') $extra_sql",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN), dbesc($ostatus), dbesc($diaspora),
dbesc(escape_tags($search)), dbesc(escape_tags($search)), dbesc(escape_tags($search)),
dbesc(escape_tags($search)), dbesc(escape_tags($search)));
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)));
$results = q("SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`photo`, `gcontact`.`network`, `gcontact`.`keywords`, `gcontact`.`addr`
FROM `gcontact`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
AND `contact`.`network` = `gcontact`.`network`
AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
WHERE (`contact`.`id` > 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND
(`gcontact`.`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
(`gcontact`.`url` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`location` LIKE '%s' OR
`gcontact`.`addr` LIKE '%s' OR `gcontact`.`about` LIKE '%s' OR `gcontact`.`keywords` LIKE '%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($ostatus), dbesc($diaspora),
dbesc(escape_tags($search)), dbesc(escape_tags($search)), dbesc(escape_tags($search)),
dbesc(escape_tags($search)), dbesc(escape_tags($search)),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)),
intval($startrec), intval($perpage));
$j = new stdClass();
$j->total = $count[0]["total"];
@ -131,6 +136,8 @@ function dirfind_content(&$a, $prefix = "") {
if (poco_alternate_ostatus_url($result["url"]))
continue;
$result = get_contact_details_by_url($result["url"], local_user(), $result);
if ($result["name"] == "") {
$urlparts = parse_url($result["url"]);
$result["name"] = end(explode("/", $urlparts["path"]));
@ -192,8 +199,10 @@ function dirfind_content(&$a, $prefix = "") {
} else {
$connlnk = $a->get_baseurl().'/follow/?url='.(($jj->connect) ? $jj->connect : $jj->url);
$conntxt = t('Connect');
$photo_menu = array(array(t("View Profile"), zrl($jj->url)));
$photo_menu[] = array(t("Connect/Follow"), $connlnk);
$photo_menu = array(
'profile' => array(t("View Profile"), zrl($jj->url)),
'follow' => array(t("Connect/Follow"), $connlnk)
);
}
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
@ -221,7 +230,7 @@ function dirfind_content(&$a, $prefix = "") {
$tpl = get_markup_template('viewcontact_template.tpl');
$o .= replace_macros($tpl,array(
'title' => sprintf( t('People Search - %s'), $search),
'title' => $header,
'$contacts' => $entries,
'$paginate' => paginate($a),
));

View file

@ -16,7 +16,7 @@ function display_init(&$a) {
// Does the local user have this item?
if (local_user()) {
$r = q("SELECT `id`, `parent`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid` FROM `item`
$r = q("SELECT `id`, `parent`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item`
WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
if (count($r)) {
@ -28,7 +28,7 @@ function display_init(&$a) {
// Or is it anywhere on the server?
if ($nick == "") {
$r = q("SELECT `user`.`nickname`, `item`.`id`, `item`.`parent`, `item`.`author-name`,
`item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`body`
`item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`owner-link`, `item`.`body`
FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid`
WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
@ -44,8 +44,8 @@ function display_init(&$a) {
// Is it an item with uid=0?
if ($nick == "") {
$r = q("SELECT `item`.`id`, `item`.`parent`, `item`.`author-name`,
`item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`body`
$r = q("SELECT `item`.`id`, `item`.`parent`, `item`.`author-name`, `item`.`author-link`,
`item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`owner-link`, `item`.`body`
FROM `item` WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
@ -55,10 +55,32 @@ function display_init(&$a) {
}
if (count($r)) {
if ($r[0]["id"] != $r[0]["parent"])
$r = q("SELECT `id`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid` FROM `item`
$r = q("SELECT `id`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item`
WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
AND `id` = %d", $r[0]["parent"]);
if (($itemuid != local_user()) AND local_user()) {
// Do we know this contact but we haven't got this item?
// Copy the wohle thread to our local storage so that we can interact.
// We really should change this need for the future since it scales very bad.
$contactid = get_contact($r[0]['owner-link'], local_user());
if ($contactid) {
$items = q("SELECT * FROM `item` WHERE `parent` = %d ORDER BY `id`", intval($r[0]["id"]));
foreach ($items AS $item) {
$itemcontactid = get_contact($item['owner-link'], local_user());
if (!$itemcontactid)
$itemcontactid = $contactid;
unset($item['id']);
$item['uid'] = local_user();
$item['origin'] = 0;
$item['contact-id'] = $itemcontactid;
$local_copy = item_store($item, false, false, true);
logger("Stored local copy for post ".$item['guid']." under id ".$local_copy, LOGGER_DEBUG);
}
}
}
$profiledata = display_fetchauthor($a, $r[0]);
if (strstr(normalise_link($profiledata["url"]), normalise_link($a->get_baseurl()))) {
@ -90,6 +112,8 @@ function display_init(&$a) {
function display_fetchauthor($a, $item) {
require_once("include/Contact.php");
$profiledata = array();
$profiledata["uid"] = -1;
$profiledata["nickname"] = $item["author-name"];
@ -154,61 +178,9 @@ function display_fetchauthor($a, $item) {
$profiledata["about"] = "";
}
// Don't show details from Diaspora contacts if you don't follow the contact
$showdetails = ($profiledata["network"] != NETWORK_DIASPORA);
$profiledata = get_contact_details_by_url($profiledata["url"], local_user(), $profiledata);
// Fetching further contact data from the contact table
$r = q("SELECT `uid`, `network`, `name`, `photo`, `nick`, `addr`, `location`, `about`, `gender`, `keywords`
FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` = '%s' AND `rel` IN (%d, %d)",
dbesc(normalise_link($profiledata["url"])), intval(local_user()), dbesc($item["network"]),
intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND));
if (!count($r))
$r = q("SELECT `uid`, `network`, `name`, `photo`, `nick`, `addr`, `location`, `about`, `gender`, `keywords`
FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `rel` IN (%d, %d)",
dbesc(normalise_link($profiledata["url"])), intval(local_user()),
intval(CONTACT_IS_SHARING), intval(CONTACT_IS_FRIEND));
if (count($r)) {
$profiledata["name"] = $r[0]["name"];
$profiledata["photo"] = $r[0]["photo"];
$profiledata["nickname"] = $r[0]["nick"];
$profiledata["addr"] = $r[0]["addr"];
$profiledata["keywords"] = $r[0]["keywords"];
$profiledata["network"] = $r[0]["network"];
if (local_user() OR $showdetails) {
$showdetails = true;
$profiledata["address"] = $r[0]["location"];
$profiledata["about"] = $r[0]["about"];
$profiledata["gender"] = $r[0]["gender"];
}
}
// Fetching profile data from global contacts
if ($profiledata["network"] != NETWORK_FEED) {
$r = q("SELECT `name`, `photo`, `nick`, `addr`, `location`, `about`, `gender`, `keywords`, `network` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($profiledata["url"])));
if (count($r)) {
$profiledata["name"] = $r[0]["name"];
$profiledata["photo"] = $r[0]["photo"];
$profiledata["nickname"] = $r[0]["nick"];
$profiledata["addr"] = $r[0]["addr"];
$profiledata["network"] = $r[0]["network"];
if ($r[0]["keywords"])
$profiledata["keywords"] = $r[0]["keywords"];
if ($showdetails) {
if ($r[0]["location"])
$profiledata["address"] = $r[0]["location"];
if ($r[0]["about"])
$profiledata["about"] = $r[0]["about"];
if ($r[0]["gender"])
$profiledata["gender"] = $r[0]["gender"];
}
}
}
$profiledata["photo"] = App::remove_baseurl($profiledata["photo"]);
if (local_user()) {
if (in_array($profiledata["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
@ -390,17 +362,14 @@ function display_content(&$a, $update = 0) {
return '';
}
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
AND NOT `item`.`moderated`
$r = q("SELECT %s, %s FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND %s
WHERE %s AND `item`.`uid` = %d
AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `id` = %d)
$sql_extra
ORDER BY `parent` DESC, `gravity` ASC, `id` ASC",
item_fieldlist(), contact_fieldlist(),
contact_condition(), item_condition(),
intval($a->profile['uid']),
intval($item_id)
);
@ -416,16 +385,13 @@ function display_content(&$a, $update = 0) {
if($r) {
$item_uri = $r[0]['uri'];
$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
AND NOT `item`.`moderated`
$r = q("SELECT %s, %s FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND %s
WHERE %s AND `item`.`uid` = %d
AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `uri` = '%s' AND uid = %d)
ORDER BY `parent` DESC, `gravity` ASC, `id` ASC ",
item_fieldlist(), contact_fieldlist(),
contact_condition(), item_condition(),
intval(local_user()),
dbesc($item_uri),
intval(local_user())
@ -437,10 +403,14 @@ function display_content(&$a, $update = 0) {
if($r) {
if((local_user()) && (local_user() == $a->profile['uid'])) {
q("UPDATE `item` SET `unseen` = 0
WHERE `parent` = %d AND `unseen`",
intval($r[0]['parent'])
);
$unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `parent` = %d",
intval($r[0]['parent']));
if ($unseen)
q("UPDATE `item` SET `unseen` = 0
WHERE `parent` = %d AND `unseen`",
intval($r[0]['parent'])
);
}
$items = conv_sort($r,"`commented`");
@ -456,9 +426,7 @@ function display_content(&$a, $update = 0) {
$title = trim(html2plain(bbcode($r[0]["title"], false, false), 0, true));
$author_name = $r[0]["author-name"];
$image = "";
if ($image == "")
$image = $r[0]["thumb"];
$image = $a->remove_baseurl($r[0]["thumb"]);
if ($title == "")
$title = $author_name;

View file

@ -124,6 +124,7 @@ function events_post(&$a) {
$datarray = array();
$datarray['guid'] = get_guid(32);
$datarray['start'] = $start;
$datarray['finish'] = $finish;
$datarray['summary'] = $summary;

View file

@ -74,10 +74,18 @@ function fbrowser_content($a){
$filename_e = $rr['filename'];
}
// Take the largest picture that is smaller or equal 640 pixels
$p = q("SELECT `scale` FROM `photo` WHERE `resource-id` = '%s' AND `height` <= 640 AND `width` <= 640 ORDER BY `resource-id`, `scale` LIMIT 1",
dbesc($rr['resource-id']));
if ($p)
$scale = $p[0]["scale"];
else
$scale = $rr['loq'];
return array(
$a->get_baseurl() . '/photos/' . $a->user['nickname'] . '/image/' . $rr['resource-id'],
$filename_e,
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['loq'] . '.'. $ext
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $scale . '.'. $ext
);
}
$files = array_map("_map_files1", $r);

121
mod/hovercard.php Normal file
View file

@ -0,0 +1,121 @@
<?php
/**
* Name: Frio Hovercard
* Description: Hovercard addon for the frio theme
* Version: 0.1
* Author: Rabuzarus <https://github.com/rabuzarus>
* License: GNU AFFERO GENERAL PUBLIC LICENSE (Version 3)
*/
require_once("include/socgraph.php");
require_once("include/Contact.php");
function hovercard_init(&$a) {
// Just for testing purposes
$_GET["mode"] = "minimal";
}
function hovercard_content() {
$profileurl = (x($_REQUEST,'profileurl') ? $_REQUEST['profileurl'] : "");
$datatype = (x($_REQUEST,'datatype') ?$_REQUEST['datatype'] : "json");
// Get out if the system doesn't have public access allowed
if(intval(get_config('system','block_public')))
http_status_exit(401);
// Return the raw content of the template. We use this to make templates usable for js functions.
// Look at hovercard.js (function getHoverCardTemplate()).
// This part should be moved in it's own module. Maybe we could make more templates accessabel.
// (We need to discuss possible security lacks before doing this)
if ($datatype == "tpl") {
$templatecontent = get_template_content("hovercard.tpl");
echo $templatecontent;
killme();
}
// If a contact is connected the url is internally changed to "redir/CID". We need the pure url to search for
// the contact. So we strip out the contact id from the internal url and look in the contact table for
// the real url (nurl)
if(local_user() && strpos($profileurl, "redir/") === 0) {
$cid = intval(substr($profileurl, 6));
$r = q("SELECT `nurl`, `self` FROM `contact` WHERE `id` = '%d' LIMIT 1", intval($cid));
$profileurl = ($r[0]["nurl"] ? $r[0]["nurl"] : "");
$self = ($r[0]["self"] ? $r[0]["self"] : "");
}
// if it's the url containing https it should be converted to http
$nurl = normalise_link(clean_contact_url($profileurl));
if($nurl) {
// Search for contact data
$contact = get_contact_details_by_url($nurl);
}
if(!is_array($contact))
return;
// Get the photo_menu - the menu if possible contact actions
if(local_user())
$actions = contact_photo_menu($contact);
// Move the contact data to the profile array so we can deliver it to
//
$profile = array(
'name' => $contact["name"],
'nick' => $contact["nick"],
'addr' => (($contact["addr"] != "") ? $contact["addr"] : $contact["url"]),
'thumb' => proxy_url($contact["thumb"], false, PROXY_SIZE_THUMB),
'url' => ($cid ? ("redir/".$cid) : zrl($contact["url"])),
'nurl' => $contact["nurl"], // We additionally store the nurl as identifier
// 'alias' => $contact["alias"],
'location' => $contact["location"],
'gender' => $contact["gender"],
'about' => $contact["about"],
'network' => format_network_name($contact["network"], $contact["url"]),
'tags' => intval($contact["keywords"]),
// 'nsfw' => intval($contact["nsfw"]),
// 'server_url' => $contact["server_url"],
'bd' => (($contact["birthday"] == "0000-00-00") ? "" : $contact["birthday"]),
// 'generation' => $contact["generation"],
'account_type' => ($contact['community'] ? t("Forum") : ""),
'actions' => $actions,
);
if($datatype == "html") {
$t = get_markup_template("hovercard.tpl");
$o = replace_macros($t, array(
'$profile' => $profile,
));
return $o;
} else {
json_return_and_die($profile);
}
}
/**
* @brief Get the raw content of a template file
*
* @param string $template The name of the template
* @param string $root Directory of the template
*
* @return string|bool Output the raw content if existent, otherwise false
*/
function get_template_content($template, $root = "") {
// We load the whole template system to get the filename.
// Maybe we can do it a little bit smarter if I get time.
$t = get_markup_template($template, $root);
$filename = $t->filename;
// Get the content of the template file
if(file_exists($filename)) {
$content = file_get_contents($filename);
return $content;
}
return false;
}

View file

@ -77,7 +77,16 @@ function install_post(&$a) {
$dbdata = notags(trim($_POST['dbdata']));
$phpath = notags(trim($_POST['phpath']));
$timezone = notags(trim($_POST['timezone']));
$language = notags(trim($_POST['language']));
$adminmail = notags(trim($_POST['adminmail']));
// In step 4 of the installer, we passed the check for mcrypt
// already, so we can activate RINO, make RINO2 the default
// and only fall back if the mcrypt_create_iv function is
// not available on the system.
$rino = 2;
if (! function_exists('mcrypt_create_iv')) {
$rino = 1;
}
// connect to db
$db = new dba($dbhost, $dbuser, $dbpass, $dbdata, true);
@ -89,9 +98,11 @@ function install_post(&$a) {
'$dbpass' => $dbpass,
'$dbdata' => $dbdata,
'$timezone' => $timezone,
'$language' => $language,
'$urlpath' => $urlpath,
'$phpath' => $phpath,
'$adminmail' => $adminmail
'$adminmail' => $adminmail,
'$rino' => $rino
));
@ -273,6 +284,8 @@ function install_content(&$a) {
$adminmail = notags(trim($_POST['adminmail']));
$timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
/* Installed langs */
$lang_choices = get_avaiable_languages();
$tpl = get_markup_template('install_settings.tpl');
$o .= replace_macros($tpl, array(
@ -291,7 +304,7 @@ function install_content(&$a) {
'$timezone' => field_timezone('timezone', t('Please select a default timezone for your website'), $timezone, ''),
'$language' => array('language', t('System Language:'), 'en', t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices),
'$baseurl' => $a->get_baseurl(),
@ -404,7 +417,7 @@ function check_funcs(&$checks) {
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, "");
check_add($ck_funcs, t('XML PHP module'), true, true, "");
if(function_exists('apache_get_modules')){
if (! in_array('mod_rewrite',apache_get_modules())) {
@ -445,7 +458,7 @@ function check_funcs(&$checks) {
if ($ck_funcs[5]['status']) {
if (function_exists('mcrypt_create_iv')) {
$__status = true;
$__help = "If you are using php_cli, please make sure that mcrypt module is enabled in its config file";
$__help = t("If you are using php_cli, please make sure that mcrypt module is enabled in its config file");
} else {
$__status = false;
$__help = t('Function mcrypt_create_iv() is not defined. This is needed to enable RINO2 encryption layer.');
@ -453,6 +466,13 @@ function check_funcs(&$checks) {
check_add($checks, t('mcrypt_create_iv() function'), $__status, false, $__help);
}
// check for XML DOM Documents being able to be generated
try {
$xml = new DOMDocument();
} catch (Exception $e) {
$ck_funcs[6]['status'] = false;
$ck_funcs[6]['help'] = t('Error, XML PHP module required but not installed.');
}
/*if((x($_SESSION,'sysmsg')) && is_array($_SESSION['sysmsg']) && count($_SESSION['sysmsg']))
notice( t('Please see the file "INSTALL.txt".') . EOL);*/

View file

@ -24,6 +24,7 @@ require_once('include/threads.php');
require_once('include/text.php');
require_once('include/items.php');
require_once('include/Scrape.php');
require_once('include/diaspora.php');
function item_post(&$a) {
@ -504,10 +505,11 @@ function item_post(&$a) {
}
}
// embedded bookmark in post? set bookmark flag
// embedded bookmark or attachment in post? set bookmark flag
$bookmark = 0;
if(preg_match_all("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism",$body,$match,PREG_SET_ORDER)) {
$data = get_attachment_data($body);
if (preg_match_all("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", $body, $match, PREG_SET_ORDER) OR isset($data["type"])) {
$objecttype = ACTIVITY_OBJ_BOOKMARK;
$bookmark = 1;
}
@ -900,7 +902,7 @@ function item_post(&$a) {
// Store the comment signature information in case we need to relay to Diaspora
store_diaspora_comment_sig($datarray, $author, ($self ? $user['prvkey'] : false), $parent_item, $post_id);
diaspora::store_comment_signature($datarray, $author, ($self ? $user['prvkey'] : false), $post_id);
} else {
$parent = $post_id;
@ -1064,10 +1066,11 @@ function item_content(&$a) {
* the appropiate link.
*
* @param unknown_type $body the text to replace the tag in
* @param unknown_type $inform a comma-seperated string containing everybody to inform
* @param unknown_type $str_tags string to add the tag to
* @param unknown_type $profile_uid
* @param unknown_type $tag the tag to replace
* @param string $inform a comma-seperated string containing everybody to inform
* @param string $str_tags string to add the tag to
* @param integer $profile_uid
* @param string $tag the tag to replace
* @param string $network The network of the post
*
* @return boolean true if replaced, false if not replaced
*/
@ -1092,7 +1095,17 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
// Checking for the alias that is used for OStatus
$pattern = "/@\[url\=(.*?)\](.*?)\[\/url\]/ism";
if (preg_match($pattern, $tag, $matches)) {
$data = probe_url($matches[1]);
$r = q("SELECT `alias`, `name` FROM `contact` WHERE `nurl` = '%s' AND `alias` != '' AND `uid` = 0",
normalise_link($matches[1]));
if (!$r)
$r = q("SELECT `alias`, `name` FROM `gcontact` WHERE `nurl` = '%s' AND `alias` != ''",
normalise_link($matches[1]));
if ($r)
$data = $r[0];
else
$data = probe_url($matches[1]);
if ($data["alias"] != "") {
$newtag = '@[url='.$data["alias"].']'.$data["name"].'[/url]';
if(!stristr($str_tags,$newtag)) {
@ -1119,33 +1132,47 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
// Is it in format @user@domain.tld or @http://domain.tld/...?
// First check the contact table for the address
$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `contact` WHERE `addr` = '%s' AND `uid` = %d LIMIT 1",
$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `contact`
WHERE `addr` = '%s' AND `uid` = %d AND
(`network` != '%s' OR (`notify` != '' AND `alias` != ''))
LIMIT 1",
dbesc($name),
intval($profile_uid)
intval($profile_uid),
dbesc(NETWORK_OSTATUS)
);
// Then check in the contact table for the url
if (!$r)
$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `notify`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `contact`
WHERE `nurl` = '%s' AND `uid` = %d AND
(`network` != '%s' OR (`notify` != '' AND `alias` != ''))
LIMIT 1",
dbesc(normalise_link($name)),
intval($profile_uid)
intval($profile_uid),
dbesc(NETWORK_OSTATUS)
);
// Then check in the global contacts for the address
if (!$r)
$r = q("SELECT `url`, `name`, `nick`, `network`, `alias`, `notify` FROM `gcontact` WHERE `addr` = '%s' LIMIT 1", dbesc($name));
$r = q("SELECT `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `gcontact`
WHERE `addr` = '%s' AND (`network` != '%s' OR (`notify` != '' AND `alias` != ''))
LIMIT 1",
dbesc($name),
dbesc(NETWORK_OSTATUS)
);
// Then check in the global contacts for the url
if (!$r)
$r = q("SELECT `url`, `name`, `nick`, `network`, `alias`, `notify` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link($name)));
// If the data isn't complete then refetch the data
if ($r AND ($r[0]["network"] == NETWORK_OSTATUS) AND (($r[0]["notify"] == "") OR ($r[0]["alias"] == "")))
$r = false;
$r = q("SELECT `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `gcontact`
WHERE `nurl` = '%s' AND (`network` != '%s' OR (`notify` != '' AND `alias` != ''))
LIMIT 1",
dbesc(normalise_link($name)),
dbesc(NETWORK_OSTATUS)
);
if (!$r) {
$probed = probe_url($name);
if (isset($probed["url"])) {
if ($result['network'] != NETWORK_PHANTOM) {
update_gcontact($probed);
$r = q("SELECT `url`, `name`, `nick`, `network`, `alias`, `notify` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link($probed["url"])));
@ -1175,7 +1202,7 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
//select someone from this user's contacts by name in the current network
if (!$r AND ($network != ""))
$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `name` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1",
dbesc($newname),
dbesc($name),
dbesc($network),
intval($profile_uid)
);
@ -1192,7 +1219,7 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
//select someone from this user's contacts by name
if(!$r)
$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
dbesc($newname),
dbesc($name),
intval($profile_uid)
);
}
@ -1215,13 +1242,13 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
}
//if there is an url for this persons profile
if(isset($profile)) {
if (isset($profile) AND ($newname != "")) {
$replaced = true;
//create profile link
$profile = str_replace(',','%2c',$profile);
$newtag = '@[url=' . $profile . ']' . $newname . '[/url]';
$body = str_replace('@' . $name, $newtag, $body);
$newtag = '@[url='.$profile.']'.$newname.'[/url]';
$body = str_replace('@'.$name, $newtag, $body);
//append tag to str_tags
if(! stristr($str_tags,$newtag)) {
if(strlen($str_tags))
@ -1233,7 +1260,7 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
// subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both.
if(strlen($alias)) {
$newtag = '@[url=' . $alias . ']' . $newname . '[/url]';
$newtag = '@[url='.$alias.']'.$newname.'[/url]';
if(! stristr($str_tags,$newtag)) {
if(strlen($str_tags))
$str_tags .= ',';
@ -1245,42 +1272,3 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
return array('replaced' => $replaced, 'contact' => $r[0]);
}
function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, $post_id) {
// We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key
$enabled = intval(get_config('system','diaspora_enabled'));
if(! $enabled) {
logger('mod_item: diaspora support disabled, not storing comment signature', LOGGER_DEBUG);
return;
}
logger('mod_item: storing diaspora comment signature');
require_once('include/bb2diaspora.php');
$signed_body = html_entity_decode(bb2diaspora($datarray['body']));
// Only works for NETWORK_DFRN
$contact_baseurl_start = strpos($author['url'],'://') + 3;
$contact_baseurl_length = strpos($author['url'],'/profile') - $contact_baseurl_start;
$contact_baseurl = substr($author['url'], $contact_baseurl_start, $contact_baseurl_length);
$diaspora_handle = $author['nick'] . '@' . $contact_baseurl;
$signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $diaspora_handle;
if( $uprvkey !== false )
$authorsig = rsa_sign($signed_text,$uprvkey,'sha256');
else
$authorsig = '';
q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
intval($post_id),
dbesc($signed_text),
dbesc(base64_encode($authorsig)),
dbesc($diaspora_handle)
);
return;
}

View file

@ -67,8 +67,10 @@ function match_content(&$a) {
if (!count($match)) {
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
$connlnk = $a->get_baseurl() . '/follow/?url=' . $jj->url;
$photo_menu = array(array(t("View Profile"), zrl($jj->url)));
$photo_menu[] = array(t("Connect/Follow"), $connlnk);
$photo_menu = array(
'profile' => array(t("View Profile"), zrl($jj->url)),
'follow' => array(t("Connect/Follow"), $connlnk)
);
$contact_details = get_contact_details_by_url($jj->url, local_user());

View file

@ -2,6 +2,7 @@
require_once('include/acl_selectors.php');
require_once('include/message.php');
require_once('include/Smilies.php');
function message_init(&$a) {
@ -182,7 +183,7 @@ function message_content(&$a) {
return;
}
$myprofile = 'profile/' . $a->user['nickname'];
$myprofile = $a->get_baseurl().'/profile/' . $a->user['nickname'];
$tpl = get_markup_template('mail_head.tpl');
$header = replace_macros($tpl, array(
@ -304,15 +305,29 @@ function message_content(&$a) {
$prename = $preurl = $preid = '';
if($preselect) {
$r = q("select name, url, id from contact where uid = %d and id = %d limit 1",
$r = q("SELECT `name`, `url`, `id` FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1",
intval(local_user()),
intval($a->argv[2])
);
if(!$r) {
$r = q("SELECT `name`, `url`, `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1",
intval(local_user()),
dbesc(normalise_link(base64_decode($a->argv[2])))
);
}
if(!$r) {
$r = q("SELECT `name`, `url`, `id` FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
intval(local_user()),
dbesc(base64_decode($a->argv[2]))
);
}
if(count($r)) {
$prename = $r[0]['name'];
$preurl = $r[0]['url'];
$preid = $r[0]['id'];
}
$preselect = array($preid);
} else
$preselect = false;
}
$prefill = (($preselect) ? $prename : '');
@ -341,7 +356,6 @@ function message_content(&$a) {
'$wait' => t('Please wait'),
'$submit' => t('Submit')
));
return $o;
}
@ -356,8 +370,7 @@ function message_content(&$a) {
$r = q("SELECT count(*) AS `total` FROM `mail`
WHERE `mail`.`uid` = %d GROUP BY `parent-uri` ORDER BY `created` DESC",
intval(local_user()),
dbesc($myprofile)
intval(local_user())
);
if(count($r)) $a->set_pager_total($r[0]['total']);
@ -446,9 +459,11 @@ function message_content(&$a) {
if($message['from-url'] == $myprofile) {
$from_url = $myprofile;
$sparkle = '';
}
else {
$from_url = 'redir/' . $message['contact-id'];
} elseif ($message['contact-id'] != 0) {
$from_url = 'redir/'.$message['contact-id'];
$sparkle = ' sparkle';
} else {
$from_url = $message['from-url']."?zrl=".urlencode($myprofile);
$sparkle = ' sparkle';
}
@ -460,22 +475,27 @@ function message_content(&$a) {
if($a->theme['template_engine'] === 'internal') {
$from_name_e = template_escape($message['from-name']);
$subject_e = template_escape($message['title']);
$body_e = template_escape(smilies(bbcode($message['body'])));
$body_e = template_escape(Smilies::replace(bbcode($message['body'])));
$to_name_e = template_escape($message['name']);
}
else {
} else {
$from_name_e = $message['from-name'];
$subject_e = $message['title'];
$body_e = smilies(bbcode($message['body']));
$body_e = Smilies::replace(bbcode($message['body']));
$to_name_e = $message['name'];
}
$contact = get_contact_details_by_url($message['from-url']);
if (isset($contact["thumb"]))
$from_photo = $contact["thumb"];
else
$from_photo = $message['from-photo'];
$mails[] = array(
'id' => $message['id'],
'from_name' => $from_name_e,
'from_url' => $from_url,
'sparkle' => $sparkle,
'from_photo' => $message['from-photo'],
'from_photo' => proxy_url($from_photo, false, PROXY_SIZE_THUMB),
'subject' => $subject_e,
'body' => $body_e,
'delete' => t('Delete message'),
@ -549,19 +569,16 @@ function render_messages($msg, $t) {
$tpl = get_markup_template($t);
$rslt = '';
$myprofile = 'profile/' . $a->user['nickname'];
$myprofile = $a->get_baseurl().'/profile/' . $a->user['nickname'];
foreach($msg as $rr) {
if($rr['unknown']) {
if($rr['unknown'])
$participants = sprintf( t("Unknown sender - %s"),$rr['from-name']);
}
elseif (link_compare($rr['from-url'], $myprofile)){
elseif (link_compare($rr['from-url'], $myprofile))
$participants = sprintf( t("You and %s"), $rr['name']);
}
else {
$participants = sprintf( t("%s and You"), $rr['from-name']);
}
else
$participants = sprintf(t("%s and You"), $rr['from-name']);
if($a->theme['template_engine'] === 'internal') {
$subject_e = template_escape((($rr['mailseen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'));
@ -574,12 +591,18 @@ function render_messages($msg, $t) {
$to_name_e = $rr['name'];
}
$contact = get_contact_details_by_url($rr['url']);
if (isset($contact["thumb"]))
$from_photo = $contact["thumb"];
else
$from_photo = (($rr['thumb']) ? $rr['thumb'] : $rr['from-photo']);
$rslt .= replace_macros($tpl, array(
'$id' => $rr['id'],
'$from_name' => $participants,
'$from_url' => (($rr['network'] === NETWORK_DFRN) ? 'redir/' . $rr['contact-id'] : $rr['url']),
'$sparkle' => ' sparkle',
'$from_photo' => (($rr['thumb']) ? $rr['thumb'] : $rr['from-photo']),
'$from_photo' => proxy_url($from_photo, false, PROXY_SIZE_THUMB),
'$subject' => $subject_e,
'$delete' => t('Delete conversation'),
'$body' => $body_e,

View file

@ -62,7 +62,7 @@ function mood_init(&$a) {
$action = sprintf( t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' , $verbs[$verb]);
$arr = array();
$arr['guid'] = get_guid(32);
$arr['uid'] = $uid;
$arr['uri'] = $uri;
$arr['parent-uri'] = (($parent_uri) ? $parent_uri : $uri);

View file

@ -143,7 +143,7 @@ function network_init(&$a) {
// search terms header
if(x($_GET,'search')) {
$a->page['content'] .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => sprintf( t('Search Results For: %s'), $search)
'$title' => sprintf( t('Results for: %s'), $search)
));
}
@ -720,17 +720,14 @@ function network_content(&$a, $update = 0) {
$sql_order = "`item`.`received`";
// "New Item View" - show all items unthreaded in reverse created date order
$items = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, `contact`.`writable`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM $sql_table $sql_post_table INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
WHERE `item`.`uid` = %d AND `item`.`visible` = 1
AND `item`.`deleted` = 0 AND `item`.`moderated` = 0
$items = q("SELECT %s, %s FROM $sql_table $sql_post_table
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND %s
WHERE %s AND `item`.`uid` = %d
$simple_update
$sql_extra $sql_nets
ORDER BY $sql_order DESC $pager_sql ",
item_fieldlist(), contact_fieldlist(),
contact_condition(), item_condition(),
intval($_SESSION['uid'])
);
@ -810,16 +807,13 @@ function network_content(&$a, $update = 0) {
foreach ($parents_arr AS $parents) {
// $sql_extra ORDER BY `item`.`commented` DESC LIMIT %d",
$thread_items = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`rel`, `contact`.`writable`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
AND `item`.`moderated` = 0
$thread_items = q("SELECT %s, %s FROM `item`
INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND %s
WHERE %s AND `item`.`uid` = %d
AND `item`.`parent` = %d
ORDER BY `item`.`commented` DESC LIMIT %d",
item_fieldlist(), contact_fieldlist(),
contact_condition(), item_condition(),
intval(local_user()),
intval($parents),
intval($max_comments + 1)
@ -857,14 +851,24 @@ function network_content(&$a, $update = 0) {
if((! $group) && (! $cid) && (! $star)) {
$r = q("UPDATE `item` SET `unseen` = 0
WHERE `unseen` = 1 AND `uid` = %d",
intval(local_user())
);
$unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `uid` = %d",
intval(local_user()));
if ($unseen)
$r = q("UPDATE `item` SET `unseen` = 0
WHERE `unseen` = 1 AND `uid` = %d",
intval(local_user())
);
}
else {
if($update_unseen)
$r = q("UPDATE `item` SET `unseen` = 0 $update_unseen");
if($update_unseen) {
$unseen = q("SELECT `id` FROM `item` ".$update_unseen);
if ($unseen)
$r = q("UPDATE `item` SET `unseen` = 0 $update_unseen");
}
}
// Set this so that the conversation function can find out contact info for our wall-wall items

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