Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Michael Vogel 2015-12-22 11:27:49 +01:00
commit a91ce7c0d1
295 changed files with 39666 additions and 25660 deletions

View File

@ -1,6 +1,85 @@
Version 3.4.3
What's new for the users:
Updates to the documentation (silke, tobiasd, annando, rebeka-catalina)
Updated translations (tobiasd & translation teams)
New "Credits" page (tobiasd)
New custom font icon set (tobiasd, Andi Stadler)
Support to events attendance. Users can mark their participation to an event (rabuzarus, tobiasd, fabrixxm, annando)
Revised templates and used interaction in contacts lists (rabuzarus)
Mobile support for Vier theme (annando, fabrixxm)
Events editing and deletion from stream (annando)
Private forums are mentioned automatically like community forums (rabuzarus)
Show profile pictures and pending notifications on manage page (rabuzarus, annando)
Show Profile photo album only to owner and authenticated contacts (rabuzarus)
User language setting is now between settings in user settings page (fabrixxm)
Search for remote users in form of "@user@domain.tld" is supported (issue #1595) (annando)
Optionally show geo informations of uploaded photos, backport from Red (rabuzarus)
Setting for the first day of the week for events calendar (annando)
Reduced profile view with "show more" link (annando)
Show more informations to users when following a new contact (annando)
Renamed "Statusnet" to "GNU Social" (annando)
Image dialog insert link to image page instead of direct image (fabrixxm)
In registration page make clear that we only need a 'real-looking' name (issue #1898) (tobiasd, n4rky)
Unseen items per groups are shown (issue #1718) (strk, rabuzarus, fabrixxm)
Unseen items in forumlist widget (rabuzarus)
Preview the last five conversations in private message's sidebar (FlxAlbroscheit, fabrixxm)
Don't get notifications about own posts (strk)
Profile page shows a "Subscribe to atom feed" link (annando)
Contact list shows only contacts from supported networks (ananndo)
username@hostname is used instead of full urls (issue #1925) (annando)
Various small OStatus improvements (annando)
Contact's posts are shown in a dedicated page (annando)
Module name is shown in page title to ease browser history navigation (issue #2079) (tobiasd)
What's new for admins:
Forumlist functionality moved from plugin to core (rabuzarus, annando)
Changes on poller/workers limits management (annando)
Diaspora and OStatus can be enabled only if requirements are satisfied (annando)
Support for additional passwords for ejabberd (annando)
Use proxy for profile photos (annando)
'Reload active themes' in theme admin page (fabrixxm)
Install routine checks for ImageMagick and GIF support (fabrixxm)
Install routine checks for availability of "mcrypt_create_iv()" function, needed for RINO2 (fabrixxm)
Only suported themes are shown in admin page (annando)
Optimized SQL queries (annando)
System perform an optimize pass on tables in cron, with maximum table size and minimum fragmentation level settings (annando)
New access keys in profile and contact pages (rabuzarus, annando)
Support for a new Diaspora command for post retraction (annando)
Show an info message if an empty contact group is shown (issue #1871) (annando)
User setting to disable network page autoupdate (issue #1921) (annando)
Settings to limit or permit access to crawler to search page (annando)
What's new for developers:
Themes can show Events entry in navbar (annando)
Themes can now override colorbox (fabrixxm)
Updated Vagrant development VM (silke, hauke)
New hook 'template_vars' (fabrixxm)
$baseurl variable is passed to all templates by default (fabrixxm)
OStatus delivery code is moved in new function (annando)
Doxygen config file and initial documetation of code (rabuzarus)
Full rewrite of util/php2po.php (fabrixxm)
Bugfixs:
Remote self works again (annando)
Fix feeds mistakenly recognized as OStatus (issue #1914) (annando)
Report invalid feeds to user (issue #1913) (annando)
Fix Update contact data functionality (annando)
Fix proxy function with embedded images (annando)
Fix Diaspora unidirectional connect request (annando)
Fix empty poco response (annando)
Fix API for andStatus (issue#1427, AndStatus issue #241) (annando)
Fix expiration of items (fabrixxm)
Fix javascript contact deletion confirmation dialog (issue #1986) (fabrixxm)
Admin wasn't able to change settings of not currently in use themes. Fixed (issue #2022) (fabrixxm)
Fix rapid repeated requests to GNUSocial instance (issue #2038) (annando)
Fix install routine css when mod_rewrite doesn't works (issue #2071) (fabrixxm)
Fix code to be compliant with minimum required PHP version (issue #2066) (fabrixxm, rabuzarus)
Fix feedback after succesfull registration (issue #2060) (annando)
Fix mention completition popup with TinyMCE (issue #1920) (fabrixxm)
Fix photo cache and proxy when installed in subfolder (ddorian1)
Fix bbcode conversion of the about text for the profile (issue #1607) (annando)
Version 3.4.2
Updates to the documentation (tobias, silke, annando)
Updates to the documentation (tobiasd, silke, annando)
Updates to the translations (tobiasd & translation teams)
Updates to themes frost-mobile, vier, duepuntozero, quattro (annando, tobiasd)
Enancements of the communications via OStatus and Diaspora protocols (annando)

66
Vagrantfile vendored
View File

@ -1,16 +1,19 @@
server_ip = "192.168.22.10"
server_memory = "384" # MB
server_timezone = "UTC"
server_ip = "192.168.22.10"
server_memory = "384" # MB
server_timezone = "UTC"
public_folder = "/vagrant"
public_folder = "/vagrant"
Vagrant.configure("2") do |config|
Vagrant.configure(2) do |config|
# Set server to Ubuntu 12.04
config.vm.box = "precise64"
# Set server to Ubuntu 14.04
config.vm.box = "ubuntu/trusty64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a hostname, don't forget to put it to the `hosts` file
# This will point to the server's default virtual host
@ -20,40 +23,21 @@ Vagrant.configure("2") do |config|
# Create a static IP
config.vm.network :private_network, ip: server_ip
# If using VirtualBox
config.vm.provider :virtualbox do |vb|
# Set server memory
vb.customize ["modifyvm", :id, "--memory", server_memory]
# Set the timesync threshold to 10 seconds, instead of the default 20 minutes.
# If the clock gets more than 15 minutes out of sync (due to your laptop going
# to sleep for instance, then some 3rd party services will reject requests.
vb.customize ["guestproperty", "set", :id, "/VirtualBox/GuestAdd/VBoxService/--timesync-set-threshold", 10000]
# Prevent VMs running on Ubuntu to lose internet connection
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
# Share a folder between host and guest
config.vm.synced_folder "./", "/vagrant/", owner: "www-data", group: "vagrant"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
vb.memory = server_memory
end
# If using VMWare Fusion
config.vm.provider "vmware_fusion" do |vb, override|
override.vm.box_url = "http://files.vagrantup.com/precise64_vmware.box"
# Set server memory
vb.vmx["memsize"] = server_memory
end
####
# Local Scripts
# Any local scripts you may want to run post-provisioning.
# Add these to the same directory as the Vagrantfile.
##########
config.vm.synced_folder "./", "/vagrant/", :owner=> 'www-data', :group=>'vagrant', :mount_options => ['dmode=775', 'fmode=775']
config.vm.provision "shell", path: "./util/vagrant_provision.sh"
# Enable provisioning with a shell script.
config.vm.provision "shell", path: "./util/vagrant_provision.sh"
# run: "always"
# run: "once"
end

118
boot.php
View File

@ -17,9 +17,9 @@ require_once('include/dbstructure.php');
define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Lily of the valley');
define ( 'FRIENDICA_VERSION', '3.4.2' );
define ( 'FRIENDICA_VERSION', '3.4.3' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1188 );
define ( 'DB_UPDATE_VERSION', 1191 );
define ( 'EOL', "<br />\r\n" );
define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
@ -163,7 +163,8 @@ define ( 'NETWORK_TWITTER', 'twit'); // Twitter
define ( 'NETWORK_DIASPORA2', 'dspc'); // Diaspora connector
define ( 'NETWORK_STATUSNET', 'stac'); // Statusnet connector
define ( 'NETWORK_APPNET', 'apdn'); // app.net
define ( 'NETWORK_NEWS', 'nntp'); // Network News Transfer Protocol
define ( 'NETWORK_ICALENDAR', 'ical'); // iCalendar
define ( 'NETWORK_PHANTOM', 'unkn'); // Place holder
/**
@ -189,7 +190,9 @@ $netgroup_ids = array(
NETWORK_TWITTER => (-14),
NETWORK_DIASPORA2 => (-15),
NETWORK_STATUSNET => (-16),
NETWORK_APPNET => (-17),
NETWORK_APPNET => (-17),
NETWORK_NEWS => (-18),
NETWORK_ICALENDAR => (-19),
NETWORK_PHANTOM => (-127),
);
@ -270,6 +273,10 @@ define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
define ( 'ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like' );
define ( 'ACTIVITY_DISLIKE', NAMESPACE_DFRN . '/dislike' );
define ( 'ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes' );
define ( 'ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno' );
define ( 'ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe' );
define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_DFRN . '/heart' );
define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
@ -408,6 +415,7 @@ if(! class_exists('App')) {
public $videoheight = 350;
public $force_max_items = 0;
public $theme_thread_allow = true;
public $theme_events_in_profile = true;
// An array for all theme-controllable parameters
// Mostly unimplemented yet. Only options 'stylesheet' and
@ -626,6 +634,9 @@ if(! class_exists('App')) {
$basepath = get_config("system", "basepath");
if ($basepath == "")
$basepath = dirname(__FILE__);
if ($basepath == "")
$basepath = $_SERVER["DOCUMENT_ROOT"];
@ -726,10 +737,22 @@ if(! class_exists('App')) {
function init_pagehead() {
$interval = ((local_user()) ? get_pconfig(local_user(),'system','update_interval') : 40000);
// If the update is "deactivated" set it to the highest integer number (~24 days)
if ($interval < 0)
$interval = 2147483647;
if($interval < 10000)
$interval = 40000;
$this->page['title'] = $this->config['sitename'];
// compose the page title from the sitename and the
// current module called
if (!$this->module=='')
{
$this->page['title'] = $this->config['sitename'].' ('.$this->module.')';
} else {
$this->page['title'] = $this->config['sitename'];
}
/* put the head template at the beginning of page['htmlhead']
* since the code added by the modules frequently depends on it
@ -1432,8 +1455,46 @@ if(! function_exists('proc_run')) {
if(! $arr['run_cmd'])
return;
if(count($args) && $args[0] === 'php')
if(count($args) && $args[0] === 'php') {
if (get_config("system", "worker")) {
$argv = $args;
array_shift($argv);
$parameters = json_encode($argv);
$found = q("SELECT `id` FROM `workerqueue` WHERE `parameter` = '%s'",
dbesc($parameters));
if (!$found)
q("INSERT INTO `workerqueue` (`parameter`, `created`, `priority`)
VALUES ('%s', '%s', %d)",
dbesc($parameters),
dbesc(datetime_convert()),
intval(0));
// Should we quit and wait for the poller to be called as a cronjob?
if (get_config("system", "worker_dont_fork"))
return;
// Checking number of workers
$workers = q("SELECT COUNT(*) AS `workers` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
// Get number of allowed number of worker threads
$queues = intval(get_config("system", "worker_queues"));
if ($queues == 0)
$queues = 4;
// If there are already enough workers running, don't fork another one
if ($workers[0]["workers"] >= $queues)
return;
// Now call the poller to execute the jobs that we just added to the queue
$args = array("php", "include/poller.php", "no_cron");
}
$args[0] = ((x($a->config,'php_path')) && (strlen($a->config['php_path'])) ? $a->config['php_path'] : 'php');
}
// add baseurl to args. cli scripts can't construct it
$args[] = $a->get_baseurl();
@ -1441,9 +1502,8 @@ if(! function_exists('proc_run')) {
for($x = 0; $x < count($args); $x ++)
$args[$x] = escapeshellarg($args[$x]);
$cmdline = implode($args," ");
if(get_config('system','proc_windows'))
proc_close(proc_open('cmd /c start /b ' . $cmdline,array(),$foo,dirname(__FILE__)));
else
@ -1620,7 +1680,7 @@ if(! function_exists('load_contact_links')) {
if(! $uid || x($a->contacts,'empty'))
return;
$r = q("SELECT `id`,`network`,`url`,`thumb` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `thumb` != ''",
$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)) {
@ -1860,3 +1920,43 @@ if(!function_exists('exif_imagetype')) {
return($size[2]);
}
}
function validate_include(&$file) {
$orig_file = $file;
$file = realpath($file);
if (strpos($file, getcwd()) !== 0)
return false;
$file = str_replace(getcwd()."/", "", $file, $count);
if ($count != 1)
return false;
if ($orig_file !== $file)
return false;
$valid = false;
if (strpos($file, "include/") === 0)
$valid = true;
if (strpos($file, "addon/") === 0)
$valid = true;
if (!$valid)
return false;
return true;
}
function current_load() {
if (!function_exists('sys_getloadavg'))
return false;
$load_arr = sys_getloadavg();
if (!is_array($load_arr))
return false;
return max($load_arr);
}

View File

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 3.4.1 (Lily of the valley)
-- DB_UPDATE_VERSION 1188
-- Friendica 3.4.2 (Lily of the valley)
-- DB_UPDATE_VERSION 1190
-- ------------------------------------------
@ -317,6 +317,7 @@ CREATE TABLE IF NOT EXISTS `gcontact` (
`gender` varchar(32) NOT NULL DEFAULT '',
`community` tinyint(1) NOT NULL DEFAULT 0,
`network` varchar(255) NOT NULL DEFAULT '',
`addr` varchar(255) NOT NULL DEFAULT '',
`generation` tinyint(3) NOT NULL DEFAULT 0,
`server_url` varchar(255) NOT NULL DEFAULT '',
INDEX `nurl` (`nurl`),
@ -1020,3 +1021,16 @@ CREATE TABLE IF NOT EXISTS `userd` (
INDEX `username` (`username`)
) DEFAULT CHARSET=utf8;
--
-- TABLE workerqueue
--
CREATE TABLE IF NOT EXISTS `workerqueue` (
`id` int(11) NOT NULL auto_increment PRIMARY KEY,
`parameter` text NOT NULL,
`priority` tinyint(3) unsigned NOT NULL DEFAULT 0,
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`pid` int(11) NOT NULL DEFAULT 0,
`executed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
INDEX `created` (`created`)
) DEFAULT CHARSET=utf8;

View File

@ -19,6 +19,7 @@ General
* v: Videos
* e: Events and Calendar
* t: Personal Notes
* k: View Contacts
/contacts (contact list)
---------
@ -32,6 +33,10 @@ General
/contacts (single contact view)
-------------------------------
* m: Status messages
* o: Profile
* t: Contacts
* d: Common friends
* b: Toggle Blocked status
* i: Toggle Ignored status
* v: Toggle Archive status

View File

@ -23,7 +23,7 @@ The following window shows some text while connecting.
This text isn't importend for you, just wait for the next window.
The first line shows your name and your current IP address.
The right part of the window shows all users.
The lower part of the window contains an input field.
The lower part of the window contains an input field.
Jappix Mini
---
@ -41,7 +41,7 @@ You can use several servers to create an account:
At first you have to get the current version. You can either pull it from [Github](https://github.com) like so:
$> cd /var/www/virtual/YOURSPACE/html/addon; git pull
$> cd /var/www/virtual/YOURSPACE/html/addon; git pull
Or you can download a tar archive here: [jappixmini.tgz](https://github.com/friendica/friendica-addons/blob/master/jappixmini.tgz) (click at „view raw“).
@ -63,9 +63,10 @@ At first you have to activate the addon.
Now add your Jabber/XMPP name, the domain/server (without "http"; just "jappix.com").
For „Jabber BOSH Host“ you could use "https://bind.jappix.com/".
Note that you need another BOSH server if you do not use jappix.com for your XMPP account.
You can find further information in the „Configuration Help“-section below this fields.
At last you have enter your password (there are some more optional options, you can choose).
Finish these steps with "send" to save the entries.
Finish these steps with "send" to save the entries.
Now, you should find the chatbox at the lower right corner of your browser window.
If you want to add contacts manually, you can click "add contact".
If you want to add contacts manually, you can click "add contact".

View File

@ -54,6 +54,8 @@ Have a look at our [issue tracker](https://github.com/friendica/friendica) on gi
* Try to reproduce a bug that needs more inquries and write down what you find out.
* If a bug looks fixed, ask the bug reporters for feedback to find out if the bug can be closed.
* Fix a bug if you can. Please make the pull request against the *develop* branch of the repository.
* There is a *Junior Job* label for issues we think might be a good point to start with.
But you don't have to limit yourself to those issues.
###Web interface

View File

@ -87,8 +87,8 @@ However their conversations with your friends will still be visible in your stre
If you remove a contact completely, they can send you another friend request.
Blocked contacts cannot do this. They cannot communicate with you directly, only through friends.
**Ignored contacts** are included in delivery - they will receive your posts.
However we do not import their posts to you.
**Ignored contacts** are included in delivery - they will receive your posts and private messages.
However we do not import their posts or private messages to you.
Like blocking, you will still see this person's comments to posts made by your friends.
A plugin called "blockem" can be installed to collapse/hide all posts from a particular person in your stream if you desire complete blocking of an individual, including his/her conversations with your other friends.

View File

@ -10,7 +10,7 @@ Friendica Documentation and Resources
* [BBCode tag reference](help/BBCode)
* [Comment, sort and delete posts](help/Text_comment)
* [Profiles](help/Profiles)
* [Accesskey reference](help/Accesskeys
* [Accesskey reference](help/Accesskeys)
* [Events](help/events)
* You and other users
* [Connectors](help/Connectors)
@ -30,9 +30,11 @@ Friendica Documentation and Resources
* [Install](help/Install)
* [Settings](help/Settings)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd)
* [Message Flow](help/Message-Flow)
* [Using SSL with Friendica](help/SSL)
* [Twitter/GNU Social API Functions](help/api)
* [Config values that can only be set in .htconfig.php](help/htconfig)
**Developer Manual**
@ -44,6 +46,7 @@ Friendica Documentation and Resources
* [Plugin Development](help/Plugins)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
* [Code - Reference(Doxygen generated - sets cookies)](doc/html/)
**External Resources**
@ -53,4 +56,5 @@ Friendica Documentation and Resources
**About**
* [Site/Version Info](friendica)
* [Friendica Credits](credits)

View File

@ -10,9 +10,11 @@ Not every PHP/MySQL hosting provider will be able to support Friendica.
Many will.
But **please** review the requirements and confirm these with your hosting provider prior to installation.
Also if you encounter installation issues, please let us know via the [helper]() or the [developer]() forum or [file an issue](https://github.com/friendica/friendica/issues).
Also if you encounter installation issues, please let us know via the [helper](http://helpers.pyxis.uberspace.de/profile/helpers) or the [developer](https://friendika.openmindspace.org/profile/friendicadevelopers) forum or [file an issue](https://github.com/friendica/friendica/issues).
Please be as clear as you can about your operating environment and provide as much detail as possible about any error messages you may see, so that we can prevent it from happening in the future.
Due to the large variety of operating systems and PHP platforms in existence we may have only limited ability to debug your PHP installation or acquire any missing modules - but we will do our best to solve any general code issues.
Due to the large variety of operating systems and PHP platforms in existence we may have only limited ability to debug your PHP installation or acquire any missing modules - but we will do our best to solve any general code issues.
If you do not have a Friendica account yet, you can register a temporary one at [tryfriendica.de](https://tryfriendica.de) and join the forums mentioned above from there.
The account will expire after 7 days, but you can ask the server admin to keep your account longer, should the problem not be resolved after that.
Before you begin: Choose a domain name or subdomain name for your server.
Put some thought into this. Changing it after installation is currently not supported.
@ -29,7 +31,7 @@ Requirements
* curl, gd, mysql, hash and openssl extensions
* some form of email server or email gateway such that PHP mail() works
* mcrypt (optional; used for server-to-server message encryption)
* Mysql 5.x
* Mysql 5.x or an equivalant alternative for MySQL (MariaDB etc.)
* the ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks (Windows) (Note: other options are presented in Section 7 of this document.)
* Installation into a top-level domain or sub-domain (without a directory/path component in the URL) is preferred. Directory paths will not be as convenient to use and have not been thoroughly tested.
* If your hosting provider doesn't allow Unix shell access, you might have trouble getting everything to work.
@ -42,23 +44,23 @@ Installation procedure
Unpack the Friendica files into the root of your web server document area.
If you are able to do so, we recommend using git to clone the source repository rather than to use a packaged tar or zip file.
This makes the software much easier to update.
The Linux command to clone the repository into a directory "mywebsite" would be
The Linux command to clone the repository into a directory "mywebsite" would be
git clone https://github.com/friendica/friendica.git mywebsite
git clone https://github.com/friendica/friendica.git mywebsite
Make sure the folder *view/smarty3* exists and is writable by the webserver user
mkdir view/smarty3
chmod 777 view/smarty3
mkdir view/smarty3
chmod 777 view/smarty3
Get the addons by going into your website folder.
cd mywebsite
cd mywebsite
Clone the addon repository (separately):
git clone https://github.com/friendica/friendica-addons.git addon
git clone https://github.com/friendica/friendica-addons.git addon
If you copy the directory tree to your webserver, make sure that you also copy .htaccess - as "dot" files are often hidden and aren't normally copied.
###Create a database
@ -87,14 +89,14 @@ You might wish to move/rename .htconfig.php to another name and empty (called 'd
Set up a cron job or scheduled task to run the poller once every 5-10 minutes in order to perform background processing.
Example:
cd /base/directory; /path/to/php include/poller.php
cd /base/directory; /path/to/php include/poller.php
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
If you are using a Linux server, run "crontab -e" and add a line like the
one shown, substituting for your unique paths and settings:
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php include/poller.php
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php include/poller.php
You can generally find the location of PHP by executing "which php".
If you run into trouble with this section please contact your hosting provider for assistance.
@ -104,25 +106,31 @@ Alternative: You may be able to use the 'poormancron' plugin to perform this ste
To do this, edit the file ".htconfig.php" and look for a line describing your plugins.
On a fresh installation, it will look like this:
$a->config['system']['addon'] = 'js_upload';
$a->config['system']['addon'] = 'js_upload';
It indicates the "js_upload" addon module is enabled.
You may add additional addons/plugins using this same line in the configuration file.
Change it to read
$a->config['system']['addon'] = 'js_upload,poormancron';
$a->config['system']['addon'] = 'js_upload,poormancron';
and save your changes.
and save your changes.
Once you have installed Friendica and created an admin account as part of the process, you can access the admin panel of your installation and do most of the server wide configuration from there
Updating your installation with git
---
You can get the latest changes at any time with
cd mywebsite
git pull
cd mywebsite
git pull
The default branch to use it the ``master`` branch, which is the stable version of Friendica.
If you want to use and test bleeding edge code please checkout the ``develop`` branch.
The new features and fixes will be merged from ``develop`` into ``master`` when they are stable approx four times a year.
The addon tree has to be updated separately like so:
cd mywebsite/addon
git pull
cd mywebsite/addon
git pull

View File

@ -3,7 +3,7 @@ Friendica Addon/Plugin development
Please see the sample addon 'randplace' for a working example of using some of these features.
Addons work by intercepting event hooks - which must be registered.
Modules work by intercepting specific page requests (by URL path).
Modules work by intercepting specific page requests (by URL path).
Plugin names cannot contain spaces or other punctuation and are used as filenames and function names.
You may supply a "friendly" name within the comment block.
@ -12,12 +12,12 @@ For instance "plugin1name_install()".
These two functions take no arguments and are usually responsible for registering (and unregistering) event hooks that your plugin will require.
The install and uninstall functions will also be called (i.e. re-installed) if the plugin changes after installation.
Therefore your uninstall should not destroy data and install should consider that data may already exist.
Future extensions may provide for "setup" amd "remove".
Future extensions may provide for "setup" amd "remove".
Plugins should contain a comment block with the four following parameters:
Plugins should contain a comment block with the four following parameters:
/*
* Name: My Great Plugin
* Name: My Great Plugin
* Description: This is what my plugin does. It's really cool
* Version: 1.0
* Author: John Q. Public <john@myfriendicasite.com>
@ -52,7 +52,7 @@ It contains a wealth of information about the current state of Friendica:
* which module has been called,
* configuration information,
* the page contents at the point the hook was invoked,
* profile and user information, etc.
* profile and user information, etc.
It is recommeded you call this '$a' to match its usage elsewhere.
@ -77,7 +77,7 @@ This will include:
Your module functions will often contain the function plugin_name_content(&$a), which defines and returns the page body content.
They may also contain plugin_name_post(&$a) which is called before the _content function and typically handles the results of POST forms.
You may also have plugin_name_init(&$a) which is called very early on and often does module initialisation.
You may also have plugin_name_init(&$a) which is called very early on and often does module initialisation.
Templates
----------
@ -89,11 +89,11 @@ Put your tpl files in the *templates/* subfolder of your plugin.
In your code, like in the function plugin_name_content(), load the template file and execute it passing needed values:
# load template file. first argument is the template name,
# load template file. first argument is the template name,
# second is the plugin path relative to friendica top folder
$tpl = get_markup_template('mytemplate.tpl', 'addon/plugin_name/');
# apply template. first argument is the loaded template,
# apply template. first argument is the loaded template,
# second an array of 'name'=>'values' to pass to template
$output = replace_macros($tpl,array(
'title' => 'My beautiful plugin',
@ -271,6 +271,16 @@ $b is an array, params to mail()
is called after the navigational menu is build in include/nav.php.
$b is an array containing $nav from nav.php.
###'template_vars'
is called before vars are passed to the template engine to render the page.
The registered function can add,change or remove variables passed to template.
$b is an array with:
'template' => filename of template
'vars' => array of vars passed to template
Complete list of hook callbacks
---
@ -298,7 +308,7 @@ include/text.php: call_hooks('contact_block_end', $arr);
include/text.php: call_hooks('smilie', $s);
include/text.php: call_hooks('prepare_body_init', $item);
include/text.php: call_hooks('prepare_body_init', $item);
include/text.php: call_hooks('prepare_body', $prep_arr);
@ -310,7 +320,7 @@ include/auth.php: call_hooks('authenticate', $addon_auth);
include/bbcode.php: call_hooks('bbcode',$Text);
include/oauth.php: call_hooks('logged_in', $a->user);
include/oauth.php: call_hooks('logged_in', $a->user);
include/acl_selectors.php: call_hooks($a->module . '_pre_' . $selname, $arr);
@ -396,7 +406,7 @@ mod/photos.php: call_hooks('photo_post_end',intval($item_id));
mod/photos.php: call_hooks('photo_upload_form',$ret);
mod/friendica.php: call_hooks('about_hook', $o);
mod/friendica.php: call_hooks('about_hook', $o);
mod/editpost.php: call_hooks('jot_tool', $jotplugins);

View File

@ -3,166 +3,104 @@ Using SSL with Friendica
* [Home](help)
If you are running your own Friendica site, you may want to use SSL (https) to encrypt communication between yourself and your server (communication between servers is encrypted anyway).
Disclaimer
---
**This document has been updated in November 2015.
SSL encryption is relevant for security.
This means that recommended settings change fast.
Keep your setup up to date and do not rely on this document being updated as fast as technologies change!**
To do that on a domain of your own, you have to obtain a certificate from a trusted organization (so-called self-signed certificates that are popular among geeks dont work very well with Friendica, because they can cause disturbances in other people's browsers).
Intro
---
If you are running your own Friendica site, you may want to use SSL (https) to encrypt communication between servers and between yourself and your server.
If you are reading this document before actually installing Friendica, you might want to consider a very simple option: Go for a shared hosting account without your own domain name. That way, your address will be something like yourname.yourprovidersname.com, which isn't very fancy compared to yourname.com. But it will still be your very own site, and you will usually be able to hitch a lift on your provider's SSL certificate. That means that you won't need to configure SSL at all - it will simply work out of the box when people type https instead of http.
There are basically two sorts of SSL certificates: Self-signed certificates and certificates signed by a certificate authority (CA).
Technically, both provide the same valid encryption.
There is a problem with self-signed certificates though:
They are neither installed in browsers nor on other servers.
That is why they provoke warnings about "mistrusted certificates".
This is confusing and disturbing.
If that isn't your idea of doing things, read on...
For this reason, we recommend to get a certificate signed by a CA.
Normally, you have to pay for them - and they are valid for a limited period of time (e.g. a year or two).
**Shared hosts**
There are ways to get a trusted certificate for free.
If you are using a shared host on a domain of your own, your provider may well offer to obtain and install the certificate for you. You will then only need to apply and pay for it and everything will be set up. If that is the case for you, the rest of this document need not concern you at all. Just make sure the certificate is for the address that Friendica uses: e.g. myownfriendica.com or friendica.myserver.com.
Chose your domain name
---
The above ought to be the most common scenario for Friendica sites, making the rest of this article superfluous for most people.
Your SSL certificate will be valid for a domain or even only for a subdomain.
Make your final decision about your domain resp. subdomain *before* ordering the certificate.
Once you have it, changing the domain name means getting a new certificate.
**Obtaining a certificate yourself**
Shared hosts
---
Alternatively, a few shared hosting providers may ask you to obtain and upload the certificate yourself.
If your Friendica instance is running on a shared hosting platform, you should first check with your hosting provider.
They have instructions for you on how to do it there.
You can always order a paid certificate with your provider.
They will either install it for you or provide an easy way to upload the certificate and the key via a web interface.
The next section describes the process of acquiring a certificate from StartSSL. The good thing about StartSSL is that you can get an entry-level, but perfectly sufficient certificate for free. Thats not the case with most other certificate issuers - so we will be concentrating on StartSSL in this document If you want to use a certificate from a different source, you will have to follow the instructions given by that organization. We can't cover every possibility here.
Installing your certificate - once you have obtained it - depends on your providers way of doing things. But for shared hosts, there will usually be an easy web tool for this.
It might be worth asking if your provider would install a certificate you provide yourself, to save money.
If so, read on.
Note: Your certificate is usually restricted to one subdomain. When you apply for the certificate, make sure its for the domain and subdomain Friendica uses: e.g. myownfriendica.com or friendica.myserver.com.
Getting a free StartSSL certificate
---
StartSSL is a certificate authority that issues certificates for free.
They are valid for a year and are sufficient for our purposes.
**Getting a free StartSSL certificate**
### Step 1: Create a client certificate
StartSSLs website attempts to guide you through the process of obtaining a free certificate, but some people end up frustrated. We really recommend working your way through the steps on the site very slowly and carefully. Don't take things for granted - read every word before proceeding and don't close the browser window until everything is working. That said, there are three main stumbling blocks that can confuse users:
When you initially sign up with StartSSL, you receive a certificate that is installed in your browser.
You need it for the login on startssl.com, also when coming back to the site later.
It has nothing to do with the SSL certificate for your server.
When you initially sign up with StartSSL, the first certificate you receive is simply installed in your browser (though you should also store it somewhere safe, so that you can reinstall it in any other browser at a later date, for instance when you need to renew something). This authentication certificate is only used for logging on to the StartSSL website it has nothing to do with the certificate you will need for your server. As a first-timer with StartSSL, start here: https://www.startssl.com/?app=12 and choose the Express Lane option to get that browser authentication certificate. Then seamlessly continue to the process of acquiring the desired certificate for your server (the one you actually came for). You can change the websites language if that makes things easier for you.
### Step 2: Validate your email address and your domain
When you are first prompted for a domain to certify, you need to enter your top-level domain not the subdomain Friendica uses. In the next step, you will be able to specify that subdomain. So if you have friendica.yourname.com on your server, you first enter yourname.com and specify the subdomain friendica later.
To continue you have to prove that you own the email address you specified and the domain that you want a certificate for.
Specify your email address, request a validation link via email from the "validations wizard".
Same procedure for the domain validation.
Dont quit too fast when you have received your personal web server certificate at the end of the procedure. Depending on your server software, you will also require one or two generic files for use with this free StartSSL certificate. These are sub.class1.server.ca.pem and ca.pem. If you have already overlooked this step, you can download those files here: http://www.startssl.com/?app=21 But once again, the very best way of doing things is not to quit the StartSSL site until you are completely done and your https certificate is up and working.
### Step 3: Request the certificate
**Virtual private and dedicated servers (using StartSSL free)**
Go to the "certificates wizard".
Choose the target web server.
When you are first prompted for a domain to certify, you need to enter your main domain, e.g. example.com.
In the next step, you will be able to specify a subdomain for Friendica, if needed.
Example: If you have friendica.example.com, you first enter example.com, then specify the subdomain friendica later.
The rest of this document is slightly more complicated, but its only for people running Friendica on a virtual private or dedicated server. Everyone else can stop reading at this point.
If you know how to generate an openssl key and a certificate signing request (csr) yourself, do so.
Paste the csr into your browser to get it signed by StartSSL.
Follow the instructions here ( http://www.startssl.com/?app=20 ) to configure the web server you are using (e.g. Apache) for your certificate.
If you do not know how to generate a key and a csr, accept StartSSL's offer to generate it for you.
This means: StartSSL has the key to your encryption but it is better than no certificate at all.
Download your certificate from the website.
(Or in the second case: Download your certificate and your key.)
To illustrate the necessary changes, we will now assume you are running Apache. In essence, you can simply create a second httpd.conf entry for Friendica.
To install your certificate on a server, you need one or two extra files: sub.class1.server.ca.pem and ca.pem, delivered by startssl.com
Go to the "Tool box" section and download "Class 1 Intermediate Server CA" and "StartCom Root CA (PEM encoded)".
To do this, you copy the existing one and change the end of the first line to read :443> instead of :80>, then add the following lines to that entry, as also shown in StartSSLs instructions:
If you want to send your certificate to your hosting provider, they need the certificate, the key and probably at least the intermediate server CA.
To be sure, send those three and the ca.pem file.
**You should send them to your provider via an encrypted channel!**
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM
If you run your own server, upload the files and check out the Mozilla wiki link below.
SSLCertificateFile /usr/local/apache/conf/ssl.crt
SSLCertificateKeyFile /usr/local/apache/conf/ssl.key
SSLCertificateChainFile /usr/local/apache/conf/sub.class1.server.ca.pem
SSLCACertificateFile /usr/local/apache/conf/ca.pem
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
CustomLog /usr/local/apache/logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
Let's encrypt
---
(Note that the directory /usr/local/apache/conf/ may not exist on your machine. For Debian, for instance, the directory might be /etc/apache2/ - in which you can create an ssl subdirectory if it doesnt already exist. Then you have /etc/apache2/ssl/… instead of /usr/local/apache/conf/…)
If you run your own server and you control your name server, the "Let's encrypt" initiative might become an interesting alternative.
Their offer is not ready, yet.
Check out [their website](https://letsencrypt.org/) for status updates.
You thus end up with two entries for your Friendica site - one for simple http and one for https.
Web server settings
---
Note to those who want to force SSL: Don't redirect to SSL in your Apache settings. Friendica's own admin panel has a special setting for SSL policy. Please use this facility instead.
Visit the [Mozilla's wiki](https://wiki.mozilla.org/Security/Server_Side_TLS) for instructions on how to configure a secure webserver.
They provide recommendations for [different web servers](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations).
**Mixing certificates on Apache StartSSL and others (self-signed)**
Test your SSL settings
---
Many people using a virtual private or dedicated server will be running more than Friendica on it. They will probably want to use SSL for other sites they run on the server, too. To achieve this, they may wish to employ more than one certificate with a single IP for instance, a trusted one for Friendica and a self-signed certificate for personal stuff (possibly a wildcard certificate covering arbitrary subdomains).
For this to work, Apache offers a NameVirtualHost directive. You can see how to use it in httpd.conf in the following pattern. Note that wildcards (*) in httpd.conf break the NameVirtualHost method you cant use them in this new configuration. In other words, no more *80> or *443>. And you really must specify the IP, too, even if you only have one. Also note that you will soon be needing two additional NameVirtualHost lines at the top of the file to cater for IPv6.
NameVirtualHost 12.123.456.1:443
NameVirtualHost 12.123.456.1:80
<VirtualHost www.anywhere.net:80>
DocumentRoot /var/www/anywhere
Servername www.anywhere.net
</VirtualHost>
<VirtualHost www.anywhere.net:443>
DocumentRoot /var/www/anywhere
Servername www.anywhere.net
SSLEngine On
<pointers to a an eligible cert>
<more ssl stuff >
<other stuff>
</VirtualHost>
<VirtualHost www.somewhere-else.net:80>
DocumentRoot /var/www/somewhere-else
Servername www.somewhere-else.net
</VirtualHost>
<VirtualHost www.somewhere-else:443>
DocumentRoot /var/www/somewhere-else
Servername www.somewhere-else.net
SSLEngine On
<pointers to another eligible cert>
<more ssl stuff >
<other stuff>
</VirtualHost>
Of course, you may optionally be using other places like the sites-available directory to configure Apache, in which case only some of this information need be in httpd.conf or ports.conf - specifically, the NameVirtualHost lines must be there. But if you're savvy about alternatives like that, you will probably be able to figure out the details yourself.
Just restart Apache when you're done, whichever way you decide to do it.
**StartSSL on Nginx**
First, update to the latest Friendica code. Then follow the above instructions to get your free certificate. But instead of following the Apache installation instructions, do this:
Upload your certificate. It doesn't matter where to, as long as Nginx can find it. Some people use /home/randomlettersandnumbers to keep it in out of paranoia, but you can put it anywhere, so we'll call it /foo/bar.
You can remove the password if you like. This is probably bad practice, but if you don't, you'll have to enter the password every time you restart nginx. To remove it:
openssl rsa -in ssl.key-pass -out ssl.key
Now, grab the helper certificate:
wget http://www.startssl.com/certs/sub.class1.server.ca.pem
Now you need to merge the files:
cat ssl.crt sub.class1.server.ca.pem > ssl.crt
In some configurations there is a bug, and this doesn't quite work properly. You may now need to edit ssl.crt, so:
nano /foo/bar/ssl.crt
You'll see two certificates in the same file. Halfway down, you may see:
-----END CERTIFICATE----------BEGIN CERTIFICATE-----
This is bad. You need to see:
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
You can enter the carriage return manually if the bug is present on your system. Note there is a single carriage return for -----BEGIN CERTIFICATE----- to start on a new line. There is no empty line.
Now you need to tell Nginx about the certs.
In /etc/nginx/sites-available/foo.com.conf you need something like:
server {
listen 80;
listen 443 ssl;
listen [::]:80;
listen [::]:443 ipv6only=on ssl;
ssl_certificate /foo/bar/ssl.crt;
ssl_certificate_key /foo/bar/ssl.key;
...
Now, restart nginx:
/etc/init.d/nginx restart
And that's it.
For multiple domains, we have it easier than Apache users: Just repeat the above for each certificate, and keep it in it's own {server...} section.
When you are done, visit the test site [SSL Labs](https://www.ssllabs.com/ssltest/) to have them check if you succeeded.

View File

@ -198,7 +198,7 @@ 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 mistpark network.
This allows a private community to be completely isolated from the global network.
$a->config['system']['directory'] = 'http://dir.friendi.ca';

View File

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

View File

@ -3,33 +3,33 @@ Chats
* [Zur Startseite der Hilfe](help)
Du hast derzeit zwei Möglichkeiten, einen Chat auf Deiner Friendica-Seite zu betreiben
Du hast derzeit zwei Möglichkeiten, einen Chat auf Deiner Friendica-Seite zu betreiben
* IRC - Internet Relay Chat
* Jappix
##IRC Plugin
Sobald das Plugin aktiviert ist, kannst Du den Chat unter [deineSeite.de/irc](../irc) finden.
Beachte aber, dass dieser Chat auch ohne Anmeldung auf Deiner Seite zugänglich ist und somit auch Fremde diesen Chat mitnutzen können.
Sobald das Plugin aktiviert ist, kannst Du den Chat unter [deineSeite.de/irc](../irc) finden.
Beachte aber, dass dieser Chat auch ohne Anmeldung auf Deiner Seite zugänglich ist und somit auch Fremde diesen Chat mitnutzen können.
Wenn Du dem Link folgst, dann kommst Du zum Anmeldefenster des IR-Chats.
Wähle nun einen Spitznamen (Nickname) und wähle einen Raum aus, in dem Du chatten willst.
Hier kannst Du jeden Namen eingeben.
Es kann also auch #tollerChatdessenNamenurichkenne sein.
Wenn Du dem Link folgst, dann kommst Du zum Anmeldefenster des IR-Chats.
Wähle nun einen Spitznamen (Nickname) und wähle einen Raum aus, in dem Du chatten willst.
Hier kannst Du jeden Namen eingeben.
Es kann also auch #tollerChatdessenNamenurichkenne sein.
Gib als nächstes noch die Captchas ein, um zu zeigen, dass es sich bei Dir um einen Menschen handelt und klicke auf "Connect".
Im nächsten Fenster siehst Du zunächst viel Text beim Verbindungsaufbau, der allerdings für Dich nicht weiter von Bedeutung ist.
Anschließend öffnet sich das Chat-Fenster.
In den ersten Zeilen wird Dir Dein Name und Deine aktuelle IP-Adresse angezeigt.
Rechts im Fenster siehst Du alle Teilnehmer des Chats.
Im nächsten Fenster siehst Du zunächst viel Text beim Verbindungsaufbau, der allerdings für Dich nicht weiter von Bedeutung ist.
Anschließend öffnet sich das Chat-Fenster.
In den ersten Zeilen wird Dir Dein Name und Deine aktuelle IP-Adresse angezeigt.
Rechts im Fenster siehst Du alle Teilnehmer des Chats.
Unten hast Du ein Eingabefeld, um Beiträge zu schreiben.
Weiter Informationen zu IRC findest Du zum Beispiel auf <a href="http://wiki.ubuntuusers.de/IRC" target="_blank">ubuntuusers.de</a>, in <a href="https://de.wikipedia.org/wiki/Internet_Relay_Chat" target="_blank">Wikipedia</a> oder bei <a href="http://www.irchelp.org/" target="_blank">icrhelp.org</a> (in Englisch).
##Jappix Mini
Das Jappix Mini Plugin erlaubt das Erstellen einer Chatbox für Jabber/XMPP-Kontakte.
Das Jappix Mini Plugin erlaubt das Erstellen einer Chatbox für Jabber/XMPP-Kontakte.
Ein Jabber/XMPP Account sollte vor der Installation bereits vorhanden sein.
Die ausführliche Anleitung dazu und eine Kontrolle, ob Du nicht sogar schon über Deinen E-Mail Anbieter einen Jabber-Account hast, findest Du unter <a href="http://einfachjabber.de" target="_blank">einfachjabber.de</a>.
@ -53,29 +53,29 @@ oder als normaler Download von hier: https://github.com/friendica/friendica-addo
Entpacke diese Datei (ggf. den entpackten Ordner in „jappixmini“ umbenennen) und lade sowohl den entpackten Ordner komplett als auch die .tgz Datei in den Addon Ordner Deiner Friendica Installation hoch.
Nach dem Upload gehts in den Friendica Adminbereich und dort zu den Plugins.
Nach dem Upload gehts in den Friendica Adminbereich und dort zu den Plugins.
Aktiviere das Jappixmini Addon und gehe anschließend über die Plugins Seitenleiste (dort wo auch die Twitter-, Impressums-, GNU Social-, usw. Einstellungen gemacht werden) zu den Jappix Grundeinstellungen.
Setze hier den Haken zur Aktivierung des BOSH Proxys.
Setze hier den Haken zur Aktivierung des BOSH Proxys.
Weiter gehts in den Einstellungen Deines Friendica Accounts.
2. Einstellungen
Gehe bitte zu den Plugin-Einstellungen in Deinen Konto-Einstellungen (Account Settings).
Gehe bitte zu den Plugin-Einstellungen in Deinen Konto-Einstellungen (Account Settings).
Scrolle ein Stück hinunter bis zu den Jappix Mini Addon settings.
Aktiviere hier zuerst das Addon.
Trage nun Deinen Jabber/XMPP Namen ein, ebenfalls die entsprechende Domain bzw. den Server (ohne http, also zb einfach so: jappix.com).
Trage nun Deinen Jabber/XMPP Namen ein, ebenfalls die entsprechende Domain bzw. den Server (ohne http, also zb einfach so: jappix.com).
Um das JavaScript Applet zum Chatten im Browser verwenden zu können, benötigst du einen BOSH Proxy.
Entweder betreibst du deinen eigenen (s. Dokumentation deines XMPP Servers) oder du verwendest einen öffentlichen BOSH Proxy.
Beachte aber, dass der Betreiber dieses Proxies den kompletten Datenverkehr über den Proxy mitlesen kann.
Siehe dazu auch die „Configuration Help“ weiter unten.
Gebe danach noch Dein Passwort an, und damit ist eigentlich schon fast alles geschafft.
Die weiteren Einstellmöglichkeiten bleiben Dir überlassen, sind also optional.
Siehe dazu auch die „Configuration Help“ unter den Eingabefeldern.
Gebe danach noch Dein Passwort an, und damit ist eigentlich schon fast alles geschafft.
Die weiteren Einstellmöglichkeiten bleiben Dir überlassen, sind also optional.
Jetzt noch auf „senden“ klicken und fertig.
Deine Chatbox sollte jetzt irgendwo unten rechts im Browserfenster „kleben“.
Falls Du manuell Kontakte hinzufügen möchtest, einfach den „Add Contact“-Knopf nutzen.
Deine Chatbox sollte jetzt irgendwo unten rechts im Browserfenster „kleben“.
Falls Du manuell Kontakte hinzufügen möchtest, einfach den „Add Contact“-Knopf nutzen.
Viel Spass beim Chatten!
Viel Spass beim Chatten!

View File

@ -7,18 +7,23 @@ Hier erfährst Du, wie Du bei uns mitmachen kannst:
Zunächst erstelle Dir per 'git clone https://github.com/friendica/friendica.git' ein funktionierendes Git-Paket auf Deinem System, auf dem Du die Entwicklung durchführst, und einen eigenen Github-Account.
Erstelle Deine eigene Kopie (fork) der Ursprungsdaten auf Github, an der Du dann entspannt arbeiten kannst.
Erstelle Deine eigene Kopie (fork) der Ursprungsdaten auf Github, an der Du dann entspannt arbeiten kannst.
Deine Arbeiten sollten mit einem neuen Arbeitszweig (branch) beginnen, den du vom develop Zweig des Repositories beginnst.
Die Anleitung unter [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) erklärt Dir genau, wie Du das tun musst.
Gehe dann nach getaner Arbeit zu Deiner Github-Seite und erstelle eine "Pull request", um Deine Änderungen in das Hauptprojekt einzugliedern (merge).
Solltest du keine Idee haben, an welcher Stelle du einsteigen könntest.
Wir haben einige Aufgaben auf github mit dem Schlagwort *Junior Job* versehen.
Bei diesen Aufgaben gehen wir davon aus, dass sie geeignete Einstiegsstellen sind.
Du musst dich aber natürlich nicht mit diesen Aufgaben beschäftigen um den Friendica Code zu verbeesern.
**Wichtig**
Bitte hole Dir alle Änderungen aus dem Projektverzeichnis und führe sie mit Deiner Arbeit zusammen, **bevor** Du Deine "pull request" erstellst. Wir behalten es uns vor, Patches abzulehnen, die eine große Anzahl an Fehlern hervorrufen.
Bitte hole Dir alle Änderungen aus dem Projektverzeichnis und führe sie mit Deiner Arbeit zusammen, **bevor** Du Deine "pull request" erstellst. Wir behalten es uns vor, Patches abzulehnen, die eine große Anzahl an Fehlern hervorrufen.
Dies gilt vor allem für Übersetzungen, da wir hier möglicherweise nicht alle feinen Unterschiede in konfliktären Versionen erkennen können.
Außerdem: **teste Deine Änderungen!** Vergiss nicht, dass eine simple Fehlerlösung einen anderen Fehler auslösen kann.
Außerdem: **teste Deine Änderungen!** Vergiss nicht, dass eine simple Fehlerlösung einen anderen Fehler auslösen kann.
Lass Deine Änderungen von einem erfahrenen Friendica-Entwickler gegenprüfen.
Eine ausführliche Anleitung zu Git findest Du unter <a href="https://git-scm.com/book/de/v1" target="_blank">https://git-scm.com/book/de/v1</a>.

View File

@ -100,9 +100,9 @@ Wenn Du einen Kontakt komplett löschst, können sie Dir eine neue Freundschafts
Blockierte Kontakte können das nicht machen.
Sie können nicht mit Dir direkt kommunizieren, nur über Freunde.
Ignorierte Kontakte können weiterhin Beiträge von Dir erhalten.
Deren Beiträge werden allerdings nicht importiert. W
ie bei blockierten Beiträgen siehst Du auch hier weiterhin die Kommentare dieser Person zu anderen Beiträgen Deiner Freunde.
Ignorierte Kontakte können weiterhin Beiträge und private Nachrichten von Dir erhalten.
Deren Beiträge und private Nachrichten werden allerdings nicht importiert.
Wie bei blockierten Beiträgen siehst Du auch hier weiterhin die Kommentare dieser Person zu anderen Beiträgen Deiner Freunde.
[Ein Plugin namens "blockem" kann installiert werden, um alle Beiträge einer bestimmten Person in Deinem Stream zu verstecken bzw. zu verkürzen.
Dabei werden auch Kommentare dieser Person in Beiträgen Deiner Freunde blockiert.]

View File

@ -32,11 +32,13 @@ Friendica - Dokumentation und Ressourcen
* [Konfigurationen](help/Settings)
* [Plugins](help/Plugins)
* [Konnektoren (Connectors) installieren (Twitter/GNU Social)](help/Installing-Connectors)
* [Installation eines ejabberd Servers (XMPP-Chat) mit synchronisierten Anmeldedaten](help/install-ejabberd) (EN)
* [Nachrichtenfluss](help/Message-Flow)
* [Betreibe deine Seite mit einem SSL-Zertifikat](help/SSL)
* [Entwickler](help/Developers)
* [Twitter/GNU Social API Functions](help/api) (EN)
* [Translation of Friendica](help/translations) (EN)
* [Konfigurationswerte, die nur in der .htconfig.php gesetzt werden können](help/htconfig) (EN)
**Entwickler Dokumentation**
@ -48,6 +50,7 @@ Friendica - Dokumentation und Ressourcen
* [Plugin Development](help/Plugins)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
* [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/)
**Externe Ressourcen**
@ -58,4 +61,5 @@ Friendica - Dokumentation und Ressourcen
**Über diese Seite**
* [Seite/Friendica-Version](friendica)
* [Mitwirkenden bei Friendica](credits)

View File

@ -3,216 +3,124 @@ Friendica mit SSL nutzen
* [Zur Startseite der Hilfe](help)
Wenn du deine eigene Friendica-Seite betreibst, willst du vielleicht SSL (https) nutzen, um die Kommunikation zwischen dir und deinem Server zu verschlüsseln (die Kommunikation zwischen den Servern ist bereits verschlüsselt).
Disclaimer
---
**Dieses Dokument wurde im November 2015 aktualisiert.
SSL-Verschlüsselung ist sicherheitskritisch.
Das bedeutet, dass sich die empfohlenen Einstellungen schnell verändern.
Halte deine Installation auf dem aktuellen Stand und verlasse dich nicht darauf, dass dieses Dokument genau so schnell aktualisiert wird, wie sich Technologien verändern!**
Wenn du das auf deiner eigenen Domain machen willst, musst du ein Zertifikat von einer anerkannten Organisation beschaffen (sogenannte selbst-signierte Zertifikate, die unter Computerfreaks beliebt sind, arbeiten nicht sehr gut mit Friendica, weil sie Warnungen im Browser hervorrufen können).
Einleitung
---
Wenn du dieses Dokument liest, bevor du Friendica installierst, kannst du eine sehr einfache Option in Betracht ziehen: suche dir ein geteiltes Hosting-Angebot (shared hosting) ohne eigene Domain.
Dadurch wirst du eine Adresse in der Form deinName.deinAnbietername.de erhalten, was nicht so schön wie deinName.de ist.
Aber es wird trotzdem deine ganz persönliche Seite sein und du wirst unter Umständen die Möglichkeit haben, das SSL-Zertifikat deines Anbieters mitzubenutzen.
Das bedeutet, dass du SSL überhaupt nicht konfigurieren musst - es wird einfach sofort funktionieren, wenn die Besucher deiner Seite https statt http eingeben.
Wenn du deine eigene Friendica-Seite betreibst, willst du vielleicht SSL (https) nutzen, um die Kommunikation zwischen den Servern und zwischen dir und deinem Server zu verschlüsseln.
Wenn dir diese Lösung nicht gefällt, lies weiter...
Dafür gibt es grundsätzlich zwei Arten von SSL-Zertifikaten: Selbst-signierte Zertifikate und Zertifikate, die von einer Zertifizierungsstelle (CA) unterschrieben sind.
Technisch gesehen sorgen beide für valide Verschlüsselung.
Mit selbst-signierten Zertifikaten gibt es jedoch ein Problem:
Sie sind weder in Browsern noch auf anderen Servern installiert.
Deshalb führen sie zu Warnungen über "nicht vertrauenswürdige Zertifikate".
Das ist verwirrend und stört sehr.
**Geteilte Hosting-Angebote/Shared hosts**
Aus diesem Grund empfehlen wir, dass du dir ein von einer CA unterschriebenes Zertifikat besorgst.
Normalerweise kosten sie Geld - und sind nur für eine begrenzte Zeit gültig (z.B. ein Jahr oder zwei).
Wenn du ein geteiltes Hosting-Angebot mit einer eigenen Domain nutzt, dann wird dir dein Anbieter ggf. anbieten, dir das Zertifikat zu besorgen und zu installieren.
Du musst es nur beantragen und bezahlen und alles wird eingerichtet.
Wenn das die Lösung für dich ist, musst du das weitere Dokument nicht lesen.
Gehe nur sicher, dass das Zertifikat auch für die Domain gilt, die du für Friendica nutzt: z.B. meinfriendica.de oder friendica.meinserver.de.
Es gibt aber Möglichkeiten, ein vertrauenswürdiges Zertifikat umsonst zu bekommen.
Das Vorangehende wird die häufigste Art sein, eine Friendica-Seite zu betreiben, so dass der Rest des Artikels für die meisten Leute nicht von Bedeutung ist.
Wähle deinen Domainnamen
---
**Beschaffe dir das Zertifikat selbst**
Dein SSL-Zertifikat wird für eine bestimmte Domain gültig sein oder sogar nur für eine Subdomain.
Entscheide dich endgültig für einen Domainnamen, *bevor* du ein Zertifikat bestellst.
Wenn du das Zertifikat hast, brauchst du ein neues, wenn du den Domainnamen ändern möchtest.
Alternativ kannst du dir auch selbst ein Zertifikat besorgen und hochladen, falls dein Anbieter das unterstützt.
Gehosteter Webspace
---
Der nächste Abschnitt beschreibt den Ablauf, um ein Zertifikat von StartSSL zu erhalten.
Das Gute an StartSSL ist, dass du kostenlos ein einfaches, aber perfekt ausreichendes Zertifikat erhältst.
Das ist bei vielen anderen Anbietern nicht so, weshalb wir uns in diesem Dokument auf StartSSL konzentrieren werden.
Wenn du ein Zertifikat eines anderen Anbieters nutzen willst, musst du die Vorgaben dieser Organisation befolgen.
Wir können hier nicht jede Möglichkeit abdecken.
Wenn deine Friendica-Instanz auf einem gehosteten Webspace läuft, solltest du dich bei deinem Hosting-Provider informieren.
Dort bekommst du Instruktionen, wie es dort läuft.
Du kannst bei deinem Provider immer ein kostenpflichtiges Zertifikat bestellen.
Sie installieren es für dich oder haben in der Weboberfläche eine einfache Upload-Möglichkeit für Zertifikat und Schlüssel.
Die Installation deines erhaltenen Zertifikats hängt von den Vorgaben deines Anbieters ab.
Aber generell nutzen solche Anbieter ein einfaches Web-Tool, um die Einrichtung zu unterstützen.
Um Geld zu sparen, kann es sich lohnen, dort auch nachzufragen, ob sie ein anderes Zertifikat, das du selbst beschaffst, für dich installieren würden.
Wenn ja, dann lies weiter.
Beachte: dein Zertifikat gilt gewöhnlich nur für eine Subdomain.
Wenn du dein Zertifikat beantragst, sorge dafür, dass es für die Domain und die Subdomain gilt, die du für Friendica nutzt: z.B. meinfriendica.de oder friendica.meinserver.de.
Ein kostenloses StartSSL-Zertifikat besorgen
---
**Erhalte ein kostenloses StartSSL-Zertifikat**
StartSSL ist eine Zertifizierungsstelle, die kostenlose Zertifikate ausstellt.
Sie sind für ein Jahr gültig und genügen für unsere Zwecke.
Die Webseite von StartSSL führt dich durch den Erstellungsprozess, aber manche Leute haben hier trotzdem Probleme.
Wir empfehlen dir ausdrücklich, die Installationsanleitung Schritt für Schritt langsam und sorgfältig zu befolgen.
Lese dir jedes Wort durch und schließe deinen Browser erst, wenn alles läuft.
Es heißt, dass es drei Schritte gibt, die den Nutzer verwirren können:
### Schritt 1: Client-Zertifikat erstellen
Wenn du dich erstmals bei StartSSL anmeldest, erhältst du ein erstes Zertifikat, dass sich einfach in deinem Browser installiert.
Dieses Zertifikat solltest du zur Sicherheit irgendwo speichern, so dass du es für einen neuen Browser neu installieren kannst, wenn du z.B. etwas erneuern musst.
Dieses Authentifizierungszertifikat wird nur für das Login benötigt und hat nichts mit dem Zertifikat zu tun, dass du später für deinen Server benötigst.
Als Anfänger mit StartSSL kannst du [hier starten](https://www.startssl.com/?lang=de) und die "Express Lane" nutzen, um dein Browser-Zertifikiat zu erhalten.
Im nächsten Schritt kannst du die Einrichtung deines Zertifikats fortsetzen.
Wenn du dich erstmalig bei StartSSL anmeldest, erhältst du ein Zertifikat, das in deinem Browser installiert wird.
Du brauchst es, um dich bei StartSSL einzuloggen, auch wenn du später wiederkommst.
Dieses Client-Zertifikat hat nichts mit dem SSL-Zertifikat für deinen Server zu tun.
Wenn du zuerst nach einer Domain für dein Zertifikat gefragt wirst, musst du die Top-Level-Domain angeben, nicht die Subdomain, die Friendica nutzt.
Im nächsten Schritt kannst du dann die Subdomain spezifizieren.
Wenn du also friendica.deinName.de auf deinem Server hast, musst du zuerst deinName.de angeben.
### Schritt 2: Email-Adresse und Domain validieren
Höre nicht zu früh auf, wenn du am Ende der Einrichtung dein persönliches Server-Zertifikat erhalten hast.
Abhängig von deiner Server-Software benötigst du ein oder zwei generische Dateien, die du mit deinem kostenlosen StartSSL-Zertifikat nutzen musst.
Diese Dateien sind sub.class1.server.ca.pem und ca.pem.
Wenn du diesen Schritt bereits übersprungen hast, kannst du die Dateien hier finden: [http://www.startssl.com/?app=21](http://www.startssl.com/?app=21).
Aber am besten funktioniert es, wenn du StartSSL nicht beendest, bevor du den Vorgang komplett abgeschlossen hast und dein https-Zertifikat hochgeladen ist und funktioniert.
Um fortzufahren musst du beweisen, dass du die Email-Adresse, die du angegeben hast, und die Domain, für die du das Zertifikat möchtest, besitzt.
Gehe in den "Validation wizard" und fordere einen Bestätigungslink per Mail an.
Dasselbe machst du auch für die Validierung der Domain.
**Virtuelle private und dedizierte Server (mit StartSSL free)**
### Schritt 3: Das Zertifikat bestellen
Der Rest dieses Dokuments ist etwas komplizierter, aber es ist auch nur für Personen, die Friendica auf einem virtuellen oder dedizierten Server nutzen.
Jeder andere kann an dieser Stelle mit dem Lesen aufhören.
Gehe in den "Certificate wizard".
Wähle das Target Webserver.
Bei der ersten Abfrage der Domain gibst du deine Hauptdomain an.
Im nächsten Schritt kannst du eine Subdomain hinzufügen.
Ein Beispiel: Wenn die Adresse der Friendica-Instanz friendica.beispiel.net lautet, gibst du zuerst beispiel.net an und danach friendica.
Folge den weiteren Anleitungen [hier](http://www.startssl.com/?app=20), um den Webserver, den du benutzt (z.B. Apache), für dein Zertifikat einzurichten.
Wenn du weißt, wie man einen openssl-Schlüssel und einen Certificate Signing Request (CSR) erstellt, tu das.
Kopiere den CSR in den Browser, um ihn von StartSSL signiert zu bekommen.
Um die nötigen Schritte zu verdeutlichen, setzen wir nun voraus, dass Apache aktiv ist.
Im Wesentlichen kannst du einfach einen zweiten httpd.conf-Eintrag für Friendica erstellen.
Wenn du nicht weißt, wie man Schlüssel und CSR erzeugt, nimm das Angebot von StartSSL an, beides für dich zu generieren.
Das bedeutet: StartSSL hat den Schlüssel zu deiner SSL-Verschlüsselung, aber das ist immer noch besser als gar kein Zertifikat.
Lade dein Zertifikat von der Website herunter.
(Oder im zweiten Fall: Lade Zertifikat und Schlüssel herunter.)
Um das zu machen, kopiere den existierenden Eintrag und ändere das Ende der ersten Zeile auf "lesen" :443> anstelle von :80> und trage dann die folgenden Zeilen ein, wie du es auch in der Anleitung von StartSSL finden kannst:
Um dein Zertifikat auf einem Webserver zu installieren, brauchst du noch ein oder zwei andere Dateien: sub.class1.server.ca.pem und ca.pem, auch von StartSSL.
Gehe in die Rubrik "Tool box" und lade "Class 1 Intermediate Server CA" und "StartCom Root CA (PEM encoded)" herunter.
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM
Wenn du dein Zertifikat zu deinem Hosting-Provider schicken möchtest, brauchen Sie mindestens Zertifikat und Schlüssel.
Schick zur Sicherheit alle vier Dateien hin.
**Du solltest sie auf einem verschlüsselten Weg hinschicken!**
SSLCertificateFile /usr/local/apache/conf/ssl.crt
SSLCertificateKeyFile /usr/local/apache/conf/ssl.key
SSLCertificateChainFile /usr/local/apache/conf/sub.class1.server.ca.pem
SSLCACertificateFile /usr/local/apache/conf/ca.pem
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
CustomLog /usr/local/apache/logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
Wenn du deinen eigenen Server betreibst, lade die Dateien hoch und besuche das Mozilla-Wiki (Link unten).
(Beachte, dass das Verzeichnis /usr/local/apache/conf/ möglicherweise nicht in deinem System existiert.
In Debian ist der Pfad bspw. /etc/apache2/, in dem du ein SSL-Unterverzeichnis erstellen kannst, wenn dieses noch nicht vorhanden ist.
Dann hast du /etc/apache2/ssl/… statt /usr/local/apache/conf/…)
Let's encrypt
---
Du solltest nun zwei Einträgen für deine Friendica-Seite haben - einen für einfaches http und eines für https.
Wenn du einen eigenen Server betreibst und den Nameserver kontrollierst, könnte auch die Initiative "Let's encrypt" interessant für dich werden.
Momentan ist deren Angebot noch nicht fertig.
Auf der [Website](https://letsencrypt.org/) kannst du dich über den Stand informieren.
Ein Hinweis für diejenigen, die SSL steuern wollen: setze keine Weiterleitung deines SSL in deine Apache-Einstellung. Friendicas Admin-Panel hat eine spezielle Einstellung für die SSL-Methode.
Bitte nutze diese Einstellungen.
Webserver-Einstellungen
---
**Vermische Zertifikate in Apache StartSSL und andere (selbst-signierte)**
Im [Wiki von Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS) gibt es Anleitungen für die Konfiguration sicherer Webserver.
Dort findest du Empfehlungen, die auf [verschiedene Webserver](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations) zugeschnitten sind.
Viele Leute nutzen einen virtuellen privaten oder einen dedizierten Server, um mehr als Friendica darauf laufen zu lassen.
Sie wollen möglicherweise SSL auch für andere Seiten nutzen, die auf dem Server liegen.
Um das zu erreichen, wollen sie mehrere Zertifikate für eine IP nutzen, z.B. ein Zertifikat eines anerkannten Anbieters für Friendica und ein selbst-signiertes für eine persönliche Inhalte (möglw. ein Wildcard-Zertifikat für mehrere Subdomains).
Teste deine SSL-Einstellungen
---
Um das zum Laufen zu bringen, bietet Apache eine NameVirtualHost-Direktive.
Du findest Informationen zur Nutzung in httpd.conf in den folgenden Ausschnitten.
Beachte, dass Wildcards (*) in httpd.conf dazu führen, dass die NameVirtualHost-Methode nicht funktioniert; du kannst diese in dieser neuen Konfiguration nicht nutzen.
Das bedeutet, dass *80> oder *443> nicht funktionieren.
Und du musst unbedingt die IP definieren, selbst wenn du nur eine hast.
Beachte außerdem, dass du bald zwei Zeilen zu Beginn der Datei hinzufügen musst, um NameVirtualHost für IPv6 vorzubereiten.
Wenn du fertig bist, kannst du auf der Testseite [SSL-Labs](https://www.ssllabs.com/ssltest/) prüfen lassen, ob Du alles richtig gemacht hast.
NameVirtualHost 12.123.456.1:443
NameVirtualHost 12.123.456.1:80
<VirtualHost www.anywhere.net:80>
DocumentRoot /var/www/anywhere
Servername www.anywhere.net
</VirtualHost>
<VirtualHost www.anywhere.net:443>
DocumentRoot /var/www/anywhere
Servername www.anywhere.net
SSLEngine On
<pointers to a an eligible cert>
<more ssl stuff >
<other stuff>
</VirtualHost>
<VirtualHost www.somewhere-else.net:80>
DocumentRoot /var/www/somewhere-else
Servername www.somewhere-else.net
</VirtualHost>
<VirtualHost www.somewhere-else:443>
DocumentRoot /var/www/somewhere-else
Servername www.somewhere-else.net
SSLEngine On
<pointers to another eligible cert>
<more ssl stuff >
<other stuff>
</VirtualHost>
Natürlich kannst du auch andere Verzeichnisse auf deinem Server nutzen, um Apache zu konfigurieren.
In diesem Fall müssen nur einige Zeilen in httpd.conf oder ports.conf angepasst werden - vor allem die NameVirtualHost-Zeilen.
Aber wenn du sicher im Umgang mit solchen Alternativen bist, wirst du sicherlich die nötigen Anpassungen herausfinden.
Starte dein Apache abschließend neu.
**StartSSL auf Nginx**
Führe zunächst ein Update auf den neuesten Friendica-Code durch.
Folge dann der Anleitung oben, um dein kostenloses Zertifikat zu erhalten.
Aber statt der Apache-Installationsanleitung zu folgen, mache das Folgende:
Lade dein Zertifikat hoch.
Es ist nicht wichtig, wohin du es lädst, solange Nginx es finden kann.
Einige Leute nutzen /home/verschiedeneNummernundBuchstaben, du kannst aber auch z.B. etwas wie /foo/bar nutzen.
Du kannst das Passwort entfernen, wenn du willst.
Es ist zwar möglicherweise nicht die beste Wahl, aber wenn du es nicht machst, wirst du das Passwort immer wieder eingeben müssen, wenn du Ngingx neustartest.
Um es zu entfernen, gebe Folgendes ein:
openssl rsa -in ssl.key-pass -out ssl.key
Nun hole dir das Hifs-Zertifikat:
wget http://www.startssl.com/certs/sub.class1.server.ca.pem
Nun vereinige die Dateien:
cat ssl.crt sub.class1.server.ca.pem > ssl.crt
In manchen Konfigurationen ist ein Bug enthalten, weshalb diese Schritte nicht ordentlich arbeiten.
Du musst daher ggf. ssl.crt bearbeiten:
nano /foo/bar/ssl.crt
Du wirst zwei Zertifikate in der gleichen Date sehen. In der Mitte findest du:
-----END CERTIFICATE----------BEGIN CERTIFICATE-----
Das ist schlecht. Du brauchst die folgenden Einträge:
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Du kannst den Zeilenumbruch manuell eingeben, falls dein System vom Bug betroffen ist.
Beachte, dass nach -----BEGIN CERTIFICATE----- nur ein Zeilenumbruch ist.
Es gibt keine leere Zeile zwischen beiden Einträgen.
Nun musst du Nginx über die Zertifikate informieren.
In /etc/nginx/sites-available/foo.com.conf benötigst du etwas wie:
server {
listen 80;
listen 443 ssl;
listen [::]:80;
listen [::]:443 ipv6only=on ssl;
ssl_certificate /foo/bar/ssl.crt;
ssl_certificate_key /foo/bar/ssl.key;
...
Nun starte Nginx neu:
/etc/init.d/nginx restart
Und das war es schon.
Für multiple Domains ist es mit Nginx einfacher als mit Apache.
Du musst du oben genannten Schritte nur für jedes Zertifikat wiederholen und die spezifischen Informationen im eigenen {server...}-Bereich spezifizieren.

View File

@ -53,9 +53,21 @@ In the descirption and location field you can use BBCode to format the text.
When you *Share* the event it will be posted to your wall with the access permissions you've selected.
But before you do, you can also *preview* the event in a pop-up box.
### Interaction with Events
When you publish an event, you can choose who shall receive it, as with a regular new posting.
The recipients will see the posting about the event in their network-stream.
Additionally it will be added to their calendar and thus be shown in their events overview page.
Recipients of the event-posting can comment or dis-/like the event, as with a regular posting, but also announce that they will attend, not attend or may-be attend the event with a single click.
### Addons
#### OpenStreetMap
If this addon is activated on you friendica node, the content of the location field will be mathced with the identification service of OSM when you submit the event.
Should OSM find anything matching, a map for the location will be embedded automatically at the end of the events view.
#### Calendar Export
If this addon is activated the public events you have created will be published in ical or csv file. The URL of the published file is ``example.com/cal/nickname/export/format`` (where format is either ical of csv).

100
doc/htconfig.md Normal file
View File

@ -0,0 +1,100 @@
Config values that can only be set in .htconfig.php
===================================================
There are some config values that haven't found their way into the administration page. This has several reasons. Maybe they are part of a
current development that isn't considered stable and will be added later in the administration page when it is considered safe. Or it triggers
something that isn't expected to be of public interest. Or it is for testing purposes only.
**Attention:** Please be warned that you shouldn't use one of these values without the knowledge what it could trigger. Especially don't do that with
undocumented values.
The header of the section describes the category, the value is the parameter. Example: To set the directory value please add this
line to your .htconfig.php:
$a->config['system']['directory'] = 'http://dir.friendi.ca';
## Jabber ##
* debug (Boolean) - Enable debug level for the jabber account synchronisation.
* logfile - Logfile for the jabber account synchronisation.
## System ##
* birthday_input_format - Default value is "ymd".
* block_local_dir (Boolean) - Blocks the access to the directory of the local users.
* default_service_class -
* delivery_batch_count - Number of deliveries per process. Default value is 1. (Disabled when using the worker)
* diaspora_test (Boolean) - For development only. Disables the message transfer.
* directory - The path to global directory. If not set then "http://dir.friendi.ca" is used.
* disable_email_validation (Boolean) - Disables the check if a mail address is in a valid format and can be resolved via DNS.
* disable_url_validation (Boolean) - Disables the DNS lookup of an URL.
* event_input_format - Default value is "ymd".
* ignore_cache (Boolean) - For development only. Disables the item cache.
* like_no_comment (Boolean) - Don't update the "commented" value of an item when it is liked.
* local_block (Boolean) - Used in conjunction with "block_public".
* local_search (Boolean) - Blocks the search for not logged in users to prevent crawlers from blocking your system.
* max_contact_queue - Default value is 500.
* max_batch_queue - Default value is 1000.
* 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.
* no_view_full_size (Boolean) - Don't add the link "View full size" under a resized image.
* optimize_items (Boolean) - Triggers an SQL command to optimize the item table before expiring items.
* ostatus_poll_timeframe - Defines how old an item can be to try to complete the conversation with it.
* paranoia (Boolean) - Log out users if their IP address changed.
* permit_crawling (Boolean) - Restricts the search for not logged in users to one search per minute.
* free_crawls - Number of "free" searches when "permit_crawling" is activated (Default value is 10)
* crawl_permit_period - Period in seconds between allowed searches when the number of free searches is reached and "permit_crawling" is activated (Default value is 60)
* png_quality - Default value is 8.
* proc_windows (Boolean) - Should be enabled if Friendica is running under Windows.
* proxy_cache_time - Time after which the cache is cleared. Default value is one day.
* pushpoll_frequency -
* qsearch_limit - Default value is 100.
* relay_server - Experimental Diaspora feature. Address of the relay server where public posts should be send to. For example https://podrelay.net
* relay_subscribe (Boolean) - Enables the receiving of public posts from the relay. They will be included in the search and on the community page when it is set up to show all public items.
* relay_scope - Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts witt selected tags should be received.
* relay_server_tags - Comma separated list of tags for the "tags" subscription (see "relay_scrope")
* relay_user_tags (Boolean) - If enabled, the tags from the saved searches will used for the "tags" subscription in addition to the "relay_server_tags".
* remove_multiplicated_lines (Boolean) - If enabled, multiple linefeeds in items are stripped to a single one.
* show_unsupported_addons (Boolean) - Show all addons including the unsupported ones.
* show_unsupported_themes (Boolean) - Show all themes including the unsupported ones.
* throttle_limit_day - Maximum number of posts that a user can send per day with the API.
* throttle_limit_week - Maximum number of posts that a user can send per week with the API.
* throttle_limit_month - Maximum number of posts that a user can send per month with the API.
* wall-to-wall_share (Boolean) - Displays forwarded posts like "wall-to-wall" posts.
* worker (Boolean) - (Experimental) Use the worker system instead of calling several background processes. Reduces the overall load and speeds up item delivery.
* worker_dont_fork (Boolean) - if enabled, the workers are only called from the poller process. Useful on systems that permit the use of "proc_open".
* worker_queues - Number of parallel workers. Default value is 10 queues.
* xrd_timeout - Timeout for fetching the XRD links. Default value is 20 seconds.
## service_class ##
* upgrade_link -
## experimentals ##
* exp_themes (Boolean) - Show experimental themes as well.
## theme ##
* hide_eventlist (Boolean) - Don't show the birthdays and events on the profile and network page
# Administrator Options #
Enabling the admin panel for an account, and thus making the account holder
admin of the node, is done by setting the variable
$a->config['admin_email'] = "someone@example.com";
where you have to match the email address used for the account with the one you
enter to the .htconfig file. If more then one account should be able to access
the admin panel, seperate the email addresses with a comma.
$a->config['admin_email'] = "someone@example.com,someonelese@example.com";
If you want to have a more personalized closing line for the notification
emails you can set a variable for the admin_name.
$a->config['admin_name'] = "Marvin";

16
doc/html/index.php Normal file
View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>$Projectname Doxygen API Documentation</title>
</head>
<body>
<h1>$Projectname Doxygen API Documentation not rendered</h1>
To get the Doxygen API Documentation you must render it with the program <a href="http://www.doxygen.org">Doxygen</a> (included in most distributions).
<pre>
$ doxygen util/Doxyfile
</pre>
<br>
<a href="javascript:history.back()">back</a>
</body>
</html>

45
doc/install-ejabberd.md Normal file
View File

@ -0,0 +1,45 @@
Install an ejabberd with synchronized credentials
=================================================
* [Home](help)
[Ejabberd](https://www.ejabberd.im/) is a chat server that uses XMPP as messaging protocol that you can use with a large amount of clients. In conjunction
with the "xmpp" addon it can be used for a web based chat solution for your users.
Installation
------------
- Change it's owner to whichever user is running the server, ie. ejabberd
$ chown ejabberd:ejabberd /path/to/friendica/include/auth_ejabberd.php
- Change the access mode so it is readable only to the user ejabberd and has exec
$ chmod 700 /path/to/friendica/include/auth_ejabberd.php
- Edit your ejabberd.cfg file, comment out your auth_method and add:
{auth_method, external}.
{extauth_program, "/path/to/friendica/include/auth_ejabberd.php"}.
- Disable the module "mod_register" and disable the registration:
{access, register, [{deny, all}]}.
- Enable BOSH:
- Enable the module "mod_http_bind"
- Edit this line:
{5280, ejabberd_http, [captcha, http_poll, http_bind]}
- In your apache configuration for your site add this line:
ProxyPass /http-bind http://127.0.0.1:5280/http-bind retry=0
- Restart your ejabberd service, you should be able to login with your friendica credentials
Other hints
-----------
- if a user has a space or a @ in the nickname, the user has to replace these characters:
- " " (space) is replaced with "%20"
- "@" is replaced with "(a)"

View File

@ -30,6 +30,7 @@ Friendica Documentation and Resources
* [Settings](help/Settings)
* [Plugins](help/Plugins)
* [Installing Connectors (Twitter/GNU Social)](help/Installing-Connectors)
* [Install an ejabberd server (XMPP chat) with synchronized credentials](help/install-ejabberd)
* [Message Flow](help/Message-Flow)
* [Using SSL with Friendica](help/SSL)
* [Developers](help/Developers)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -144,7 +144,7 @@ function terminate_friendship($user,$self,$contact) {
// and we won't waste any more time trying to communicate with them.
// This provides for the possibility that their database is temporarily messed
// up or some other transient event and that there's a possibility we could recover from it.
if(! function_exists('mark_for_death')) {
function mark_for_death($contact) {
@ -166,7 +166,7 @@ function mark_for_death($contact) {
$expiry = $contact['term-date'] . ' + 32 days ';
if(datetime_convert() > datetime_convert('UTC','UTC',$expiry)) {
// relationship is really truly dead.
// relationship is really truly dead.
// archive them rather than delete
// though if the owner tries to unarchive them we'll start the whole process over again
@ -191,8 +191,90 @@ function unmark_for_death($contact) {
);
}}
function get_contact_details_by_url($url, $uid = -1) {
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"]);
} else {
$r = q("SELECT `url`, `name`, `nick`, `avatar` AS `photo`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'",
dbesc(normalise_link($url)));
if (count($r)) {
$profile = $r[0];
$profile["keywords"] = "";
$profile["gender"] = "";
$profile["community"] = false;
$profile["network"] = "";
$profile["addr"] = "";
}
}
// Fetching further contact data from the contact table
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `addr`, `forum`, `prv`, `bd` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` = '%s'",
dbesc(normalise_link($url)), intval($uid), dbesc($profile["network"]));
if (!count($r))
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `addr`, `forum`, `prv`, `bd` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
dbesc(normalise_link($url)), intval($uid));
if (!count($r))
$r = q("SELECT `id`, `uid`, `url`, `network`, `name`, `nick`, `addr`, `location`, `about`, `keywords`, `gender`, `photo`, `addr`, `forum`, `prv`, `bd` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
dbesc(normalise_link($url)));
if ($r) {
if (isset($r[0]["url"]) AND $r[0]["url"])
$profile["url"] = $r[0]["url"];
if (isset($r[0]["name"]) AND $r[0]["name"])
$profile["name"] = $r[0]["name"];
if (isset($r[0]["nick"]) AND $r[0]["nick"] AND ($profile["nick"] == ""))
$profile["nick"] = $r[0]["nick"];
if (isset($r[0]["addr"]) AND $r[0]["addr"] AND ($profile["addr"] == ""))
$profile["addr"] = $r[0]["addr"];
if (isset($r[0]["photo"]) AND $r[0]["photo"])
$profile["photo"] = $r[0]["photo"];
if (isset($r[0]["location"]) AND $r[0]["location"])
$profile["location"] = $r[0]["location"];
if (isset($r[0]["about"]) AND $r[0]["about"])
$profile["about"] = $r[0]["about"];
if (isset($r[0]["keywords"]) AND $r[0]["keywords"])
$profile["keywords"] = $r[0]["keywords"];
if (isset($r[0]["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($r[0]["network"]) AND $r[0]["network"])
$profile["network"] = $r[0]["network"];
if (isset($r[0]["addr"]) AND $r[0]["addr"])
$profile["addr"] = $r[0]["addr"];
if (isset($r[0]["bd"]) AND $r[0]["bd"])
$profile["bd"] = $r[0]["bd"];
if ($r[0]["uid"] == 0)
$profile["cid"] = 0;
else
$profile["cid"] = $r[0]["id"];
} else
$profile["cid"] = 0;
if (($profile["cid"] == 0) AND ($profile["network"] == NETWORK_DIASPORA)) {
$profile["location"] = "";
$profile["about"] = "";
}
return($profile);
}
if(! function_exists('contact_photo_menu')){
function contact_photo_menu($contact) {
function contact_photo_menu($contact, $uid = 0) {
$a = get_app();
@ -204,6 +286,33 @@ function contact_photo_menu($contact) {
$contact_drop_link = "";
$poke_link="";
if ($uid == 0)
$uid = local_user();
if ($contact["uid"] != $uid) {
if ($uid == 0) {
$profile_link = zrl($contact['url']);
$menu = Array('profile' => array(t("View Profile"), $profile_link, true));
return $menu;
}
$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `network` = '%s' AND `uid` = %d",
dbesc($contact["nurl"]), dbesc($contact["network"]), intval($uid));
if ($r)
return contact_photo_menu($r[0], $uid);
else {
$profile_link = zrl($contact['url']);
$connlnk = 'follow/?url='.$contact['url'];
$menu = Array(
'profile' => array(t("View Profile"), $profile_link, true),
'follow' => array(t("Connect/Follow"), $connlnk, true)
);
return $menu;
}
}
$sparkle = false;
if($contact['network'] === NETWORK_DFRN) {
$sparkle = true;
@ -219,24 +328,32 @@ function contact_photo_menu($contact) {
$status_link = $profile_link . "?url=status";
$photos_link = $profile_link . "?url=photos";
$profile_link = $profile_link . "?url=profile";
$pm_url = $a->get_baseurl() . '/message/new/' . $contact['id'];
}
$poke_link = $a->get_baseurl() . '/poke/?f=&c=' . $contact['id'];
if (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA)))
$pm_url = $a->get_baseurl() . '/message/new/' . $contact['id'];
if ($contact["network"] == NETWORK_DFRN)
$poke_link = $a->get_baseurl() . '/poke/?f=&c=' . $contact['id'];
$contact_url = $a->get_baseurl() . '/contacts/' . $contact['id'];
$posts_link = $a->get_baseurl() . '/network/0?nets=all&cid=' . $contact['id'];
$posts_link = $a->get_baseurl() . "/contacts/" . $contact['id'] . '/posts';
$contact_drop_link = $a->get_baseurl() . "/contacts/" . $contact['id'] . '/drop?confirm=1';
/**
* menu array:
* "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ]
*/
$menu = Array(
'poke' => array(t("Poke"), $poke_link),
'status' => array(t("View Status"), $status_link),
'profile' => array(t("View Profile"), $profile_link),
'photos' => array(t("View Photos"), $photos_link),
'network' => array(t("Network Posts"), $posts_link),
'edit' => array(t("Edit Contact"), $contact_url),
'drop' => array(t("Drop Contact"), $contact_drop_link),
'pm' => array(t("Send PM"), $pm_url),
'status' => array(t("View Status"), $status_link, true),
'profile' => array(t("View Profile"), $profile_link, true),
'photos' => array(t("View Photos"), $photos_link,true),
'network' => array(t("Network Posts"), $posts_link,false),
'edit' => array(t("Edit Contact"), $contact_url, false),
'drop' => array(t("Drop Contact"), $contact_drop_link, false),
'pm' => array(t("Send PM"), $pm_url, false),
'poke' => array(t("Poke"), $poke_link, false),
);
@ -244,25 +361,13 @@ function contact_photo_menu($contact) {
call_hooks('contact_photo_menu', $args);
/* $o = "";
foreach($menu as $k=>$v){
if ($v!="") {
if(($k !== t("Network Posts")) && ($k !== t("Send PM")) && ($k !== t('Edit Contact')))
$o .= "<li><a target=\"redir\" href=\"$v\">$k</a></li>\n";
else
$o .= "<li><a href=\"$v\">$k</a></li>\n";
}
}
return $o;*/
foreach($menu as $k=>$v){
if ($v[1]!="") {
if(($v[0] !== t("Network Posts")) && ($v[0] !== t("Send PM")) && ($v[0] !== t('Edit Contact')))
$menu[$k][2] = 1;
else
$menu[$k][2] = 0;
}
}
return $menu;
$menucondensed = array();
foreach ($menu AS $menuname=>$menuitem)
if ($menuitem[1] != "")
$menucondensed[$menuname] = $menuitem;
return $menucondensed;
}}

View File

@ -345,38 +345,37 @@ class Photo {
}
public function orient($filename) {
if ($this->is_imagick()) {
// based off comment on http://php.net/manual/en/imagick.getimageorientation.php
$orientation = $this->image->getImageOrientation();
switch ($orientation) {
case imagick::ORIENTATION_BOTTOMRIGHT:
$this->image->rotateimage("#000", 180);
break;
case imagick::ORIENTATION_RIGHTTOP:
$this->image->rotateimage("#000", 90);
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$this->image->rotateimage("#000", -90);
break;
}
if ($this->is_imagick()) {
// based off comment on http://php.net/manual/en/imagick.getimageorientation.php
$orientation = $this->image->getImageOrientation();
switch ($orientation) {
case imagick::ORIENTATION_BOTTOMRIGHT:
$this->image->rotateimage("#000", 180);
break;
case imagick::ORIENTATION_RIGHTTOP:
$this->image->rotateimage("#000", 90);
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$this->image->rotateimage("#000", -90);
break;
}
$this->image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
return TRUE;
}
$this->image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
return TRUE;
}
// based off comment on http://php.net/manual/en/function.imagerotate.php
if(!$this->is_valid())
return FALSE;
return FALSE;
if( (! function_exists('exif_read_data')) || ($this->getType() !== 'image/jpeg') )
return;
return;
$exif = @exif_read_data($filename);
$exif = @exif_read_data($filename,null,true);
if(! $exif)
return;
if(! $exif)
return;
$ort = $exif['Orientation'];
$ort = $exif['IFD0']['Orientation'];
switch($ort)
{
@ -413,6 +412,10 @@ class Photo {
$this->rotate(90);
break;
}
// logger('exif: ' . print_r($exif,true));
return $exif;
}

View File

@ -4,7 +4,7 @@ require_once('library/HTML5/Parser.php');
require_once('include/crypto.php');
if(! function_exists('scrape_dfrn')) {
function scrape_dfrn($url) {
function scrape_dfrn($url, $dont_probe = false) {
$a = get_app();
@ -17,6 +17,13 @@ function scrape_dfrn($url) {
if(! $s)
return $ret;
if (!$dont_probe) {
$probe = probe_url($url);
if (isset($probe["addr"]))
$ret["addr"] = $probe["addr"];
}
$headers = $a->get_curl_headers();
logger('scrape_dfrn: headers=' . $headers, LOGGER_DEBUG);
@ -320,7 +327,7 @@ function scrape_feed($url) {
* PROBE_DIASPORA has a bias towards returning Diaspora information
* while PROBE_NORMAL has a bias towards dfrn/zot - in the case where
* an address (such as a Friendica address) supports more than one type
* of network.
* of network.
*
*/
@ -407,7 +414,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
$pubkey = $diaspora_key;
$diaspora = true;
}
if($link['@attributes']['rel'] === 'http://ostatus.org/schema/1.0/subscribe') {
if(($link['@attributes']['rel'] === 'http://ostatus.org/schema/1.0/subscribe') AND ($mode == PROBE_NORMAL)) {
$diaspora = false;
}
}
@ -524,7 +531,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if(strlen($dfrn)) {
$ret = scrape_dfrn(($hcard) ? $hcard : $dfrn);
$ret = scrape_dfrn(($hcard) ? $hcard : $dfrn, true);
if(is_array($ret) && x($ret,'dfrn-request')) {
$network = NETWORK_DFRN;
$request = $ret['dfrn-request'];
@ -552,7 +559,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
if($network !== NETWORK_ZOT && $network !== NETWORK_DFRN && $network !== NETWORK_MAIL) {
if($diaspora)
$network = NETWORK_DIASPORA;
elseif($has_lrdd)
elseif($has_lrdd AND ($notify))
$network = NETWORK_OSTATUS;
if(strpos($url,'@'))
@ -652,9 +659,10 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
$feed->set_raw_data(($xml) ? $xml : '<?xml version="1.0" encoding="utf-8" ?><xml></xml>');
$feed->init();
if($feed->error())
if($feed->error()) {
logger('probe_url: scrape_feed: Error parsing XML: ' . $feed->error());
$network = NETWORK_PHANTOM;
}
if(! x($vcard,'photo'))
$vcard['photo'] = $feed->get_image_url();
@ -718,6 +726,45 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
}
}
// Workaround for misconfigured Friendica servers
if (($network == "") AND (strstr($url, "/profile/"))) {
$noscrape = str_replace("/profile/", "/noscrape/", $url);
$noscrapejson = fetch_url($noscrape);
if ($noscrapejson) {
$network = NETWORK_DFRN;
$poco = str_replace("/profile/", "/poco/", $url);
$noscrapedata = json_decode($noscrapejson, true);
if (isset($noscrapedata["addr"]))
$addr = $noscrapedata["addr"];
if (isset($noscrapedata["fn"]))
$vcard["fn"] = $noscrapedata["fn"];
if (isset($noscrapedata["key"]))
$pubkey = $noscrapedata["key"];
if (isset($noscrapedata["photo"]))
$vcard["photo"] = $noscrapedata["photo"];
if (isset($noscrapedata["dfrn-request"]))
$request = $noscrapedata["dfrn-request"];
if (isset($noscrapedata["dfrn-confirm"]))
$confirm = $noscrapedata["dfrn-confirm"];
if (isset($noscrapedata["dfrn-notify"]))
$notify = $noscrapedata["dfrn-notify"];
if (isset($noscrapedata["dfrn-poll"]))
$poll = $noscrapedata["dfrn-poll"];
}
}
if((! $vcard['photo']) && strlen($email))
$vcard['photo'] = avatar_img($email);
if($poll === $profile)
@ -778,6 +825,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
$baseurl = rtrim($baseurl, "/");
if(strpos($url,'@') AND ($addr == "") AND ($network == NETWORK_DFRN))
$addr = str_replace('acct:', '', $url);
$vcard['fn'] = notags($vcard['fn']);
$vcard['nick'] = str_replace(' ','',notags($vcard['nick']));
@ -820,7 +870,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
}
// Only store into the cache if the value seems to be valid
if ($result['network'] != NETWORK_FEED)
if ($result['network'] != NETWORK_PHANTOM)
Cache::set("probe_url:".$mode.":".$url,serialize($result), CACHE_DAY);
return $result;

View File

@ -1,6 +1,7 @@
<?php
require_once("include/contact_selectors.php");
require_once("include/contact_widgets.php");
require_once("include/features.php");
require_once("mod/proxy.php");
@ -392,7 +393,6 @@ 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']:"");
@ -426,6 +426,8 @@ function acl_lookup(&$a, $out_type = 'json') {
$group_count = 0;
}
$sql_extra2 .= " ".unavailable_networks();
if ($type=='' || $type=='c'){
$r = q("SELECT COUNT(*) AS c FROM `contact`
WHERE `uid` = %d AND `self` = 0
@ -492,7 +494,7 @@ function acl_lookup(&$a, $out_type = 'json') {
$groups[] = array(
"type" => "g",
"photo" => "images/twopeople.png",
"name" => $g['name'],
"name" => htmlentities($g['name']),
"id" => intval($g['id']),
"uids" => array_map("intval", explode(",",$g['uids'])),
"link" => '',
@ -545,9 +547,9 @@ function acl_lookup(&$a, $out_type = 'json') {
$x['data'] = array();
if(count($r)) {
foreach($r as $g) {
$x['photos'][] = proxy_url($g['micro']);
$x['photos'][] = proxy_url($g['micro'], false, PROXY_SIZE_MICRO);
$x['links'][] = $g['url'];
$x['suggestions'][] = $g['name'];
$x['suggestions'][] = htmlentities($g['name']);
$x['data'][] = intval($g['id']);
}
}
@ -559,12 +561,12 @@ function acl_lookup(&$a, $out_type = 'json') {
foreach($r as $g){
$contacts[] = array(
"type" => "c",
"photo" => proxy_url($g['micro']),
"name" => $g['name'],
"photo" => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
"name" => htmlentities($g['name']),
"id" => intval($g['id']),
"network" => $g['network'],
"link" => $g['url'],
"nick" => ($g['attag']) ? $g['attag'] : $g['nick'],
"nick" => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
"forum" => $g['forum']
);
}
@ -604,12 +606,12 @@ function acl_lookup(&$a, $out_type = 'json') {
// /nickname
$unknow_contacts[] = array(
"type" => "c",
"photo" => proxy_url($row['author-avatar']),
"name" => $row['author-name'],
"photo" => proxy_url($row['author-avatar'], false, PROXY_SIZE_MICRO),
"name" => htmlentities($row['author-name']),
"id" => '',
"network" => "unknown",
"link" => $row['author-link'],
"nick" => $nick,
"nick" => htmlentities($nick),
"forum" => false
);
}

View File

@ -285,7 +285,7 @@
* Unique contact to contact url.
*/
function api_unique_id_to_url($id){
$r = q("SELECT url FROM unique_contacts WHERE id=%d LIMIT 1",
$r = q("SELECT `url` FROM `unique_contacts` WHERE `id`=%d LIMIT 1",
intval($id));
if ($r)
return ($r[0]["url"]);
@ -390,9 +390,9 @@
$r = array();
if ($url != "")
$r = q("SELECT * FROM unique_contacts WHERE url='%s' LIMIT 1", $url);
$r = q("SELECT * FROM `unique_contacts` WHERE `url`='%s' LIMIT 1", $url);
elseif ($nick != "")
$r = q("SELECT * FROM unique_contacts WHERE nick='%s' LIMIT 1", $nick);
$r = q("SELECT * FROM `unique_contacts` WHERE `nick`='%s' LIMIT 1", $nick);
if ($r) {
// If no nick where given, extract it from the address
@ -505,14 +505,14 @@
}
// Fetching unique id
$r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($uinfo[0]['url'])));
$r = q("SELECT id FROM `unique_contacts` WHERE `url`='%s' LIMIT 1", dbesc(normalise_link($uinfo[0]['url'])));
// If not there, then add it
if (count($r) == 0) {
q("INSERT INTO unique_contacts (url, name, nick, avatar) VALUES ('%s', '%s', '%s', '%s')",
q("INSERT INTO `unique_contacts` (`url`, `name`, `nick`, `avatar`) VALUES ('%s', '%s', '%s', '%s')",
dbesc(normalise_link($uinfo[0]['url'])), dbesc($uinfo[0]['name']),dbesc($uinfo[0]['nick']), dbesc($uinfo[0]['micro']));
$r = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1", dbesc(normalise_link($uinfo[0]['url'])));
$r = q("SELECT `id` FROM `unique_contacts` WHERE `url`='%s' LIMIT 1", dbesc(normalise_link($uinfo[0]['url'])));
}
$network_name = network_to_name($uinfo[0]['network'], $uinfo[0]['url']);
@ -539,7 +539,8 @@
'verified' => true,
'statusnet_blocking' => false,
'notifications' => false,
'statusnet_profile_url' => $a->get_baseurl()."/contacts/".$uinfo[0]['cid'],
//'statusnet_profile_url' => $a->get_baseurl()."/contacts/".$uinfo[0]['cid'],
'statusnet_profile_url' => $uinfo[0]['url'],
'uid' => intval($uinfo[0]['uid']),
'cid' => intval($uinfo[0]['cid']),
'self' => $uinfo[0]['self'],
@ -552,32 +553,44 @@
function api_item_get_user(&$a, $item) {
$author = q("SELECT * FROM unique_contacts WHERE url='%s' LIMIT 1",
$author = q("SELECT * FROM `unique_contacts` WHERE `url`='%s' LIMIT 1",
dbesc(normalise_link($item['author-link'])));
if (count($author) == 0) {
q("INSERT INTO unique_contacts (url, name, avatar) VALUES ('%s', '%s', '%s')",
dbesc(normalise_link($item["author-link"])), dbesc($item["author-name"]), dbesc($item["author-avatar"]));
q("INSERT INTO `unique_contacts` (`url`, `name`, `avatar`) VALUES ('%s', '%s', '%s')",
dbesc(normalise_link($item["author-link"])), dbesc($item["author-name"]), dbesc($item["author-avatar"]));
$author = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1",
$author = q("SELECT `id` FROM `unique_contacts` WHERE `url`='%s' LIMIT 1",
dbesc(normalise_link($item['author-link'])));
} else if ($item["author-link"].$item["author-name"] != $author[0]["url"].$author[0]["name"]) {
q("UPDATE unique_contacts SET name = '%s', avatar = '%s' WHERE url = '%s'",
dbesc($item["author-name"]), dbesc($item["author-avatar"]), dbesc(normalise_link($item["author-link"])));
$r = q("SELECT `id` FROM `unique_contacts` WHERE `name` = '%s' AND `avatar` = '%s' AND url = '%s'",
dbesc($item["author-name"]), dbesc($item["author-avatar"]),
dbesc(normalise_link($item["author-link"])));
if (!$r)
q("UPDATE `unique_contacts` SET `name` = '%s', `avatar` = '%s' WHERE `url` = '%s'",
dbesc($item["author-name"]), dbesc($item["author-avatar"]),
dbesc(normalise_link($item["author-link"])));
}
$owner = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1",
$owner = q("SELECT `id` FROM `unique_contacts` WHERE `url`='%s' LIMIT 1",
dbesc(normalise_link($item['owner-link'])));
if (count($owner) == 0) {
q("INSERT INTO unique_contacts (url, name, avatar) VALUES ('%s', '%s', '%s')",
dbesc(normalise_link($item["owner-link"])), dbesc($item["owner-name"]), dbesc($item["owner-avatar"]));
q("INSERT INTO `unique_contacts` (`url`, `name`, `avatar`) VALUES ('%s', '%s', '%s')",
dbesc(normalise_link($item["owner-link"])), dbesc($item["owner-name"]), dbesc($item["owner-avatar"]));
$owner = q("SELECT id FROM unique_contacts WHERE url='%s' LIMIT 1",
$owner = q("SELECT `id` FROM `unique_contacts` WHERE `url`='%s' LIMIT 1",
dbesc(normalise_link($item['owner-link'])));
} else if ($item["owner-link"].$item["owner-name"] != $owner[0]["url"].$owner[0]["name"]) {
q("UPDATE unique_contacts SET name = '%s', avatar = '%s' WHERE url = '%s'",
dbesc($item["owner-name"]), dbesc($item["owner-avatar"]), dbesc(normalise_link($item["owner-link"])));
$r = q("SELECT `id` FROM `unique_contacts` WHERE `name` = '%s' AND `avatar` = '%s' AND url = '%s'",
dbesc($item["owner-name"]), dbesc($item["owner-avatar"]),
dbesc(normalise_link($item["owner-link"])));
if (!$r)
q("UPDATE `unique_contacts` SET `name` = '%s', `avatar` = '%s' WHERE `url` = '%s'",
dbesc($item["owner-name"]), dbesc($item["owner-avatar"]),
dbesc(normalise_link($item["owner-link"])));
}
// Comments in threads may appear as wall-to-wall postings.
@ -914,14 +927,18 @@
logger('api_status_show: user_info: '.print_r($user_info, true), LOGGER_DEBUG);
if ($type == "raw")
$privacy_sql = "AND `item`.`allow_cid`='' AND `item`.`allow_gid`='' AND `item`.`deny_cid`='' AND `item`.`deny_gid`=''";
else
$privacy_sql = "";
// get last public wall message
$lastwall = q("SELECT `item`.*, `i`.`contact-id` as `reply_uid`, `i`.`author-link` AS `item-author`
FROM `item`, `item` as `i`
WHERE `item`.`contact-id` = %d AND `item`.`uid` = %d
AND ((`item`.`author-link` IN ('%s', '%s')) OR (`item`.`owner-link` IN ('%s', '%s')))
AND `i`.`id` = `item`.`parent`
AND `item`.`type`!='activity'
AND `item`.`allow_cid`='' AND `item`.`allow_gid`='' AND `item`.`deny_cid`='' AND `item`.`deny_gid`=''
AND `item`.`type`!='activity' $privacy_sql
ORDER BY `item`.`created` DESC
LIMIT 1",
intval($user_info['cid']),
@ -944,7 +961,7 @@
$in_reply_to_status_id= intval($lastwall['parent']);
$in_reply_to_status_id_str = (string) intval($lastwall['parent']);
$r = q("SELECT * FROM unique_contacts WHERE `url` = '%s'", dbesc(normalise_link($lastwall['item-author'])));
$r = q("SELECT * FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($lastwall['item-author'])));
if ($r) {
if ($r[0]['nick'] == "")
$r[0]['nick'] = api_get_nick($r[0]["url"]);
@ -967,7 +984,7 @@
$in_reply_to_screen_name = NULL;
}
$converted = api_convert_item($item);
$converted = api_convert_item($lastwall);
$status_info = array(
'created_at' => api_date($lastwall['created']),
@ -1013,6 +1030,8 @@
unset($status_info["user"]["self"]);
}
logger('status_info: '.print_r($status_info, true), LOGGER_DEBUG);
if ($type == "raw")
return($status_info);
@ -1064,7 +1083,7 @@
$in_reply_to_status_id = intval($lastwall['parent']);
$in_reply_to_status_id_str = (string) intval($lastwall['parent']);
$r = q("SELECT * FROM unique_contacts WHERE `url` = '%s'", dbesc(normalise_link($reply[0]['item-author'])));
$r = q("SELECT * FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($reply[0]['item-author'])));
if ($r) {
if ($r[0]['nick'] == "")
$r[0]['nick'] = api_get_nick($r[0]["url"]);
@ -1076,7 +1095,7 @@
}
}
$converted = api_convert_item($item);
$converted = api_convert_item($lastwall);
$user_info['status'] = array(
'text' => $converted["text"],
@ -1125,9 +1144,9 @@
$userlist = array();
if (isset($_GET["q"])) {
$r = q("SELECT id FROM unique_contacts WHERE name='%s'", dbesc($_GET["q"]));
$r = q("SELECT id FROM `unique_contacts` WHERE `name`='%s'", dbesc($_GET["q"]));
if (!count($r))
$r = q("SELECT id FROM unique_contacts WHERE nick='%s'", dbesc($_GET["q"]));
$r = q("SELECT `id` FROM `unique_contacts` WHERE `nick`='%s'", dbesc($_GET["q"]));
if (count($r)) {
foreach ($r AS $user) {
@ -2170,7 +2189,7 @@
intval(api_user()),
intval($in_reply_to_status_id));
if ($r) {
$r = q("SELECT * FROM unique_contacts WHERE `url` = '%s'", dbesc(normalise_link($r[0]['author-link'])));
$r = q("SELECT * FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($r[0]['author-link'])));
if ($r) {
if ($r[0]['nick'] == "")
@ -2429,7 +2448,7 @@
$stringify_ids = (x($_REQUEST,'stringify_ids')?$_REQUEST['stringify_ids']:false);
$r = q("SELECT unique_contacts.id FROM contact, unique_contacts WHERE contact.nurl = unique_contacts.url AND `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 $sql_extra",
$r = q("SELECT `unique_contact`.`id` FROM contact, `unique_contacts` WHERE contact.nurl = unique_contacts.url AND `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 $sql_extra",
intval(api_user())
);
@ -2831,15 +2850,29 @@ function api_share_as_retweet(&$item) {
function api_get_nick($profile) {
/* To-Do:
- remove trailing jung from profile url
- remove trailing junk from profile url
- pump.io check has to check the website
*/
$nick = "";
$friendica = preg_replace("=https?://(.*)/profile/(.*)=ism", "$2", $profile);
if ($friendica != $profile)
$nick = $friendica;
$r = q("SELECT `nick` FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
if ($r)
$nick = $r[0]["nick"];
if (!$nick == "") {
$r = q("SELECT `nick` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s'",
dbesc(normalise_link($profile)));
if ($r)
$nick = $r[0]["nick"];
}
if (!$nick == "") {
$friendica = preg_replace("=https?://(.*)/profile/(.*)=ism", "$2", $profile);
if ($friendica != $profile)
$nick = $friendica;
}
if (!$nick == "") {
$diaspora = preg_replace("=https?://(.*)/u/(.*)=ism", "$2", $profile);
@ -2877,8 +2910,8 @@ function api_get_nick($profile) {
//}
if ($nick != "") {
q("UPDATE unique_contacts SET nick = '%s' WHERE url = '%s'",
dbesc($nick), dbesc(normalise_link($profile)));
q("UPDATE `unique_contacts` SET `nick` = '%s' WHERE `nick` != '%s' AND url = '%s'",
dbesc($nick), dbesc($nick), dbesc(normalise_link($profile)));
return($nick);
}

View File

@ -108,7 +108,7 @@ class exAuth
// ovdje provjeri je li korisnik OK
$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
$this->writeDebugLog("[debug] checking isuser for ". $sUser);
$sQuery = "select * from user where nickname='". $db->escape($sUser) ."'";
$sQuery = "SELECT `uid` FROM `user` WHERE `nickname`='". $db->escape($sUser) ."'";
$this->writeDebugLog("[debug] using query ". $sQuery);
if ($oResult = q($sQuery)){
if ($oResult) {
@ -120,7 +120,7 @@ class exAuth
$this->writeLog("[exAuth] invalid user: ". $sUser);
fwrite(STDOUT, pack("nn", 2, 0));
}
$oResult->close();
//$oResult->close();
} else {
$this->writeLog("[MySQL] invalid query: ". $sQuery);
fwrite(STDOUT, pack("nn", 2, 0));
@ -136,10 +136,14 @@ class exAuth
// ovdje provjeri prijavu
$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
$this->writeDebugLog("[debug] doing auth for ". $sUser);
$sQuery = "select * from user where password='".hash('whirlpool',$aCommand[3])."' and nickname='". $db->escape($sUser) ."'";
//$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `password`='".hash('whirlpool',$aCommand[3])."' AND `nickname`='". $db->escape($sUser) ."'";
$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `nickname`='". $db->escape($sUser) ."'";
$this->writeDebugLog("[debug] using query ". $sQuery);
if ($oResult = q($sQuery)){
if ($oResult) {
$uid = $oResult[0]["uid"];
$Error = ($oResult[0]["password"] != hash('whirlpool',$aCommand[3]));
/*
if ($oResult[0]["password"] == hash('whirlpool',$aCommand[3])) {
// korisnik OK
$this->writeLog("[exAuth] authentificated user ". $sUser ."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 1));
@ -149,9 +153,24 @@ class exAuth
fwrite(STDOUT, pack("nn", 2, 0));
}
$oResult->close();
*/
} else {
$this->writeLog("[MySQL] invalid query: ". $sQuery);
$Error = true;
$uid = -1;
}
if ($Error) {
$oConfig = q("SELECT `v` FROM `pconfig` WHERE `uid`=%d AND `cat` = 'xmpp' AND `k`='password' LIMIT 1;", intval($uid));
$this->writeLog("[exAuth] got password ".$oConfig[0]["v"]);
$Error = ($aCommand[3] != $oConfig[0]["v"]);
}
if ($Error) {
$this->writeLog("[exAuth] authentification failed for user ". $sUser ."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 0));
} else {
$this->writeLog("[exAuth] authentificated user ". $sUser ."@". $aCommand[2]);
fwrite(STDOUT, pack("nn", 2, 1));
}
}
break;

View File

@ -83,7 +83,6 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
'return \'#\'. str_replace(\' \', \'_\', $match[2]);'
), $Text);
// Converting images with size parameters to simple images. Markdown doesn't know it.
$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $Text);
@ -94,11 +93,12 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
// Add all tags that maybe were removed
if (preg_match_all("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",$OriginalText, $tags)) {
$tagline = "";
foreach($tags[2] as $tag)
if (!strpos($Text, "#".$tag))
foreach($tags[2] as $tag) {
$tag = html_entity_decode($tag, ENT_QUOTES, 'UTF-8');
if (!strpos(html_entity_decode($Text, ENT_QUOTES, 'UTF-8'), "#".$tag))
$tagline .= "#".$tag." ";
$Text = $Text."<br />".$tagline;
}
$Text = $Text." ".$tagline;
}
} else

View File

@ -2,7 +2,23 @@
require_once("include/oembed.php");
require_once('include/event.php');
require_once('include/map.php');
require_once('mod/proxy.php');
function bb_PictureCacheExt($matches) {
if (strpos($matches[3], "data:image/") === 0)
return ($matches[0]);
$matches[3] = proxy_url($matches[3]);
return "[img=".$matches[1]."x".$matches[2]."]".$matches[3]."[/img]";
}
function bb_PictureCache($matches) {
if (strpos($matches[1], "data:image/") === 0)
return ($matches[0]);
$matches[1] = proxy_url($matches[1]);
return "[img]".$matches[1]."[/img]";
}
function bb_map_coords($match) {
// the extra space in the following line is intentional
@ -83,10 +99,19 @@ function bb_attachment($Text, $simplehtml = false, $tryoembed = true) {
$image = "";
}
if ($simplehtml == 7)
$text = sprintf('<a href="%s" title="%s" class="attachment thumbnail" rel="nofollow external">%s</a>',
$url, $title, $title);
elseif (($simplehtml != 4) AND ($simplehtml != 0))
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);
@ -101,9 +126,9 @@ function bb_attachment($Text, $simplehtml = false, $tryoembed = true) {
$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, $image, $title);
$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, $preview, $title);
$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;
@ -455,7 +480,7 @@ function bb_replace_images($body, $images) {
// We're depending on the property of 'foreach' (specified on the PHP website) that
// it loops over the array starting from the first element and going sequentially
// to the last element
$newbody = str_replace('[$#saved_image' . $cnt . '#$]', '<img src="' . $image .'" alt="' . t('Image/photo') . '" />', $newbody);
$newbody = str_replace('[$#saved_image' . $cnt . '#$]', '<img src="' . proxy_url($image) .'" alt="' . t('Image/photo') . '" />', $newbody);
$cnt++;
}
@ -585,7 +610,7 @@ function bb_ShareAttributes($share, $simplehtml) {
default:
$headline = trim($share[1]).'<div class="shared_header">';
if ($avatar != "")
$headline .= '<img src="'.$avatar.'" height="32" width="32" >';
$headline .= '<img src="'.proxy_url($avatar, false, PROXY_SIZE_MICRO).'" height="32" width="32" >';
$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>";
@ -934,12 +959,14 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
$Text = preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi", 'bb_DiasporaLinks', $Text);
// if the HTML is used to generate plain text, then don't do this search, but replace all URL of that kind to text
if (!$forplaintext)
$Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1<a href="$2" target="_blank">$2</a>', $Text);
else {
$Text = preg_replace("(\[url\]([$URLSearchString]*)\[\/url\])ism"," $1 ",$Text);
$Text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'bb_RemovePictureLinks', $Text);
}
// if ($simplehtml != 7) {
if (!$forplaintext)
$Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1<a href="$2" target="_blank">$2</a>', $Text);
else {
$Text = preg_replace("(\[url\]([$URLSearchString]*)\[\/url\])ism"," $1 ",$Text);
$Text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'bb_RemovePictureLinks', $Text);
}
// }
if ($tryoembed)
$Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism",'tryoembed',$Text);
@ -1102,13 +1129,17 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
"<br /><strong class=".'"author"'.">" . $t_wrote . "</strong><blockquote>$2</blockquote>",
$Text);
// [img=widthxheight]image source[/img]
//$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="height: $2px; width: $1px;" >', $Text);
$Text = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", 'bb_PictureCacheExt', $Text);
$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" >', $Text);
$Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px;" >', $Text);
// Images
// [img]pathtoimage[/img]
$Text = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", 'bb_PictureCache', $Text);
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img src="$1" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img src="$1" alt="' . t('Image/photo') . '" />', $Text);
@ -1190,7 +1221,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
// start which is always required). Allow desc with a missing summary for compatibility.
if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
$sub = format_event_html($ev);
$sub = format_event_html($ev, $simplehtml);
$Text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism",'',$Text);
$Text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/ism",'',$Text);

View File

@ -88,7 +88,7 @@ function network_to_name($s, $profile = "") {
NETWORK_PUMPIO => t('pump.io'),
NETWORK_TWITTER => t('Twitter'),
NETWORK_DIASPORA2 => t('Diaspora Connector'),
NETWORK_STATUSNET => t('Statusnet'),
NETWORK_STATUSNET => t('GNU Social'),
NETWORK_APPNET => t('App.net')
);

View File

@ -20,12 +20,12 @@ function findpeople_widget() {
if(get_config('system','invitation_only')) {
$x = get_pconfig(local_user(),'system','invites_remaining');
if($x || is_site_admin()) {
$a->page['aside'] .= '<div class="side-link" id="side-invite-remain">'
. sprintf( tt('%d invitation available','%d invitations available',$x), $x)
$a->page['aside'] .= '<div class="side-link" id="side-invite-remain">'
. sprintf( tt('%d invitation available','%d invitations available',$x), $x)
. '</div>' . $inv;
}
}
return replace_macros(get_markup_template('peoplefind.tpl'),array(
'$findpeople' => t('Find People'),
'$desc' => t('Enter name or interest'),
@ -40,18 +40,55 @@ function findpeople_widget() {
}
function unavailable_networks() {
$network_filter = "";
$networks = array();
if (!plugin_enabled("appnet"))
$networks[] = NETWORK_APPNET;
if (!plugin_enabled("fbpost") AND !plugin_enabled("facebook"))
$networks[] = NETWORK_FACEBOOK;
if (!plugin_enabled("statusnet"))
$networks[] = NETWORK_STATUSNET;
if (!plugin_enabled("pumpio"))
$networks[] = NETWORK_PUMPIO;
if (!plugin_enabled("twitter"))
$networks[] = NETWORK_TWITTER;
if (get_config("system","ostatus_disabled"))
$networks[] = NETWORK_OSTATUS;
if (!get_config("system","diaspora_enabled"))
$networks[] = NETWORK_DIASPORA;
if (!sizeof($networks))
return "";
$network_filter = implode("','", $networks);
$network_filter = "AND `network` NOT IN ('$network_filter')";
return $network_filter;
}
function networks_widget($baseurl,$selected = '') {
$a = get_app();
if(! local_user())
if(!local_user())
return '';
if(! feature_enabled(local_user(),'networks'))
if(!feature_enabled(local_user(),'networks'))
return '';
$r = q("SELECT DISTINCT(`network`) FROM `contact` WHERE `uid` = %d AND `self` = 0 ORDER BY `network`",
$extra_sql = unavailable_networks();
$r = q("SELECT DISTINCT(`network`) FROM `contact` WHERE `uid` = %d AND NOT `self` $extra_sql ORDER BY `network`",
intval(local_user())
);
@ -180,7 +217,7 @@ function common_friends_visitor_widget($profile_uid) {
}
if($cid == 0 && $zcid == 0)
return;
return;
require_once('include/socgraph.php');
@ -204,6 +241,6 @@ function common_friends_visitor_widget($profile_uid) {
'$linkmore' => (($t > 5) ? 'true' : ''),
'$more' => t('show more'),
'$items' => $r
));
));
};

View File

@ -100,7 +100,11 @@ function localize_item(&$item){
$item['body'] = item_redir_and_replace_images($extracted['body'], $extracted['images'], $item['contact-id']);
$xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">";
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)){
$r = q("SELECT * from `item`,`contact` WHERE
`item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s';",
@ -139,6 +143,15 @@ function localize_item(&$item){
elseif(activity_match($item['verb'],ACTIVITY_DISLIKE)) {
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
}
elseif(activity_match($item['verb'],ACTIVITY_ATTEND)) {
$bodyverb = t('%1$s attends %2$s\'s %3$s');
}
elseif(activity_match($item['verb'],ACTIVITY_ATTENDNO)) {
$bodyverb = t('%1$s doesn\'t attend %2$s\'s %3$s');
}
elseif(activity_match($item['verb'],ACTIVITY_ATTENDMAYBE)) {
$bodyverb = t('%1$s attends maybe %2$s\'s %3$s');
}
$item['body'] = sprintf($bodyverb, $author, $objauthor, $plink);
}
@ -204,7 +217,7 @@ function localize_item(&$item){
// we can't have a translation string with three positions but no distinguishable text
// So here is the translate string.
$txt = t('%1$s poked %2$s');
// now translate the verb
$poked_t = trim(sprintf($txt, "",""));
$txt = str_replace( $poked_t, t($verb), $txt);
@ -341,8 +354,15 @@ function count_descendants($item) {
function visible_activity($item) {
if(activity_match($item['verb'],ACTIVITY_LIKE) || activity_match($item['verb'],ACTIVITY_DISLIKE))
return false;
// likes (etc.) can apply to other things besides posts. Check if they are post children,
// in which case we handle them specially
$hidden_activities = array(ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE);
foreach($hidden_activities as $act) {
if(activity_match($item['verb'],$act)) {
return false;
}
}
if(activity_match($item['verb'],ACTIVITY_FOLLOW) && $item['object-type'] === ACTIVITY_OBJ_NOTE) {
if(! (($item['self']) && ($item['uid'] == local_user()))) {
@ -396,25 +416,25 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$page_writeable = true;
if(!$update) {
// The special div is needed for liveUpdate to kick in for this page.
// We only launch liveUpdate if you aren't filtering in some incompatible
// We only launch liveUpdate if you aren't filtering in some incompatible
// way and also you aren't writing a comment (discovered in javascript).
$live_update_div = '<div id="live-network"></div>' . "\r\n"
. "<script> var profile_uid = " . $_SESSION['uid']
. "<script> var profile_uid = " . $_SESSION['uid']
. "; var netargs = '" . substr($a->cmd,8)
. '?f='
. ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '')
. ((x($_GET,'search')) ? '&search=' . $_GET['search'] : '')
. ((x($_GET,'star')) ? '&star=' . $_GET['star'] : '')
. ((x($_GET,'order')) ? '&order=' . $_GET['order'] : '')
. ((x($_GET,'bmark')) ? '&bmark=' . $_GET['bmark'] : '')
. ((x($_GET,'liked')) ? '&liked=' . $_GET['liked'] : '')
. ((x($_GET,'conv')) ? '&conv=' . $_GET['conv'] : '')
. ((x($_GET,'spam')) ? '&spam=' . $_GET['spam'] : '')
. ((x($_GET,'nets')) ? '&nets=' . $_GET['nets'] : '')
. ((x($_GET,'cmin')) ? '&cmin=' . $_GET['cmin'] : '')
. ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
. ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '')
. ((x($_GET,'search')) ? '&search=' . $_GET['search'] : '')
. ((x($_GET,'star')) ? '&star=' . $_GET['star'] : '')
. ((x($_GET,'order')) ? '&order=' . $_GET['order'] : '')
. ((x($_GET,'bmark')) ? '&bmark=' . $_GET['bmark'] : '')
. ((x($_GET,'liked')) ? '&liked=' . $_GET['liked'] : '')
. ((x($_GET,'conv')) ? '&conv=' . $_GET['conv'] : '')
. ((x($_GET,'spam')) ? '&spam=' . $_GET['spam'] : '')
. ((x($_GET,'nets')) ? '&nets=' . $_GET['nets'] : '')
. ((x($_GET,'cmin')) ? '&cmin=' . $_GET['cmin'] : '')
. ((x($_GET,'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
. ((x($_GET,'file')) ? '&file=' . $_GET['file'] : '')
. "'; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
}
@ -431,7 +451,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
// because browser prefetching might change it on us. We have to deliver it with the page.
$live_update_div = '<div id="live-profile"></div>' . "\r\n"
. "<script> var profile_uid = " . $a->profile['profile_uid']
. "<script> var profile_uid = " . $a->profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
}
}
@ -441,7 +461,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$page_writeable = true;
if(!$update) {
$live_update_div = '<div id="live-notes"></div>' . "\r\n"
. "<script> var profile_uid = " . local_user()
. "<script> var profile_uid = " . local_user()
. "; var netargs = '/?f='; var profile_page = " . $a->pager['page'] . "; </script>\r\n";
}
}
@ -484,8 +504,10 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
$cmnt_tpl = get_markup_template('comment_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)
$threads = array();
@ -656,7 +678,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
'name' => $profile_name_e,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => proxy_url($profile_avatar),
'thumb' => proxy_url($profile_avatar, false, PROXY_SIZE_THUMB),
'title' => $item['title_e'],
'body' => $body_e,
'tags' => $tags_e,
@ -675,7 +697,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
'indent' => '',
'owner_name' => $owner_name_e,
'owner_url' => $owner_url,
'owner_photo' => proxy_url($owner_photo),
'owner_photo' => proxy_url($owner_photo, false, PROXY_SIZE_THUMB),
'plink' => get_plink($item),
'edpost' => false,
'isstarred' => $isstarred,
@ -734,8 +756,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
// Can we put this after the visibility check?
like_puller($a,$item,$alike,'like');
like_puller($a,$item,$dlike,'dislike');
builtin_activity_puller($item, $conv_responses);
// Only add what is visible
if($item['network'] === NETWORK_MAIL && local_user() != $item['uid']) {
@ -755,7 +776,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
}
}
$threads = $conv->get_template_data($alike, $dlike);
$threads = $conv->get_template_data($conv_responses);
if(!$threads) {
logger('[ERROR] conversation : Failed to get template data.', LOGGER_DEBUG);
@ -792,10 +813,16 @@ function best_link_url($item,&$sparkle,$ssl_state = false) {
if($a->contacts[$clean_url]['network'] === NETWORK_DFRN) {
$best_url = $a->get_baseurl($ssl_state) . '/redir/' . $a->contacts[$clean_url]['id'];
$sparkle = true;
}
else
} else
$best_url = $a->contacts[$clean_url]['url'];
}
} elseif (local_user()) {
$r = q("SELECT `id`, `network` FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` = '%s'",
dbesc(NETWORK_DFRN), intval(local_user()), dbesc(normalise_link($clean_url)));
if ($r) {
$best_url = $a->get_baseurl($ssl_state).'/redir/'.$r[0]['id'];
$sparkle = true;
}
}
if(! $best_url) {
if(strlen($item['author-link']))
@ -848,15 +875,23 @@ function item_photo_menu($item){
$profile_link = zrl($profile_link);
if(local_user() && local_user() == $item['uid'] && link_compare($item['url'],$item['author-link'])) {
$cid = $item['contact-id'];
}
else {
$cid = 0;
} else {
$r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' ORDER BY `uid` DESC 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 = $a->get_baseurl($ssl_state) . '/message/new/' . $cid;
} else
$cid = 0;
}
}
if(($cid) && (! $item['self'])) {
$poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $cid;
$contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid;
$posts_link = $a->get_baseurl($ssl_state) . '/network/0?nets=all&cid=' . $cid;
$posts_link = $a->get_baseurl($ssl_state) . '/contacts/' . $cid . '/posts';
$clean_url = normalise_link($item['author-link']);
@ -870,17 +905,25 @@ function item_photo_menu($item){
}
$menu = Array(
t("Follow Thread") => $sub_link,
t("View Status") => $status_link,
t("View Profile") => $profile_link,
t("View Photos") => $photos_link,
t("Network Posts") => $posts_link,
t("Edit Contact") => $contact_url,
t("Send PM") => $pm_url,
t("Poke") => $poke_link
);
if (local_user()) {
$menu = Array(
t("Follow Thread") => $sub_link,
t("View Status") => $status_link,
t("View Profile") => $profile_link,
t("View Photos") => $photos_link,
t("Network Posts") => $posts_link,
t("Edit Contact") => $contact_url,
t("Send PM") => $pm_url
);
if ($a->contacts[$clean_url]['network'] === NETWORK_DFRN)
$menu[t("Poke")] = $poke_link;
if ((($cid == 0) OR ($a->contacts[$clean_url]['rel'] == CONTACT_IS_FOLLOWER)) AND
in_array($item['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
$menu[t("Connect/Follow")] = $a->get_baseurl($ssl_state)."/follow?url=".urlencode($item['author-link']);
} else
$menu = array(t("View Profile") => $item['author-link']);
$args = array('item' => $item, 'menu' => $menu);
@ -899,65 +942,114 @@ function item_photo_menu($item){
return $o;
}}
if(! function_exists('like_puller')) {
function like_puller($a,$item,&$arr,$mode) {
/**
* @brief Checks item to see if it is one of the builtin activities (like/dislike, event attendance, consensus items, etc.)
* Increments the count of each matching activity and adds a link to the author as needed.
*
* @param array $a (not used)
* @param array $item
* @param array &$conv_responses (already created with builtin activity structure)
* @return void
*/
if(! function_exists('builtin_activity_puller')) {
function builtin_activity_puller($item, &$conv_responses) {
foreach($conv_responses as $mode => $v) {
$url = '';
$sparkle = '';
$url = '';
$sparkle = '';
$verb = (($mode === 'like') ? ACTIVITY_LIKE : ACTIVITY_DISLIKE);
if((activity_match($item['verb'],$verb)) && ($item['id'] != $item['parent'])) {
$url = $item['author-link'];
if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === NETWORK_DFRN) && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) {
$url = $a->get_baseurl(true) . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle" ';
switch($mode) {
case 'like':
$verb = ACTIVITY_LIKE;
break;
case 'dislike':
$verb = ACTIVITY_DISLIKE;
break;
case 'attendyes':
$verb = ACTIVITY_ATTEND;
break;
case 'attendno':
$verb = ACTIVITY_ATTENDNO;
break;
case 'attendmaybe':
$verb = ACTIVITY_ATTENDMAYBE;
break;
default:
return;
break;
}
else
$url = zrl($url);
if(! $item['thr-parent'])
$item['thr-parent'] = $item['parent-uri'];
if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
$url = $item['author-link'];
if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === NETWORK_DFRN) && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) {
$url = z_root(true) . '/redir/' . $item['contact-id'];
$sparkle = ' class="sparkle" ';
}
else
$url = zrl($url);
if(! ((isset($arr[$item['thr-parent'] . '-l'])) && (is_array($arr[$item['thr-parent'] . '-l']))))
$arr[$item['thr-parent'] . '-l'] = array();
if(! isset($arr[$item['thr-parent']]))
$arr[$item['thr-parent']] = 1;
else
$arr[$item['thr-parent']] ++;
$arr[$item['thr-parent'] . '-l'][] = '<a href="'. $url . '"'. $sparkle .'>' . $item['author-name'] . '</a>';
$url = '<a href="'. $url . '"'. $sparkle .'>' . htmlentities($item['author-name']) . '</a>';
if(! $item['thr-parent'])
$item['thr-parent'] = $item['parent-uri'];
if(! ((isset($conv_responses[$mode][$item['thr-parent'] . '-l']))
&& (is_array($conv_responses[$mode][$item['thr-parent'] . '-l']))))
$conv_responses[$mode][$item['thr-parent'] . '-l'] = array();
// only list each unique author once
if(in_array($url,$conv_responses[$mode][$item['thr-parent'] . '-l']))
continue;
if(! isset($conv_responses[$mode][$item['thr-parent']]))
$conv_responses[$mode][$item['thr-parent']] = 1;
else
$conv_responses[$mode][$item['thr-parent']] ++;
$conv_responses[$mode][$item['thr-parent'] . '-l'][] = $url;
// there can only be one activity verb per item so if we found anything, we can stop looking
return;
}
}
return;
}}
// Format the like/dislike text for a profile item
// $cnt = number of people who like/dislike the item
// Format the vote text for a profile item
// $cnt = number of people who vote the item
// $arr = array of pre-linked names of likers/dislikers
// $type = one of 'like, 'dislike'
// $type = one of 'like, 'dislike', 'attendyes', 'attendno', 'attendmaybe'
// $id = item id
// returns formatted text
if(! function_exists('format_like')) {
function format_like($cnt,$arr,$type,$id) {
$o = '';
if($cnt == 1)
$o .= (($type === 'like') ? sprintf( t('%s likes this.'), $arr[0]) : sprintf( t('%s doesn\'t like this.'), $arr[0])) . EOL ;
else {
$spanatts = "class=\"fakelink\" onclick=\"openClose('{$type}list-$id');\"";
$expanded = '';
if($cnt == 1) {
$likers = $arr[0];
// Phrase if there is only one liker. In other cases it will be uses for the expanded
// list which show all likers
switch($type) {
case 'like':
$phrase = sprintf( t('<span %1$s>%2$d people</span> like this'), $spanatts, $cnt);
case 'like' :
$phrase = sprintf( t('%s likes this.'), $likers);
break;
case 'dislike':
$phrase = sprintf( t('<span %1$s>%2$d people</span> don\'t like this'), $spanatts, $cnt);
case 'dislike' :
$phrase = sprintf( t('%s doesn\'t like this.'), $likers);
break;
case 'attendyes' :
$phrase = sprintf( t('%s attends.'), $likers);
break;
case 'attendno' :
$phrase = sprintf( t('%s doesn\'t attend.'), $likers);
break;
case 'attendmaybe' :
$phrase = sprintf( t('%s attends maybe.'), $likers);
break;
}
$phrase .= EOL ;
$o .= replace_macros(get_markup_template('voting_fakelink.tpl'), array(
'$phrase' => $phrase,
'$type' => $type,
'$id' => $id
));
}
if($cnt > 1) {
$total = count($arr);
if($total >= MAX_LIKERS)
$arr = array_slice($arr, 0, MAX_LIKERS - 1);
@ -970,9 +1062,45 @@ function format_like($cnt,$arr,$type,$id) {
$str = implode(', ', $arr);
$str .= sprintf( t(', and %d other people'), $total - MAX_LIKERS );
}
$str = (($type === 'like') ? sprintf( t('%s like this.'), $str) : sprintf( t('%s don\'t like this.'), $str));
$o .= "\t" . '<div class="wall-item-' . $type . '-expanded" id="' . $type . 'list-' . $id . '" style="display: none;" >' . $str . '</div>';
$likers = $str;
$spanatts = "class=\"fakelink\" onclick=\"openClose('{$type}list-$id');\"";
switch($type) {
case 'like':
$phrase = sprintf( t('<span %1$s>%2$d people</span> like this'), $spanatts, $cnt);
$explikers = sprintf( t('%s like this.'), $likers);
break;
case 'dislike':
$phrase = sprintf( t('<span %1$s>%2$d people</span> don\'t like this'), $spanatts, $cnt);
$explikers = sprintf( t('%s don\'t like this.'), $likers);
break;
case 'attendyes':
$phrase = sprintf( t('<span %1$s>%2$d people</span> attend'), $spanatts, $cnt);
$explikers = sprintf( t('%s attend.'), $likers);
break;
case 'attendno':
$phrase = sprintf( t('<span %1$s>%2$d people</span> don\'t attend'), $spanatts, $cnt);
$explikers = sprintf( t('%s don\'t attend.'), $likers);
break;
case 'attendmaybe':
$phrase = sprintf( t('<span %1$s>%2$d people</span> anttend maybe'), $spanatts, $cnt);
$explikers = sprintf( t('%s anttend maybe.'), $likers);
break;
}
$expanded .= "\t" . '<div class="wall-item-' . $type . '-expanded" id="' . $type . 'list-' . $id . '" style="display: none;" >' . $explikers . EOL . '</div>';
}
$phrase .= EOL ;
$o .= replace_macros(get_markup_template('voting_fakelink.tpl'), array(
'$phrase' => $phrase,
'$type' => $type,
'$id' => $id
));
$o .= $expanded;
return $o;
}}
@ -1163,6 +1291,15 @@ function conv_sort($arr,$order) {
$parents = array();
$children = array();
$newarr = array();
// This is a preparation for having two different items with the same uri in one thread
// This will otherwise lead to an endless loop.
foreach($arr as $x)
if (!isset($newarr[$x['uri']]))
$newarr[$x['uri']] = $x;
$arr = $newarr;
foreach($arr as $x)
if($x['id'] == $x['parent'])
@ -1236,3 +1373,51 @@ function render_location_dummy($item) {
if ($item['coord'] != "")
return $item['coord'];
}
function get_responses($conv_responses,$response_verbs,$ob,$item) {
$ret = array();
foreach($response_verbs as $v) {
$ret[$v] = array();
$ret[$v]['count'] = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri']] : '');
$ret[$v]['list'] = ((x($conv_responses[$v],$item['uri'])) ? $conv_responses[$v][$item['uri'] . '-l'] : '');
if(count($ret[$v]['list']) > MAX_LIKERS) {
$ret[$v]['list_part'] = array_slice($ret[$v]['list'], 0, MAX_LIKERS);
array_push($ret[$v]['list_part'], '<a href="#" data-toggle="modal" data-target="#' . $v . 'Modal-'
. (($ob) ? $ob->get_id() : $item['id']) . '"><b>' . t('View all') . '</b></a>');
}
else {
$ret[$v]['list_part'] = '';
}
$ret[$v]['button'] = get_response_button_text($v,$ret[$v]['count']);
$ret[$v]['title'] = $conv_responses[$v]['title'];
}
$count = 0;
foreach($ret as $key) {
if ($key['count'] == true)
$count++;
}
$ret['count'] = $count;
return $ret;
}
function get_response_button_text($v,$count) {
switch($v) {
case 'like':
return tt('Like','Likes',$count,'noun');
break;
case 'dislike':
return tt('Dislike','Dislikes',$count,'noun');
break;
case 'attendyes':
return tt('Attending','Attending',$count,'noun');
break;
case 'attendno':
return tt('Not Attending','Not Attending',$count,'noun');
break;
case 'attendmaybe':
return tt('Undecided','Undecided',$count,'noun');
break;
}
}

379
include/cron.php Normal file
View File

@ -0,0 +1,379 @@
<?php
if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
$directory = dirname($_SERVER["argv"][0]);
if (substr($directory, 0, 1) != "/")
$directory = $_SERVER["PWD"]."/".$directory;
$directory = realpath($directory."/..");
chdir($directory);
}
require_once("boot.php");
function cron_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
require_once('library/simplepie/simplepie.inc');
require_once('include/items.php');
require_once('include/Contact.php');
require_once('include/email.php');
require_once('include/socgraph.php');
require_once('include/pidfile.php');
require_once('mod/nodeinfo.php');
load_config('config');
load_config('system');
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
$load = current_load();
if($load) {
if(intval($load) > $maxsysload) {
logger('system: load ' . $load . ' too high. cron deferred to next scheduled run.');
return;
}
}
$last = get_config('system','last_cron');
$poll_interval = intval(get_config('system','cron_interval'));
if(! $poll_interval)
$poll_interval = 10;
if($last) {
$next = $last + ($poll_interval * 60);
if($next > time()) {
logger('cron intervall not reached');
return;
}
}
$lockpath = get_lockpath();
if ($lockpath != '') {
$pidfile = new pidfile($lockpath, 'cron');
if($pidfile->is_already_running()) {
logger("cron: Already running");
if ($pidfile->running_time() > 9*60) {
$pidfile->kill();
logger("cron: killed stale process");
// Calling a new instance
proc_run('php','include/cron.php');
}
exit;
}
}
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('cron: start');
// run queue delivery process in the background
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");
// run the process to update locally stored global contacts in the background
proc_run('php',"include/discover_poco.php", "checkcontact");
// expire any expired accounts
q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
AND `account_expires_on` != '0000-00-00 00:00:00'
AND `account_expires_on` < UTC_TIMESTAMP() ");
// delete user and contact records for recently removed accounts
$r = q("SELECT * FROM `user` WHERE `account_removed` = 1 AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
if ($r) {
foreach($r as $user) {
q("DELETE FROM `contact` WHERE `uid` = %d", intval($user['uid']));
q("DELETE FROM `user` WHERE `uid` = %d", intval($user['uid']));
}
}
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
$abandon_days = 0;
// Check OStatus conversations
// Check only conversations with mentions (for a longer time)
check_conversations(true);
// Check every conversation
check_conversations(false);
// Follow your friends from your legacy OStatus account
// Doesn't work
// ostatus_check_follow_friends();
// update nodeinfo data
nodeinfo_cron();
// To-Do: Regenerate usage statistics
// q("ANALYZE TABLE `item`");
// once daily run birthday_updates and then expire in background
$d1 = get_config('system','last_expire_day');
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
if($d2 != intval($d1)) {
update_contact_birthdays();
proc_run('php',"include/discover_poco.php", "suggestions");
set_config('system','last_expire_day',$d2);
proc_run('php','include/expire.php');
}
$last = get_config('system','cache_last_cleared');
if($last) {
$next = $last + (3600); // Once per hour
$clear_cache = ($next <= time());
} else
$clear_cache = true;
if ($clear_cache) {
// clear old cache
Cache::clear();
// clear old item cache files
clear_cache();
// clear cache for photos
clear_cache($a->get_basepath(), $a->get_basepath()."/photo");
// clear smarty cache
clear_cache($a->get_basepath()."/view/smarty3/compiled", $a->get_basepath()."/view/smarty3/compiled");
// clear cache for image proxy
if (!get_config("system", "proxy_disabled")) {
clear_cache($a->get_basepath(), $a->get_basepath()."/proxy");
$cachetime = get_config('system','proxy_cache_time');
if (!$cachetime) $cachetime = PROXY_DEFAULT_TIME;
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
}
// Maximum table size in megabyte
$max_tablesize = intval(get_config('system','optimize_max_tablesize')) * 1000000;
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%
// Optimize some tables that need to be optimized
$r = q("SHOW TABLE STATUS");
foreach($r as $table) {
// Don't optimize tables that are too large
if ($table["Data_length"] > $max_tablesize)
continue;
// Don't optimize empty tables
if ($table["Data_length"] == 0)
continue;
// Calculate fragmentation
$fragmentation = $table["Data_free"] / $table["Data_length"];
logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
// Don't optimize tables that needn't to be optimized
if ($fragmentation < $fragmentation_level)
continue;
// So optimize it
logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
}
set_config('system','cache_last_cleared', time());
}
$manual_id = 0;
$generation = 0;
$force = false;
$restart = false;
if(($argc > 1) && ($argv[1] == 'force'))
$force = true;
if(($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
killme();
}
if(($argc > 1) && intval($argv[1])) {
$manual_id = intval($argv[1]);
$force = true;
}
$interval = intval(get_config('system','poll_interval'));
if(! $interval)
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker"))
$interval = false;
$sql_extra = (($manual_id) ? " AND `id` = $manual_id " : "");
reload_plugins();
$d = datetime_convert();
// Only poll from those with suitable relationships,
// and which have a polling address and ignore Diaspora since
// we are unable to match those posts with a Diaspora GUID and prevent duplicates.
$abandon_sql = (($abandon_days)
? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days))
: ''
);
$contacts = q("SELECT `contact`.`id` FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `rel` IN (%d, %d) AND `poll` != '' AND `network` IN ('%s', '%s', '%s', '%s', '%s', '%s')
$sql_extra
AND NOT `self` AND NOT `contact`.`blocked` AND NOT `contact`.`readonly` AND NOT `contact`.`archive`
AND NOT `user`.`account_expired` AND NOT `user`.`account_removed` $abandon_sql ORDER BY RAND()",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_ZOT),
dbesc(NETWORK_OSTATUS),
dbesc(NETWORK_FEED),
dbesc(NETWORK_MAIL),
dbesc(NETWORK_MAIL2)
);
if(! count($contacts)) {
return;
}
foreach($contacts as $c) {
$res = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($c['id'])
);
if((! $res) || (! count($res)))
continue;
foreach($res as $contact) {
$xml = false;
if($manual_id)
$contact['last-update'] = '0000-00-00 00:00:00';
if(in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS)))
$contact['priority'] = 2;
if($contact['subhub'] AND in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) {
// We should be getting everything via a hub. But just to be sure, let's check once a day.
// (You can make this more or less frequent if desired by setting 'pushpoll_frequency' appropriately)
// This also lets us update our subscription to the hub, and add or replace hubs in case it
// changed. We will only update hubs once a day, regardless of 'pushpoll_frequency'.
$poll_interval = get_config('system','pushpoll_frequency');
$contact['priority'] = (($poll_interval !== false) ? intval($poll_interval) : 3);
}
if($contact['priority'] AND !$force) {
$update = false;
$t = $contact['last-update'];
/**
* Based on $contact['priority'], should we poll this site now? Or later?
*/
switch ($contact['priority']) {
case 5:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 month"))
$update = true;
break;
case 4:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 week"))
$update = true;
break;
case 3:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
$update = true;
break;
case 2:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 12 hour"))
$update = true;
break;
case 1:
default:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 hour"))
$update = true;
break;
}
if(!$update)
continue;
}
logger("Polling ".$contact["network"]." ".$contact["id"]." ".$contact["nick"]." ".$contact["name"]);
proc_run('php','include/onepoll.php',$contact['id']);
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
}
logger('cron: end');
set_config('system','last_cron', time());
return;
}
if (array_search(__file__,get_included_files())===0){
cron_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View File

@ -11,11 +11,11 @@ function cronhooks_run(&$argv, &$argc){
}
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);
};
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/session.php');
require_once('include/datetime.php');
@ -27,10 +27,25 @@ function cronhooks_run(&$argv, &$argc){
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load[0] . ' too high. Cronhooks deferred to next scheduled run.');
$load = current_load();
if($load) {
if(intval($load) > $maxsysload) {
logger('system: load ' . $load . ' too high. Cronhooks deferred to next scheduled run.');
return;
}
}
$last = get_config('system','last_cronhook');
$poll_interval = intval(get_config('system','cronhook_interval'));
if(! $poll_interval)
$poll_interval = 9;
if($last) {
$next = $last + ($poll_interval * 60);
if($next > time()) {
logger('cronhook intervall not reached');
return;
}
}
@ -41,11 +56,11 @@ function cronhooks_run(&$argv, &$argc){
if($pidfile->is_already_running()) {
logger("cronhooks: Already running");
if ($pidfile->running_time() > 19*60) {
$pidfile->kill();
logger("cronhooks: killed stale process");
$pidfile->kill();
logger("cronhooks: killed stale process");
// Calling a new instance
proc_run('php','include/cronhooks.php');
}
}
exit;
}
}
@ -62,10 +77,12 @@ function cronhooks_run(&$argv, &$argc){
logger('cronhooks: end');
set_config('system','last_cronhook', time());
return;
}
if (array_search(__file__,get_included_files())===0){
cronhooks_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
cronhooks_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View File

@ -43,18 +43,18 @@ function select_timezone($current = 'America/Los_Angeles') {
if($continent != t('Miscellaneous')) {
$o .= '</optgroup>';
$continent = t('Miscellaneous');
$o .= '<optgroup label="' . t($continent) . '">';
$o .= '<optgroup label="' . t($continent) . '">';
}
}
$city = str_replace('_', ' ', t($city));
$selected = (($value == $current) ? " selected=\"selected\" " : "");
$o .= "<option value=\"$value\" $selected >$city</option>";
}
}
$o .= '</optgroup></select>';
return $o;
}}
// return a select using 'field_select_raw' template, with timezones
// return a select using 'field_select_raw' template, with timezones
// groupped (primarily) by continent
// arguments follow convetion as other field_* template array:
// 'name', 'label', $value, 'help'
@ -63,12 +63,12 @@ function field_timezone($name='timezone', $label='', $current = 'America/Los_Ang
$options = select_timezone($current);
$options = str_replace('<select id="timezone_select" name="timezone">','', $options);
$options = str_replace('</select>','', $options);
$tpl = get_markup_template('field_select_raw.tpl');
return replace_macros($tpl, array(
'$field' => array($name, $label, $current, $help, $options),
));
}}
// General purpose date parse/convert function.
@ -92,8 +92,8 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
// Slight hackish adjustment so that 'zero' datetime actually returns what is intended
// otherwise we end up with -0001-11-30 ...
// add 32 days so that we at least get year 00, and then hack around the fact that
// months and days always start with 1.
// add 32 days so that we at least get year 00, and then hack around the fact that
// months and days always start with 1.
if(substr($s,0,10) == '0000-00-00') {
$d = new DateTime($s . ' + 32 days', new DateTimeZone('UTC'));
@ -203,13 +203,25 @@ function timesel($format, $h, $m, $id='timepicker') {
* set maximum date from picker with id $maxfrom (none by default)
* @param boolean $required default false
* @return string Parsed HTML output.
*
*
* @todo Once browser support is better this could probably be replaced with
* native HTML5 date picker.
*/
if(! function_exists('datetimesel')) {
function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) {
$a = get_app();
// First day of the week (0 = Sunday)
$firstDay = get_pconfig(local_user(),'system','first_day_of_week');
if ($firstDay === false) $firstDay=0;
$lang = substr(get_browser_language(), 0, 2);
// Check if the detected language is supported by the picker
if (!in_array($lang, array("ar", "ro", "id", "bg", "fa", "ru", "uk", "en", "el", "de", "nl", "tr", "fr", "es", "th", "pl", "pt", "ch", "se", "kr", "it", "da", "no", "ja", "vi", "sl", "cs", "hu")))
$lang = ((isset($a->config['system']['language'])) ? $a->config['system']['language'] : 'en');
$o = '';
$dateformat = '';
if($pickdate) $dateformat .= 'Y-m-d';
@ -217,16 +229,17 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
if($picktime) $dateformat .= 'H:i';
$minjs = $min ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : '';
$maxjs = $max ? ",maxDate: new Date({$max->getTimestamp()}*1000), yearEnd: " . $max->format('Y') : '';
$input_text = $default ? 'value="' . date($dateformat, $default->getTimestamp()) . '"' : '';
$defaultdatejs = $default ? ",defaultDate: new Date({$default->getTimestamp()}*1000)" : '';
$pickers = '';
if(!$pickdate) $pickers .= ',datepicker: false';
if(!$picktime) $pickers .= ',timepicker: false';
$extra_js = '';
if($minfrom != '')
$pickers .= ",dayOfWeekStart: ".$firstDay.",lang:'".$lang."'";
if($minfrom != '')
$extra_js .= "\$('#$minfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({minDate: currentDateTime})}})";
if($maxfrom != '')
if($maxfrom != '')
$extra_js .= "\$('#$maxfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({maxDate: currentDateTime})}})";
$readable_format = $dateformat;
$readable_format = str_replace('Y','yyyy',$readable_format);
@ -236,7 +249,9 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
$readable_format = str_replace('i','MM',$readable_format);
$o .= "<div class='date'><input type='text' placeholder='$readable_format' name='$id' id='$id' $input_text />";
$o .= '</div>';
$o .= "<script type='text/javascript'>\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})</script>";
$o .= "<script type='text/javascript'>";
$o .= "\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})";
$o .= "</script>";
return $o;
}}
@ -248,27 +263,27 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
if(! function_exists('relative_date')) {
function relative_date($posted_date,$format = null) {
$localtime = datetime_convert('UTC',date_default_timezone_get(),$posted_date);
$localtime = datetime_convert('UTC',date_default_timezone_get(),$posted_date);
$abs = strtotime($localtime);
if (is_null($posted_date) || $posted_date === '0000-00-00 00:00:00' || $abs === False) {
if (is_null($posted_date) || $posted_date === '0000-00-00 00:00:00' || $abs === False) {
return t('never');
}
$etime = time() - $abs;
if ($etime < 1) {
return t('less than a second ago');
}
/*
$time_append = '';
if ($etime >= 86400) {
$time_append = ' ('.$localtime.')';
}
*/
$a = array( 12 * 30 * 24 * 60 * 60 => array( t('year'), t('years')),
30 * 24 * 60 * 60 => array( t('month'), t('months')),
7 * 24 * 60 * 60 => array( t('week'), t('weeks')),
@ -277,7 +292,7 @@ function relative_date($posted_date,$format = null) {
60 => array( t('minute'), t('minutes')),
1 => array( t('second'), t('seconds'))
);
foreach ($a as $secs => $str) {
$d = $etime / $secs;
if ($d >= 1) {
@ -295,13 +310,13 @@ function relative_date($posted_date,$format = null) {
// Returns age in years, given a date of birth,
// the timezone of the person whose date of birth is provided,
// and the timezone of the person viewing the result.
// Why? Bear with me. Let's say I live in Mittagong, Australia, and my
// Why? Bear with me. Let's say I live in Mittagong, Australia, and my
// birthday is on New Year's. You live in San Bruno, California.
// When exactly are you going to see my age increase?
// A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start
// celebrating and become a year older. If you wish me happy birthday
// on January 1 (San Bruno time), you'll be a day late.
// A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start
// celebrating and become a year older. If you wish me happy birthday
// on January 1 (San Bruno time), you'll be a day late.
function age($dob,$owner_tz = '',$viewer_tz = '') {
if(! intval($dob))
return 0;
@ -357,7 +372,7 @@ function get_first_dim($y,$m) {
// output a calendar for the given month, year.
// if $links are provided (array), e.g. $links[12] => 'http://mylink' ,
// date 12 will be linked appropriately. Today's date is also noted by
// date 12 will be linked appropriately. Today's date is also noted by
// altering td class.
// Months count from 1.
@ -376,7 +391,7 @@ function cal($y = 0,$m = 0, $links = false, $class='') {
'April','May','June',
'July','August','September',
'October','November','December'
);
);
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
@ -427,8 +442,8 @@ function cal($y = 0,$m = 0, $links = false, $class='') {
if($dow)
for($a = $dow; $a < 7; $a ++)
$o .= '<td>&nbsp;</td>';
$o .= '</tr></table>'."\r\n";
$o .= '</tr></table>'."\r\n";
return $o;
}}
@ -452,10 +467,10 @@ function update_contact_birthdays() {
*
* $bdtext is just a readable placeholder in case the event is shared
* with others. We will replace it during presentation to our $importer
* to contain a sparkle link and perhaps a photo.
* to contain a sparkle link and perhaps a photo.
*
*/
$bdtext = sprintf( t('%s\'s birthday'), $rr['name']);
$bdtext2 = sprintf( t('Happy Birthday %s'), ' [url=' . $rr['url'] . ']' . $rr['name'] . '[/url]') ;

View File

@ -62,7 +62,6 @@ function update_fail($update_id, $error_message){
*/
//try the logger
logger("CRITICAL: Database structure update failed: ".$retval);
break;
}
@ -642,6 +641,7 @@ function db_definition() {
"gender" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
"community" => array("type" => "tinyint(1)", "not null" => "1", "default" => "0"),
"network" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"addr" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"generation" => array("type" => "tinyint(3)", "not null" => "1", "default" => "0"),
"server_url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
),
@ -1382,6 +1382,20 @@ function db_definition() {
"username" => array("username"),
)
);
$database["workerqueue"] = array(
"fields" => array(
"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"parameter" => array("type" => "text", "not null" => "1"),
"priority" => array("type" => "tinyint(3) unsigned", "not null" => "1", "default" => "0"),
"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
"pid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
"executed" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
),
"indexes" => array(
"PRIMARY" => array("id"),
"created" => array("created"),
)
);
return($database);
}

View File

@ -2,6 +2,7 @@
require_once("boot.php");
require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once("include/ostatus.php");
function delivery_run(&$argv, &$argc){
global $a, $db;
@ -57,10 +58,11 @@ function delivery_run(&$argv, &$argc){
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load[0] . ' too high. Delivery deferred to next queue run.');
$load = current_load();
if($load) {
if(intval($load) > $maxsysload) {
logger('system: load ' . $load . ' too high. Delivery deferred to next queue run.');
return;
}
}
@ -340,9 +342,9 @@ function delivery_run(&$argv, &$argc){
$ssl_policy = get_config('system','ssl_policy');
fix_contact_ssl_policy($x[0],$ssl_policy);
// If we are setup as a soapbox we aren't accepting input from this person
// If we are setup as a soapbox we aren't accepting top level posts from this person
if($x[0]['page-flags'] == PAGE_SOAPBOX)
if (($x[0]['page-flags'] == PAGE_SOAPBOX) AND $top_level)
break;
require_once('library/simplepie/simplepie.inc');
@ -391,7 +393,8 @@ function delivery_run(&$argv, &$argc){
continue;
if(($top_level) && ($public_message) && ($item['author-link'] === $item['owner-link']) && (! $expire))
$slaps[] = atom_entry($item,'html',null,$owner,true);
$slaps[] = ostatus_salmon($item,$owner);
//$slaps[] = atom_entry($item,'html',null,$owner,true);
}
logger('notifier: slapdelivery: ' . $contact['name']);
@ -520,11 +523,16 @@ function delivery_run(&$argv, &$argc){
if((! $contact['pubkey']) && (! $public_message))
break;
if($target_item['verb'] === ACTIVITY_DISLIKE) {
// unsupported
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)) {
break 2;
}
}
elseif(($target_item['deleted']) && ($target_item['uri'] === $target_item['parent-uri'])) {
if(($target_item['deleted']) && ($target_item['uri'] === $target_item['parent-uri'])) {
// top-level retraction
logger('delivery: diaspora retract: ' . $loc);

View File

@ -110,6 +110,9 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
elseif($xmlbase->message) {
$ret = diaspora_message($importer,$xmlbase->message,$msg);
}
elseif($xmlbase->participation) {
$ret = diaspora_participation($importer,$xmlbase->participation);
}
else {
logger('diaspora_dispatch: unknown message type: ' . print_r($xmlbase,true));
}
@ -589,7 +592,7 @@ function diaspora_request($importer,$xml) {
// perhaps we were already sharing with this person. Now they're sharing with us.
// That makes us friends.
if($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) {
if($contact['rel'] == CONTACT_IS_FOLLOWER && in_array($importer['page-flags'], array(PAGE_FREELOVE))) {
q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
intval(CONTACT_IS_FRIEND),
intval($contact['id']),
@ -771,7 +774,7 @@ function diaspora_post_allow($importer,$contact, $is_comment = false) {
// perhaps we were already sharing with this person. Now they're sharing with us.
// That makes us friends.
// Normally this should have handled by getting a request - but this could get lost
if($contact['rel'] == CONTACT_IS_FOLLOWER && !in_array($importer['page-flags'], array(PAGE_COMMUNITY, PAGE_SOAPBOX))) {
if($contact['rel'] == CONTACT_IS_FOLLOWER && in_array($importer['page-flags'], array(PAGE_FREELOVE))) {
q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
intval(CONTACT_IS_FRIEND),
intval($contact['id']),
@ -1383,11 +1386,6 @@ function diaspora_asphoto($importer,$xml,$msg) {
}
function diaspora_comment($importer,$xml,$msg) {
$a = get_app();
@ -1507,16 +1505,27 @@ function diaspora_comment($importer,$xml,$msg) {
}
}
// Fetch the contact id - if we know this contact
$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc(normalise_link($person['url'])), intval($importer['uid']));
if ($r) {
$cid = $r[0]['id'];
$network = $r[0]['network'];
} else {
$cid = $contact['id'];
$network = NETWORK_DIASPORA;
}
$body = diaspora2bb($text);
$message_id = $diaspora_handle . ':' . $guid;
$datarray = array();
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
$datarray['contact-id'] = $cid;
$datarray['type'] = 'remote-comment';
$datarray['wall'] = $parent_item['wall'];
$datarray['network'] = NETWORK_DIASPORA;
$datarray['network'] = $network;
$datarray['verb'] = ACTIVITY_POST;
$datarray['gravity'] = GRAVITY_COMMENT;
$datarray['guid'] = $guid;
@ -1834,7 +1843,7 @@ function diaspora_message($importer,$xml,$msg) {
$author_signature = base64_decode($msg_author_signature);
$person = find_diaspora_person_by_handle($msg_diaspora_handle);
$person = find_diaspora_person_by_handle($msg_diaspora_handle);
if(is_array($person) && x($person,'pubkey'))
$key = $person['pubkey'];
else {
@ -1881,6 +1890,9 @@ function diaspora_message($importer,$xml,$msg) {
return;
}
function diaspora_participation($importer,$xml) {
logger("Unsupported message type 'participation' ".print_r($xml, true));
}
function diaspora_photo($importer,$xml,$msg,$attempt=1) {
@ -2149,13 +2161,24 @@ function diaspora_like($importer,$xml,$msg) {
EOT;
$bodyverb = t('%1$s likes %2$s\'s %3$s');
// Fetch the contact id - if we know this contact
$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc(normalise_link($person['url'])), intval($importer['uid']));
if ($r) {
$cid = $r[0]['id'];
$network = $r[0]['network'];
} else {
$cid = $contact['id'];
$network = NETWORK_DIASPORA;
}
$arr = array();
$arr['uri'] = $uri;
$arr['uid'] = $importer['uid'];
$arr['guid'] = $guid;
$arr['network'] = NETWORK_DIASPORA;
$arr['contact-id'] = $contact['id'];
$arr['network'] = $network;
$arr['contact-id'] = $cid;
$arr['type'] = 'activity';
$arr['wall'] = $parent_item['wall'];
$arr['gravity'] = GRAVITY_LIKE;
@ -2231,8 +2254,23 @@ function diaspora_retraction($importer,$xml) {
if($type === 'Person') {
require_once('include/Contact.php');
contact_remove($contact['id']);
}
elseif($type === 'Post') {
} elseif($type === 'StatusMessage') {
$guid = notags(unxmlify($xml->post_guid));
$r = q("SELECT * FROM `item` WHERE `guid` = '%s' AND `uid` = %d AND NOT `file` LIKE '%%[%%' LIMIT 1",
dbesc($guid),
intval($importer['uid'])
);
if(count($r)) {
if(link_compare($r[0]['author-link'],$contact['url'])) {
q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()),
intval($r[0]['id'])
);
delete_thread($r[0]['id'], $r[0]['parent-uri']);
}
}
} elseif($type === 'Post') {
$r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
dbesc('guid'),
intval($importer['uid'])
@ -2415,7 +2453,8 @@ function diaspora_profile($importer,$xml,$msg) {
$birthday = str_replace('1000','1901',$birthday);
$birthday = datetime_convert('UTC','UTC',$birthday,'Y-m-d');
if ($birthday != "")
$birthday = datetime_convert('UTC','UTC',$birthday,'Y-m-d');
// this is to prevent multiple birthday notifications in a single year
// if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year

View File

@ -28,10 +28,11 @@ function discover_poco_run(&$argv, &$argc){
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load[0] . ' too high. discover_poco deferred to next scheduled run.');
$load = current_load();
if($load) {
if(intval($load) > $maxsysload) {
logger('system: load ' . $load . ' too high. discover_poco deferred to next scheduled run.');
return;
}
}
@ -41,6 +42,8 @@ function discover_poco_run(&$argv, &$argc){
$mode = 1;
} elseif(($argc == 2) && ($argv[1] == "checkcontact")) {
$mode = 2;
} elseif(($argc == 2) && ($argv[1] == "suggestions")) {
$mode = 3;
} elseif ($argc == 1) {
$search = "";
$mode = 0;
@ -69,7 +72,9 @@ function discover_poco_run(&$argv, &$argc){
logger('start '.$search);
if (($mode == 2) AND get_config('system','poco_completion'))
if ($mode==3)
update_suggestions();
elseif (($mode == 2) AND get_config('system','poco_completion'))
discover_users();
elseif (($mode == 1) AND ($search != "") and get_config('system','poco_local_search'))
discover_directory($search);

View File

@ -20,7 +20,11 @@ function notification($params) {
$siteurl = $a->get_baseurl(true);
$thanks = t('Thank You,');
$sitename = $a->config['sitename'];
$site_admin = sprintf( t('%s Administrator'), $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;

View File

@ -3,7 +3,7 @@
require_once('include/bbcode.php');
require_once('include/map.php');
function format_event_html($ev) {
function format_event_html($ev, $simple = false) {
@ -12,6 +12,32 @@ function format_event_html($ev) {
$bd_format = t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8 AM
$event_start = (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['start'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
$ev['start'] , $bd_format)));
$event_end = (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['finish'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
$ev['finish'] , $bd_format )));
if ($simple) {
$o = "<h3>".bbcode($ev['summary'])."</h3>";
$o .= "<p>".bbcode($ev['desc'])."</p>";
$o .= "<h4>".t('Starts:')."</h4><p>".$event_start."</p>";
if(! $ev['nofinish'])
$o .= "<h4>".t('Finishes:')."</h4><p>".$event_end."</p>";
if(strlen($ev['location']))
$o .= "<h4>".t('Location:')."</h4><p>".$ev['location']."</p>";
return $o;
}
$o = '<div class="vevent">' . "\r\n";
@ -21,33 +47,25 @@ function format_event_html($ev) {
$o .= '<p class="event-start">' . t('Starts:') . ' <abbr class="dtstart" title="'
. datetime_convert('UTC','UTC',$ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['start'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
$ev['start'] , $bd_format)))
. '" >'.$event_start
. '</abbr></p>' . "\r\n";
if(! $ev['nofinish'])
$o .= '<p class="event-end" >' . t('Finishes:') . ' <abbr class="dtend" title="'
. datetime_convert('UTC','UTC',$ev['finish'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['finish'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
$ev['finish'] , $bd_format )))
. '" >'.$event_end
. '</abbr></p>' . "\r\n";
if(strlen($ev['location'])){
$o .= '<p class="event-location"> ' . t('Location:') . ' <span class="location">'
. bbcode($ev['location'])
$o .= '<p class="event-location"> ' . t('Location:') . ' <span class="location">'
. bbcode($ev['location'])
. '</span></p>' . "\r\n";
if (strpos($ev['location'], "[map")===False) {
$map = generate_named_map($ev['location']);
if ($map!==$ev['location']) $o.=$map;
}
}
$o .= '</div>' . "\r\n";
@ -137,7 +155,7 @@ function format_event_bbcode($ev) {
if(($ev['finish']) && (! $ev['nofinish']))
$o .= '[event-finish]' . $ev['finish'] . '[/event-finish]';
if($ev['location'])
$o .= '[event-location]' . $ev['location'] . '[/event-location]';
@ -200,11 +218,17 @@ function ev_compare($a,$b) {
if($date_a === $date_b)
return strcasecmp($a['desc'],$b['desc']);
return strcmp($date_a,$date_b);
}
function event_delete($event_id) {
if ($event_id == 0)
return;
q("DELETE FROM `event` WHERE `id` = %d", intval($event_id));
logger("Deleted event ".$event_id, LOGGER_DEBUG);
}
function event_store($arr) {
@ -324,7 +348,7 @@ function event_store($arr) {
}
else {
// New event. Store it.
// New event. Store it.
$r = q("INSERT INTO `event` ( `uid`,`cid`,`uri`,`created`,`edited`,`start`,`finish`,`summary`, `desc`,`location`,`type`,
`adjust`,`nofinish`,`allow_cid`,`allow_gid`,`deny_cid`,`deny_gid`)
@ -362,6 +386,7 @@ function event_store($arr) {
$item_arr['contact-id'] = $arr['cid'];
$item_arr['uri'] = $arr['uri'];
$item_arr['parent-uri'] = $arr['uri'];
$item_arr['guid'] = $arr['guid'];
$item_arr['type'] = 'activity';
$item_arr['wall'] = (($arr['cid']) ? 0 : 1);
$item_arr['contact-id'] = $contact['id'];

View File

@ -1,19 +1,54 @@
<?php
/*
* Features management
/**
* @file include/features.php *
* @brief Features management
*/
/**
* @brief check if feature is enabled
*
* return boolean
*/
function feature_enabled($uid,$feature) {
//return true;
$x = get_pconfig($uid,'feature',$feature);
if($x === false) {
$x = get_config('feature',$feature);
if($x === false)
$x = get_feature_default($feature);
}
$arr = array('uid' => $uid, 'feature' => $feature, 'enabled' => $x);
call_hooks('feature_enabled',$arr);
return($arr['enabled']);
}
/**
* @brief check if feature is enabled or disabled by default
*
* @param string $feature
* @return boolean
*/
function get_feature_default($feature) {
$f = get_features();
foreach($f as $cat) {
foreach($cat as $feat) {
if(is_array($feat) && $feat[0] === $feature)
return $feat[3];
}
}
return false;
}
/**
* @ brief get a list of all available features
* The array includes the setting group, the setting name,
* explainations for the setting and if it's enabled or disabled
* by default
*
* @return array
*/
function get_features() {
$arr = array(
@ -22,45 +57,53 @@ function get_features() {
'general' => array(
t('General Features'),
//array('expire', t('Content Expiration'), t('Remove old posts/comments after a period of time')),
array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles')),
array('multi_profiles', t('Multiple Profiles'), t('Ability to create multiple profiles'),false),
array('photo_location', t('Photo Location'), t('Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map.'),false),
),
// Post composition
'composition' => array(
t('Post Composition Features'),
array('richtext', t('Richtext Editor'), t('Enable richtext editor')),
array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them')),
array('aclautomention', t('Auto-mention Forums'), t('Add/remove mention when a fourm page is selected/deselected in ACL window.')),
array('richtext', t('Richtext Editor'), t('Enable richtext editor'),false),
array('preview', t('Post Preview'), t('Allow previewing posts and comments before publishing them'),false),
array('aclautomention', t('Auto-mention Forums'), t('Add/remove mention when a fourm page is selected/deselected in ACL window.'),false),
),
// Network sidebar widgets
'widgets' => array(
t('Network Sidebar Widgets'),
array('archives', t('Search by Date'), t('Ability to select posts by date ranges')),
array('groups', t('Group Filter'), t('Enable widget to display Network posts only from selected group')),
array('networks', t('Network Filter'), t('Enable widget to display Network posts only from selected network')),
array('savedsearch', t('Saved Searches'), t('Save search terms for re-use')),
array('archives', t('Search by Date'), t('Ability to select posts by date ranges'),false),
array('forumlist_widget', t('List Forums'), t('Enable widget to display the forums your are connected with'),true),
array('groups', t('Group Filter'), t('Enable widget to display Network posts only from selected group'),false),
array('networks', t('Network Filter'), t('Enable widget to display Network posts only from selected network'),false),
array('savedsearch', t('Saved Searches'), t('Save search terms for re-use'),false),
),
// Network tabs
'net_tabs' => array(
t('Network Tabs'),
array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on')),
array('new_tab', t('Network New Tab'), t('Enable tab to display only new Network posts (from the last 12 hours)')),
array('link_tab', t('Network Shared Links Tab'), t('Enable tab to display only Network posts with links in them')),
array('personal_tab', t('Network Personal Tab'), t('Enable tab to display only Network posts that you\'ve interacted on'),false),
array('new_tab', t('Network New Tab'), t('Enable tab to display only new Network posts (from the last 12 hours)'),false),
array('link_tab', t('Network Shared Links Tab'), t('Enable tab to display only Network posts with links in them'),false),
),
// Item tools
'tools' => array(
t('Post/Comment Tools'),
array('multi_delete', t('Multiple Deletion'), t('Select and delete multiple posts/comments at once')),
array('edit_posts', t('Edit Sent Posts'), t('Edit and correct posts and comments after sending')),
array('commtag', t('Tagging'), t('Ability to tag existing posts')),
array('categories', t('Post Categories'), t('Add categories to your posts')),
array('filing', t('Saved Folders'), t('Ability to file posts under folders')),
array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments')),
array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator')),
array('ignore_posts', t('Mute Post Notifications'), t('Ability to mute notifications for a thread')),
array('multi_delete', t('Multiple Deletion'), t('Select and delete multiple posts/comments at once'),false),
array('edit_posts', t('Edit Sent Posts'), t('Edit and correct posts and comments after sending'),false),
array('commtag', t('Tagging'), t('Ability to tag existing posts'),false),
array('categories', t('Post Categories'), t('Add categories to your posts'),false),
array('filing', t('Saved Folders'), t('Ability to file posts under folders'),false),
array('dislike', t('Dislike Posts'), t('Ability to dislike posts/comments')),
array('star_posts', t('Star Posts'), t('Ability to mark special posts with a star indicator'),false),
array('ignore_posts', t('Mute Post Notifications'), t('Ability to mute notifications for a thread'),false),
),
// Advanced Profile Settings
'advanced_profile' => array(
t('Advanced Profile Settings'),
array('forumlist_profile', t('List Forums'), t('Show visitors public community forums at the Advanced Profile Page'),false),
),
);

285
include/feed.php Normal file
View File

@ -0,0 +1,285 @@
<?php
require_once("include/html2bbcode.php");
require_once("include/items.php");
function feed_import($xml,$importer,&$contact, &$hub) {
$a = get_app();
logger("Import Atom/RSS feed", LOGGER_DEBUG);
if ($xml == "")
return;
$doc = new DOMDocument();
@$doc->loadXML($xml);
$xpath = new DomXPath($doc);
$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
$xpath->registerNamespace('dc', "http://purl.org/dc/elements/1.1/");
$xpath->registerNamespace('content', "http://purl.org/rss/1.0/modules/content/");
$xpath->registerNamespace('rdf', "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
$xpath->registerNamespace('rss', "http://purl.org/rss/1.0/");
$xpath->registerNamespace('media', "http://search.yahoo.com/mrss/");
$author = array();
// Is it RDF?
if ($xpath->query('/rdf:RDF/rss:channel')->length > 0) {
//$author["author-link"] = $xpath->evaluate('/rdf:RDF/rss:channel/rss:link/text()')->item(0)->nodeValue;
$author["author-name"] = $xpath->evaluate('/rdf:RDF/rss:channel/rss:title/text()')->item(0)->nodeValue;
if ($author["author-name"] == "")
$author["author-name"] = $xpath->evaluate('/rdf:RDF/rss:channel/rss:description/text()')->item(0)->nodeValue;
$entries = $xpath->query('/rdf:RDF/rss:item');
}
// Is it Atom?
if ($xpath->query('/atom:feed/atom:entry')->length > 0) {
//$self = $xpath->query("/atom:feed/atom:link[@rel='self']")->item(0)->attributes;
//if (is_object($self))
// foreach($self AS $attributes)
// if ($attributes->name == "href")
// $author["author-link"] = $attributes->textContent;
//if ($author["author-link"] == "") {
// $alternate = $xpath->query("/atom:feed/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-name"] = $xpath->evaluate('/atom:feed/atom:title/text()')->item(0)->nodeValue;
if ($author["author-name"] == "")
$author["author-name"] = $xpath->evaluate('/atom:feed/atom:subtitle/text()')->item(0)->nodeValue;
if ($author["author-name"] == "")
$author["author-name"] = $xpath->evaluate('/atom:feed/atom:author/atom:name/text()')->item(0)->nodeValue;
//$author["author-avatar"] = $xpath->evaluate('/atom:feed/atom:logo/text()')->item(0)->nodeValue;
$author["edited"] = $author["created"] = $xpath->query('/atom:feed/atom:updated/text()')->item(0)->nodeValue;
$author["app"] = $xpath->evaluate('/atom:feed/atom:generator/text()')->item(0)->nodeValue;
$entries = $xpath->query('/atom:feed/atom:entry');
}
// Is it RSS?
if ($xpath->query('/rss/channel')->length > 0) {
//$author["author-link"] = $xpath->evaluate('/rss/channel/link/text()')->item(0)->nodeValue;
$author["author-name"] = $xpath->evaluate('/rss/channel/title/text()')->item(0)->nodeValue;
//$author["author-avatar"] = $xpath->evaluate('/rss/channel/image/url/text()')->item(0)->nodeValue;
if ($author["author-name"] == "")
$author["author-name"] = $xpath->evaluate('/rss/channel/copyright/text()')->item(0)->nodeValue;
if ($author["author-name"] == "")
$author["author-name"] = $xpath->evaluate('/rss/channel/description/text()')->item(0)->nodeValue;
$author["edited"] = $author["created"] = $xpath->query('/rss/channel/pubDate/text()')->item(0)->nodeValue;
$author["app"] = $xpath->evaluate('/rss/channel/generator/text()')->item(0)->nodeValue;
$entries = $xpath->query('/rss/channel/item');
}
//if ($author["author-link"] == "")
$author["author-link"] = $contact["url"];
if ($author["author-name"] == "")
$author["author-name"] = $contact["name"];
//if ($author["author-avatar"] == "")
$author["author-avatar"] = $contact["thumb"];
$author["owner-link"] = $contact["url"];
$author["owner-name"] = $contact["name"];
$author["owner-avatar"] = $contact["thumb"];
$header = array();
$header["uid"] = $importer["uid"];
$header["network"] = NETWORK_FEED;
$header["type"] = "remote";
$header["wall"] = 0;
$header["origin"] = 0;
$header["gravity"] = GRAVITY_PARENT;
$header["private"] = 2;
$header["verb"] = ACTIVITY_POST;
$header["object-type"] = ACTIVITY_OBJ_NOTE;
$header["contact-id"] = $contact["id"];
if(!strlen($contact["notify"])) {
// one way feed - no remote comment ability
$header["last-child"] = 0;
}
if (!is_object($entries))
return;
$entrylist = array();
foreach ($entries AS $entry)
$entrylist[] = $entry;
foreach (array_reverse($entrylist) AS $entry) {
$item = array_merge($header, $author);
$item["title"] = $xpath->evaluate('atom:title/text()', $entry)->item(0)->nodeValue;
if ($item["title"] == "")
$item["title"] = $xpath->evaluate('title/text()', $entry)->item(0)->nodeValue;
if ($item["title"] == "")
$item["title"] = $xpath->evaluate('rss:title/text()', $entry)->item(0)->nodeValue;
$alternate = $xpath->query("atom:link[@rel='alternate']", $entry)->item(0)->attributes;
if (!is_object($alternate))
$alternate = $xpath->query("atom:link", $entry)->item(0)->attributes;
if (is_object($alternate))
foreach($alternate AS $attributes)
if ($attributes->name == "href")
$item["plink"] = $attributes->textContent;
if ($item["plink"] == "")
$item["plink"] = $xpath->evaluate('link/text()', $entry)->item(0)->nodeValue;
if ($item["plink"] == "")
$item["plink"] = $xpath->evaluate('rss:link/text()', $entry)->item(0)->nodeValue;
$item["plink"] = original_url($item["plink"]);
$item["uri"] = $xpath->evaluate('atom:id/text()', $entry)->item(0)->nodeValue;
if ($item["uri"] == "")
$item["uri"] = $xpath->evaluate('guid/text()', $entry)->item(0)->nodeValue;
if ($item["uri"] == "")
$item["uri"] = $item["plink"];
$item["parent-uri"] = $item["uri"];
$published = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
if ($published == "")
$published = $xpath->query('pubDate/text()', $entry)->item(0)->nodeValue;
if ($published == "")
$published = $xpath->query('dc:date/text()', $entry)->item(0)->nodeValue;
$updated = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
if ($updated == "")
$updated = $published;
if ($published != "")
$item["created"] = $published;
if ($updated != "")
$item["edited"] = $updated;
$creator = $xpath->query('author/text()', $entry)->item(0)->nodeValue;
if ($creator == "")
$creator = $xpath->query('atom:author/atom:name/text()', $entry)->item(0)->nodeValue;
if ($creator == "")
$creator = $xpath->query('dc:creator/text()', $entry)->item(0)->nodeValue;
if ($creator != "")
$item["author-name"] = $creator;
if ($pubDate != "")
$item["edited"] = $item["created"] = $pubDate;
$creator = $xpath->query('dc:creator/text()', $entry)->item(0)->nodeValue;
if ($creator != "")
$item["author-name"] = $creator;
//$item["object"] = $xml;
$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s', '%s')",
intval($importer["uid"]), dbesc($item["uri"]), dbesc(NETWORK_FEED), dbesc(NETWORK_DFRN));
if ($r) {
logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
continue;
}
// To-Do?
// <category>Ausland</category>
// <media:thumbnail width="152" height="76" url="http://www.taz.de/picture/667875/192/14388767.jpg"/>
$attachments = array();
$enclosures = $xpath->query("enclosure", $entry);
foreach ($enclosures AS $enclosure) {
$href = "";
$length = "";
$type = "";
$title = "";
foreach($enclosure->attributes AS $attributes) {
if ($attributes->name == "url")
$href = $attributes->textContent;
elseif ($attributes->name == "length")
$length = $attributes->textContent;
elseif ($attributes->name == "type")
$type = $attributes->textContent;
}
if(strlen($item["attach"]))
$item["attach"] .= ',';
$attachments[] = array("link" => $href, "type" => $type, "length" => $length);
$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'"[/attach]';
}
if ($contact["fetch_further_information"]) {
$preview = "";
// Handle enclosures and treat them as preview picture
foreach ($attachments AS $attachment)
if ($attachment["type"] == "image/jpeg")
$preview = $attachment["link"];
$item["body"] = $item["title"].add_page_info($item["plink"], false, $preview, ($contact["fetch_further_information"] == 2), $contact["ffi_keyword_blacklist"]);
$item["tag"] = add_page_keywords($item["plink"], false, $preview, ($contact["fetch_further_information"] == 2), $contact["ffi_keyword_blacklist"]);
$item["title"] = "";
$item["object-type"] = ACTIVITY_OBJ_BOOKMARK;
unset($item["attach"]);
} else {
$body = trim($xpath->evaluate('atom:content/text()', $entry)->item(0)->nodeValue);
if ($body == "")
$body = trim($xpath->evaluate('content:encoded/text()', $entry)->item(0)->nodeValue);
if ($body == "")
$body = trim($xpath->evaluate('description/text()', $entry)->item(0)->nodeValue);
if ($body == "")
$body = trim($xpath->evaluate('atom:summary/text()', $entry)->item(0)->nodeValue);
// remove the content of the title if it is identically to the body
// This helps with auto generated titles e.g. from tumblr
if (title_is_body($item["title"], $body))
$item["title"] = "";
$item["body"] = html2bbcode($body);
}
logger("Stored feed: ".print_r($item, true), LOGGER_DEBUG);
$notify = item_is_remote_self($contact, $item);
$id = item_store($item, false, $notify);
//print_r($item);
logger("Feed for contact ".$contact["url"]." stored under id ".$id);
}
}
?>

View File

@ -9,13 +9,13 @@ function update_contact($id) {
$r = q("SELECT `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `network` FROM `contact` WHERE `id` = %d", intval($id));
if (!$r)
return;
return false;
$ret = probe_url($r[0]["url"]);
// If probe_url fails the network code will be different
if ($ret["network"] != $r[0]["network"])
return;
return false;
$update = false;
@ -29,7 +29,7 @@ function update_contact($id) {
}
if (!$update)
return;
return true;
q("UPDATE `contact` SET `url` = '%s', `nurl` = '%s', `addr` = '%s', `alias` = '%s', `batch` = '%s', `notify` = '%s', `poll` = '%s', `poco` = '%s' WHERE `id` = %d",
dbesc($ret['url']),
@ -42,6 +42,8 @@ function update_contact($id) {
dbesc($ret['poco']),
intval($id)
);
return true;
}
//
@ -152,11 +154,7 @@ function new_contact($uid,$url,$interactive = false) {
$hidden = (($ret['network'] === NETWORK_MAIL) ? 1 : 0);
if($ret['network'] === NETWORK_MAIL) {
$writeable = 1;
}
if($ret['network'] === NETWORK_DIASPORA)
if(in_array($ret['network'], array(NETWORK_MAIL, NETWORK_DIASPORA)))
$writeable = 1;
// check if we already have a contact
@ -213,9 +211,7 @@ function new_contact($uid,$url,$interactive = false) {
return $result;
}
$new_relation = (($ret['network'] === NETWORK_MAIL) ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING);
if($ret['network'] === NETWORK_DIASPORA)
$new_relation = CONTACT_IS_FOLLOWER;
$new_relation = ((in_array($ret['network'], array(NETWORK_MAIL, NETWORK_DIASPORA))) ? CONTACT_IS_FRIEND : CONTACT_IS_SHARING);
// create contact record
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `batch`, `notify`, `poll`, `poco`, `name`, `nick`, `network`, `pubkey`, `rel`, `priority`,

182
include/forums.php Normal file
View File

@ -0,0 +1,182 @@
<?php
/**
* @file include/forums.php
* @brief Functions related to forum functionality *
*/
/**
* @brief Function to list all forums a user is connected with
*
* @param int $uid of the profile owner
* @param boolean $showhidden
* Show frorums which are not hidden
* @param boolean $lastitem
* Sort by lastitem
* @param boolean $showprivate
* Show private groups
*
* @returns array
* 'url' => forum url
* 'name' => forum name
* 'id' => number of the key from the array
* 'micro' => contact photo in format micro
*/
function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) {
$forumlist = array();
$order = (($showhidden) ? '' : ' AND NOT `hidden` ');
$order .= (($lastitem) ? ' ORDER BY `last-item` DESC ' : ' ORDER BY `name` ASC ');
$select = '`forum` ';
if ($showprivate) {
$select = '(`forum` OR `prv`)';
}
$contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro` FROM `contact`
WHERE `network`= 'dfrn' AND $select AND `uid` = %d
AND NOT `blocked` AND NOT `hidden` AND NOT `pending` AND NOT `archive`
AND `success_update` > `failure_update`
$order ",
intval($uid)
);
foreach($contacts as $contact) {
$forumlist[] = array(
'url' => $contact['url'],
'name' => $contact['name'],
'id' => $contact['id'],
'micro' => $contact['micro'],
);
}
return($forumlist);
}
/**
* @brief Forumlist widget
*
* Sidebar widget to show subcribed friendica forums. If activated
* in the settings, it appears at the notwork page sidebar
*
* @param int $uid
* @param int $cid
* The contact id which is used to mark a forum as "selected"
* @return string
*/
function widget_forumlist($uid,$cid = 0) {
if(! intval(feature_enabled(local_user(),'forumlist_widget')))
return;
$o = '';
//sort by last updated item
$lastitem = true;
$contacts = get_forumlist($uid,true,$lastitem, true);
$total = count($contacts);
$visible_forums = 10;
if(count($contacts)) {
$id = 0;
foreach($contacts as $contact) {
$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
$entry = array(
'url' => z_root() . '/network?f=&cid=' . $contact['id'],
'external_url' => z_root() . '/redir/' . $contact['id'],
'name' => $contact['name'],
'cid' => $contact['id'],
'selected' => $selected,
'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
'id' => ++$id,
);
$entries[] = $entry;
}
$tpl = get_markup_template('widget_forumlist.tpl');
$o .= replace_macros($tpl,array(
'$title' => t('Forums'),
'$forums' => $entries,
'$link_desc' => t('External link to forum'),
'$total' => $total,
'$visible_forums' => $visible_forums,
'$showmore' => t('show more'),
));
}
return $o;
}
/**
* @brief Format forumlist as contact block
*
* This function is used to show the forumlist in
* the advanced profile.
*
* @param int $uid
* @return string
*
*/
function forumlist_profile_advanced($uid) {
$profile = intval(feature_enabled($uid,'forumlist_profile'));
if(! $profile)
return;
$o = '';
// place holder in case somebody wants configurability
$show_total = 9999;
//don't sort by last updated item
$lastitem = false;
$contacts = get_forumlist($uid,false,$lastitem,false);
$total_shown = 0;
foreach($contacts as $contact) {
$forumlist .= micropro($contact,false,'forumlist-profile-advanced');
$total_shown ++;
if($total_shown == $show_total)
break;
}
if(count($contacts) > 0)
$o .= $forumlist;
return $o;
}
/**
* @brief count unread forum items
*
* Count unread items of connected forums and private groups
*
* @return array
* 'id' => contact id
* 'name' => contact/forum name
* 'count' => counted unseen forum items
*
*/
function forums_count_unseen() {
$r = q("SELECT `contact`.`id`, `contact`.`name`, COUNT(*) AS `count` FROM `item`
INNER JOIN `contact` ON `item`.`contact-id` = `contact`.`id`
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` AND `item`.`unseen`
AND `contact`.`network`= 'dfrn' AND (`contact`.`forum` OR `contact`.`prv`)
AND NOT `contact`.`blocked` AND NOT `contact`.`hidden`
AND NOT `contact`.`pending` AND NOT `contact`.`archive`
AND `contact`.`success_update` > `failure_update`
GROUP BY `contact`.`id` ",
intval(local_user())
);
return $r;
}

View File

@ -2,6 +2,7 @@
require_once "object/TemplateEngine.php";
require_once("library/Smarty/libs/Smarty.class.php");
require_once "include/plugin.php";
define('SMARTY3_TEMPLATE_FOLDER','templates');
@ -39,19 +40,19 @@ class FriendicaSmarty extends Smarty {
}
return $this->fetch('file:' . $this->filename);
}
}
class FriendicaSmartyEngine implements ITemplateEngine {
static $name ="smarty3";
public function __construct(){
if(!is_writable('view/smarty3/')){
echo "<b>ERROR:</b> folder <tt>view/smarty3/</tt> must be writable by webserver."; killme();
}
}
}
// ITemplateEngine interface
public function replace_macros($s, $r) {
$template = '';
@ -59,15 +60,24 @@ class FriendicaSmartyEngine implements ITemplateEngine {
$template = $s;
$s = new FriendicaSmarty();
}
// "middleware": inject variables into templates
$arr = array(
"template"=> basename($s->filename),
"vars" => $r
);
call_hooks("template_vars", $arr);
$r = $arr['vars'];
foreach($r as $key=>$value) {
if($key[0] === '$') {
$key = substr($key, 1);
}
$s->assign($key, $value);
}
return $s->parsed($template);
return $s->parsed($template);
}
public function get_template_file($file, $root=''){
$a = get_app();
$template_file = get_template_file($a, SMARTY3_TEMPLATE_FOLDER.'/'.$file, $root);

View File

@ -47,7 +47,7 @@ function gprobe_run(&$argv, &$argc){
$result = Cache::get("gprobe:".$urlparts["host"]);
if (!is_null($result)) {
$result = unserialize($result);
if ($result["network"] == NETWORK_FEED) {
if (in_array($result["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) {
logger("DDoS attempt detected for ".$urlparts["host"]." by ".$_SERVER["REMOTE_ADDR"].". server data: ".print_r($_SERVER, true), LOGGER_DEBUG);
return;
}

View File

@ -156,9 +156,11 @@ function group_add_member($uid,$name,$member,$gid = 0) {
function group_get_members($gid) {
$ret = array();
if(intval($gid)) {
$r = q("SELECT `group_member`.`contact-id`, `contact`.* FROM `group_member`
INNER JOIN `contact` ON `contact`.`id` = `group_member`.`contact-id`
WHERE `gid` = %d AND `group_member`.`uid` = %d ORDER BY `contact`.`name` ASC ",
$r = q("SELECT `group_member`.`contact-id`, `contact`.* FROM `group_member`
INNER JOIN `contact` ON `contact`.`id` = `group_member`.`contact-id`
WHERE `gid` = %d AND `group_member`.`uid` = %d AND
NOT `contact`.`self` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
ORDER BY `contact`.`name` ASC ",
intval($gid),
intval(local_user())
);
@ -171,14 +173,14 @@ function group_get_members($gid) {
function group_public_members($gid) {
$ret = 0;
if(intval($gid)) {
$r = q("SELECT `contact`.`id` AS `contact-id` FROM `group_member`
INNER JOIN `contact` ON `contact`.`id` = `group_member`.`contact-id`
WHERE `gid` = %d AND `group_member`.`uid` = %d
$r = q("SELECT `contact`.`id` AS `contact-id` FROM `group_member`
INNER JOIN `contact` ON `contact`.`id` = `group_member`.`contact-id`
WHERE `gid` = %d AND `group_member`.`uid` = %d
AND `contact`.`network` = '%s' AND `contact`.`notify` != '' ",
intval($gid),
intval(local_user()),
dbesc(NETWORK_OSTATUS)
);
);
if(count($r))
$ret = count($r);
}
@ -187,7 +189,7 @@ function group_public_members($gid) {
function mini_group_select($uid,$gid = 0) {
$grps = array();
$o = '';
@ -205,15 +207,26 @@ function mini_group_select($uid,$gid = 0) {
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
'$label' => t('Default privacy group for new contacts'),
'$groups' => $grps
'$groups' => $grps
));
return $o;
}
function group_side($every="contacts",$each="group",$edit = false, $group_id = 0, $cid = 0) {
/**
* @brief Create group sidebar widget
*
* @param string $every
* @param string $each
* @param string $editmode
* 'standard' => include link 'Edit groups'
* 'extended' => include link 'Create new group'
* 'full' => include link 'Create new group' and provide for each group a link to edit this group
* @param int $group_id
* @param int $cid
* @return string
*/
function group_side($every="contacts",$each="group",$editmode = "standard", $group_id = 0, $cid = 0) {
$o = '';
@ -237,13 +250,13 @@ function group_side($every="contacts",$each="group",$edit = false, $group_id = 0
$member_of = array();
if($cid) {
$member_of = groups_containing(local_user(),$cid);
}
}
if(count($r)) {
foreach($r as $rr) {
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
if ($edit) {
if ($editmode == "full") {
$groupedit = array(
'href' => "group/".$rr['id'],
'title' => t('edit'),
@ -267,14 +280,17 @@ function group_side($every="contacts",$each="group",$edit = false, $group_id = 0
$tpl = get_markup_template("group_side.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Groups'),
'$title' => t('Groups'),
'newgroup' => (($editmode == "extended") || ($editmode == "full") ? 1 : ''),
'$editgroupstext' => t('Edit groups'),
'grouppage' => "group/",
'$edittext' => t('Edit group'),
'$createtext' => t('Create a new group'),
'$creategroup' => t('Group Name: '),
'$form_security_token' => get_form_security_token("group_edit"),
'$creategroup' => t('Group Name: '),
'$form_security_token' => get_form_security_token("group_edit"),
'$ungrouped' => (($every === 'contacts') ? t('Contacts not in any group') : ''),
'$groups' => $groups,
'$add' => t('add'),
'$groups' => $groups,
'$add' => t('add'),
));
@ -324,3 +340,30 @@ function groups_containing($uid,$c) {
return $ret;
}
/**
* @brief count unread group items
*
* Count unread items of each groups
*
* @return array
* 'id' => group id
* 'name' => group name
* 'count' => counted unseen group items
*
*/
function groups_count_unseen() {
$r = q("SELECT `group`.`id`, `group`.`name`, COUNT(`item`.`id`) AS `count` FROM `group`, `group_member`, `item`
WHERE `group`.`uid` = %d
AND `item`.`uid` = %d
AND `item`.`unseen` AND `item`.`visible`
AND NOT `item`.`deleted`
AND `item`.`contact-id` = `group_member`.`contact-id`
AND `group_member`.`gid` = `group`.`id`
GROUP BY `group`.`id` ",
intval(local_user()),
intval(local_user())
);
return $r;
}

View File

@ -85,14 +85,16 @@ function deletenode(&$doc, $node)
$child->parentNode->removeChild($child);
}}
function _replace_code_cb($m){
return "<code>".str_replace("\n","<br>\n",$m[1]). "</code>";
}
function html2bbcode($message)
{
$message = str_replace("\r", "", $message);
$message = preg_replace_callback("|<pre><code>([^<]*)</code></pre>|ism", function($m) {
return "<code>".str_replace("\n","<br>\n",$m[1]). "</code>";
}, $message);
$message = preg_replace_callback("|<pre><code>([^<]*)</code></pre>|ism", "_replace_code_cb", $message);
$message = str_replace(array(
"<li><p>",

View File

@ -1,5 +1,11 @@
<?php
/**
* @file include/identity.php
*/
require_once('include/forums.php');
require_once('include/bbcode.php');
require_once("mod/proxy.php");
/**
*
@ -40,39 +46,9 @@ if(! function_exists('profile_load')) {
return;
}
if(remote_user() && count($_SESSION['remote'])) {
foreach($_SESSION['remote'] as $visitor) {
if($visitor['uid'] == $user[0]['uid']) {
$r = q("SELECT `profile-id` FROM `contact` WHERE `id` = %d LIMIT 1",
intval($visitor['cid'])
);
if(count($r))
$profile = $r[0]['profile-id'];
break;
}
}
}
$pdata = get_profiledata_by_nick($nickname, $user[0]['uid'], $profile);
$r = null;
if($profile) {
$profile_int = intval($profile);
$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `contact`.`avatar-date` AS picdate, `user`.* FROM `profile`
INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
WHERE `user`.`nickname` = '%s' AND `profile`.`id` = %d and `contact`.`self` = 1 LIMIT 1",
dbesc($nickname),
intval($profile_int)
);
}
if((!$r) && (!count($r))) {
$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `contact`.`avatar-date` AS picdate, `user`.* FROM `profile`
INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
WHERE `user`.`nickname` = '%s' AND `profile`.`is-default` = 1 and `contact`.`self` = 1 LIMIT 1",
dbesc($nickname)
);
}
if(($r === false) || (!count($r)) && !count($profiledata)) {
if(($pdata === false) || (!count($pdata)) && !count($profiledata)) {
logger('profile error: ' . $a->query_string, LOGGER_DEBUG);
notice( t('Requested profile is not available.') . EOL );
$a->error = 404;
@ -81,16 +57,16 @@ if(! function_exists('profile_load')) {
// fetch user tags if this isn't the default profile
if(!$r[0]['is-default']) {
$x = q("select `pub_keywords` from `profile` where uid = %d and `is-default` = 1 limit 1",
intval($r[0]['profile_uid'])
if(!$pdata['is-default']) {
$x = q("SELECT `pub_keywords` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
intval($pdata['profile_uid'])
);
if($x && count($x))
$r[0]['pub_keywords'] = $x[0]['pub_keywords'];
$pdata['pub_keywords'] = $x[0]['pub_keywords'];
}
$a->profile = $r[0];
$a->profile_uid = $r[0]['profile_uid'];
$a->profile = $pdata;
$a->profile_uid = $pdata['profile_uid'];
$a->profile['mobile-theme'] = get_pconfig($a->profile['profile_uid'], 'system', 'mobile_theme');
$a->profile['network'] = NETWORK_DFRN;
@ -133,7 +109,6 @@ if(! function_exists('profile_load')) {
else
$a->page['aside'] .= profile_sidebar($a->profile, $block);
/*if(! $block)
$a->page['aside'] .= contact_block();*/
@ -142,6 +117,58 @@ if(! function_exists('profile_load')) {
}
/**
* @brief Get all profil data of a local user
* If the viewer is an authenticated remote viewer, the profile displayed is the
* one that has been configured for his/her viewing in the Contact manager.
* Passing a non-zero profile ID can also allow a preview of a selected profile
* by the owner
*
* @param string $nickname
* @param int $uid
* @param int $profile
* ID of the profile
* @returns array
* Includes all available profile data
*/
function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) {
if(remote_user() && count($_SESSION['remote'])) {
foreach($_SESSION['remote'] as $visitor) {
if($visitor['uid'] == $uid) {
$r = q("SELECT `profile-id` FROM `contact` WHERE `id` = %d LIMIT 1",
intval($visitor['cid'])
);
if(count($r))
$profile = $r[0]['profile-id'];
break;
}
}
}
$r = null;
if($profile) {
$profile_int = intval($profile);
$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `contact`.`avatar-date` AS picdate, `contact`.`addr`, `user`.* FROM `profile`
INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
WHERE `user`.`nickname` = '%s' AND `profile`.`id` = %d AND `contact`.`self` = 1 LIMIT 1",
dbesc($nickname),
intval($profile_int)
);
}
if((!$r) && (!count($r))) {
$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `contact`.`avatar-date` AS picdate, `contact`.`addr`, `user`.* FROM `profile`
INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
WHERE `user`.`nickname` = '%s' AND `profile`.`is-default` = 1 AND `contact`.`self` = 1 LIMIT 1",
dbesc($nickname)
);
}
return $r[0];
}
/**
*
* Function: profile_sidebar
@ -156,8 +183,6 @@ if(! function_exists('profile_load')) {
* Exceptions: Returns empty string if passed $profile is wrong type or not populated
*
*/
if(! function_exists('profile_sidebar')) {
function profile_sidebar($profile, $block = 0) {
$a = get_app();
@ -165,7 +190,7 @@ if(! function_exists('profile_sidebar')) {
$o = '';
$location = false;
$address = false;
$pdesc = true;
// $pdesc = true;
if((! is_array($profile)) && (! count($profile)))
return $o;
@ -173,11 +198,7 @@ if(! function_exists('profile_sidebar')) {
$profile['picdate'] = urlencode($profile['picdate']);
if (($profile['network'] != "") AND ($profile['network'] != NETWORK_DFRN)) {
require_once('include/contact_selectors.php');
if ($profile['url'] != "")
$profile['network_name'] = '<a href="'.$profile['url'].'">'.network_to_name($profile['network'], $profile['url'])."</a>";
else
$profile['network_name'] = network_to_name($profile['network']);
$profile['network_name'] = format_network_name($profile['network'],$profile['url']);
} else
$profile['network_name'] = "";
@ -211,12 +232,17 @@ if(! function_exists('profile_sidebar')) {
}
if ($connect AND ($profile['network'] != NETWORK_DFRN) AND !isset($profile['remoteconnect']))
$connect = false;
$connect = false;
if (isset($profile['remoteconnect']))
$remoteconnect = $profile['remoteconnect'];
if( get_my_url() && $profile['unkmail'] && ($profile['uid'] != local_user()) )
if ($connect AND ($profile['network'] == NETWORK_DFRN) AND !isset($remoteconnect))
$subscribe_feed = t("Atom feed");
else
$subscribe_feed = false;
if(get_my_url() && $profile['unkmail'] && ($profile['uid'] != local_user()))
$wallmessage = t('Message');
else
$wallmessage = false;
@ -260,6 +286,16 @@ if(! function_exists('profile_sidebar')) {
);
}
// check if profile is a forum
if((intval($profile['page-flags']) == PAGE_COMMUNITY)
|| (intval($profile['page-flags']) == PAGE_PRVGROUP)
|| (intval($profile['forum']))
|| (intval($profile['prv']))
|| (intval($profile['community'])))
$account_type = t('Forum');
else
$account_type = "";
if((x($profile,'address') == 1)
|| (x($profile,'locality') == 1)
|| (x($profile,'region') == 1)
@ -306,7 +342,7 @@ if(! function_exists('profile_sidebar')) {
if(count($r))
$updated = date("c", strtotime($r[0]['updated']));
$r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 and `pending` = 0 AND `hidden` = 0 AND `archive` = 0
$r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0
AND `network` IN ('%s', '%s', '%s', '')",
intval($profile['uid']),
dbesc(NETWORK_DFRN),
@ -324,6 +360,15 @@ if(! function_exists('profile_sidebar')) {
$p[$k] = $v;
}
if (isset($p["about"]))
$p["about"] = bbcode($p["about"]);
if (isset($p["location"]))
$p["location"] = bbcode($p["location"]);
if (isset($p["photo"]))
$p["photo"] = proxy_url($p["photo"], false, PROXY_SIZE_SMALL);
if($a->theme['template_engine'] === 'internal')
$location = template_escape($location);
@ -332,10 +377,12 @@ if(! function_exists('profile_sidebar')) {
'$profile' => $p,
'$connect' => $connect,
'$remoteconnect' => $remoteconnect,
'$subscribe_feed' => $subscribe_feed,
'$wallmessage' => $wallmessage,
'$account_type' => $account_type,
'$location' => $location,
'$gender' => $gender,
'$pdesc' => $pdesc,
// '$pdesc' => $pdesc,
'$marital' => $marital,
'$homepage' => $homepage,
'$about' => $about,
@ -501,7 +548,7 @@ if(! function_exists('get_events')) {
}
$today = ((substr($strt,0,10) === datetime_convert('UTC',$a->timezone,'now','Y-m-d')) ? true : false);
$rr['title'] = $title;
$rr['description'] = $desciption;
$rr['date'] = day_translate(datetime_convert('UTC', $rr['adjust'] ? $a->timezone : 'UTC', $rr['start'], $bd_format)) . (($today) ? ' ' . t('[today]') : '');
@ -525,29 +572,30 @@ if(! function_exists('get_events')) {
function advanced_profile(&$a) {
$o = '';
$uid = $a->profile['uid'];
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
$o .= replace_macros(get_markup_template('section_title.tpl'),array(
'$title' => t('Profile')
));
if($a->profile['name']) {
$tpl = get_markup_template('profile_advanced.tpl');
$profile = array();
$profile['fullname'] = array( t('Full Name:'), $a->profile['name'] ) ;
if($a->profile['gender']) $profile['gender'] = array( t('Gender:'), $a->profile['gender'] );
if(($a->profile['dob']) && ($a->profile['dob'] != '0000-00-00')) {
$year_bd_format = t('j F, Y');
$short_bd_format = t('j F');
$val = ((intval($a->profile['dob']))
$val = ((intval($a->profile['dob']))
? day_translate(datetime_convert('UTC','UTC',$a->profile['dob'] . ' 00:00 +00:00',$year_bd_format))
: day_translate(datetime_convert('UTC','UTC','2001-' . substr($a->profile['dob'],5) . ' 00:00 +00:00',$short_bd_format)));
@ -556,7 +604,7 @@ function advanced_profile(&$a) {
}
if($age = age($a->profile['dob'],$a->profile['timezone'],'')) $profile['age'] = array( t('Age:'), $age );
if($a->profile['marital']) $profile['marital'] = array( t('Status:'), $a->profile['marital']);
@ -591,7 +639,7 @@ function advanced_profile(&$a) {
if($txt = prepare_text($a->profile['contact'])) $profile['contact'] = array( t('Contact information and Social Networks:'), $txt);
if($txt = prepare_text($a->profile['music'])) $profile['music'] = array( t('Musical interests:'), $txt);
if($txt = prepare_text($a->profile['book'])) $profile['book'] = array( t('Books, literature:'), $txt);
if($txt = prepare_text($a->profile['tv'])) $profile['tv'] = array( t('Television:'), $txt);
@ -599,14 +647,19 @@ function advanced_profile(&$a) {
if($txt = prepare_text($a->profile['film'])) $profile['film'] = array( t('Film/dance/culture/entertainment:'), $txt);
if($txt = prepare_text($a->profile['romance'])) $profile['romance'] = array( t('Love/Romance:'), $txt);
if($txt = prepare_text($a->profile['work'])) $profile['work'] = array( t('Work/employment:'), $txt);
if($txt = prepare_text($a->profile['education'])) $profile['education'] = array( t('School/education:'), $txt );
//show subcribed forum if it is enabled in the usersettings
if (feature_enabled($uid,'forumlist_profile')) {
$profile['forumlist'] = array( t('Forums:'), forumlist_profile_advanced($uid));
}
if ($a->profile['uid'] == local_user())
$profile['edit'] = array($a->get_baseurl(). '/profiles/'.$a->profile['id'], t('Edit profile'),"", t('Edit profile'));
return replace_macros($tpl, array(
'$title' => t('Profile'),
'$profile' => $profile
@ -664,14 +717,15 @@ if(! function_exists('profile_tabs')){
);
if ($is_owner){
$tabs[] = array(
'label' => t('Events'),
'url' => $a->get_baseurl() . '/events',
'sel' =>((!isset($tab)&&$a->argv[0]=='events')?'active':''),
'title' => t('Events and Calendar'),
'id' => 'events-tab',
'accesskey' => 'e',
);
if ($a->theme_events_in_profile)
$tabs[] = array(
'label' => t('Events'),
'url' => $a->get_baseurl() . '/events',
'sel' =>((!isset($tab)&&$a->argv[0]=='events')?'active':''),
'title' => t('Events and Calendar'),
'id' => 'events-tab',
'accesskey' => 'e',
);
$tabs[] = array(
'label' => t('Personal Notes'),
'url' => $a->get_baseurl() . '/notes',
@ -682,6 +736,16 @@ if(! function_exists('profile_tabs')){
);
}
if ((! $is_owner) && ((count($a->profile)) || (! $a->profile['hide-friends']))) {
$tabs[] = array(
'label' => t('Contacts'),
'url' => $a->get_baseurl() . '/viewcontacts/' . $nickname,
'sel' => ((!isset($tab)&&$a->argv[0]=='viewcontacts')?'active':''),
'title' => t('Contacts'),
'id' => 'viewcontacts-tab',
'accesskey' => 'k',
);
}
$arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs);
call_hooks('profile_tabs', $arr);
@ -709,7 +773,7 @@ function zrl_init(&$a) {
$result = Cache::get("gprobe:".$urlparts["host"]);
if (!is_null($result)) {
$result = unserialize($result);
if ($result["network"] == NETWORK_FEED) {
if (in_array($result["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) {
logger("DDoS attempt detected for ".$urlparts["host"]." by ".$_SERVER["REMOTE_ADDR"].". server data: ".print_r($_SERVER, true), LOGGER_DEBUG);
return;
}
@ -737,8 +801,8 @@ function zrl($s,$force = false) {
// Used from within PCSS themes to set theme parameters. If there's a
// puid request variable, that is the "page owner" and normally their theme
// settings take precedence; unless a local user sets the "always_my_theme"
// system pconfig, which means they don't want to see anybody else's theme
// settings take precedence; unless a local user sets the "always_my_theme"
// system pconfig, which means they don't want to see anybody else's theme
// settings except their own while on this site.
function get_theme_uid() {

View File

@ -13,6 +13,7 @@ require_once('include/threads.php');
require_once('include/socgraph.php');
require_once('include/plaintext.php');
require_once('include/ostatus.php');
require_once('include/feed.php');
require_once('mod/share.php');
require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
@ -1096,6 +1097,48 @@ function add_guid($item) {
dbesc($item["uri"]), dbesc($item["network"]));
}
// Adds a "lang" specification in a "postopts" element of given $arr,
// if possible and not already present.
// Expects "body" element to exist in $arr.
// TODO: add a parameter to request forcing override
function item_add_language_opt(&$arr) {
if (version_compare(PHP_VERSION, '5.3.0', '<')) return; // LanguageDetect.php not available ?
if ( x($arr, 'postopts') )
{
if ( strstr($arr['postopts'], 'lang=') )
{
// do not override
// TODO: add parameter to request overriding
return;
}
$postopts = $arr['postopts'];
}
else
{
$postopts = "";
}
require_once('library/langdet/Text/LanguageDetect.php');
$naked_body = preg_replace('/\[(.+?)\]/','',$arr['body']);
$l = new Text_LanguageDetect;
//$lng = $l->detectConfidence($naked_body);
//$arr['postopts'] = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : '');
$lng = $l->detect($naked_body, 3);
if (sizeof($lng) > 0) {
if ($postopts != "") $postopts .= '&'; // arbitrary separator, to be reviewed
$postopts .= 'lang=';
$sep = "";
foreach ($lng as $language => $score) {
$postopts .= $sep . $language.";".$score;
$sep = ':';
}
$arr['postopts'] = $postopts;
}
}
function item_store($arr,$force_parent = false, $notify = false, $dontcache = false) {
// If it is a posting where users should get notifications, then define it as wall posting
@ -1153,6 +1196,24 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
}
}
// Do we already have this item?
// We have to check several networks since Friendica posts could be repeated via OStatus (maybe Diasporsa as well)
if (in_array(trim($arr['network']), array(NETWORK_DIASPORA, NETWORK_DFRN, NETWORK_OSTATUS, ""))) {
$r = q("SELECT `id`, `network` FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `network` IN ('%s', '%s', '%s') LIMIT 1",
dbesc(trim($arr['uri'])),
intval($uid),
dbesc(NETWORK_DIASPORA),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_OSTATUS)
);
if ($r) {
// We only log the entries with a different user id than 0. Otherwise we would have too many false positives
if ($uid != 0)
logger("Item with uri ".$arr['uri']." already existed for user ".$uid." with id ".$r[0]["id"]." target network ".$r[0]["network"]." - new network: ".$arr['network']);
return($r[0]["id"]);
}
}
// If there is no guid then take the same guid that was taken before for the same uri
if ((trim($arr['guid']) == "") AND (trim($arr['uri']) != "") AND (trim($arr['network']) != "")) {
logger('item_store: checking for an existing guid for uri '.$arr['uri'], LOGGER_DEBUG);
@ -1185,43 +1246,23 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
//if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
// $arr['body'] = strip_tags($arr['body']);
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
require_once('library/langdet/Text/LanguageDetect.php');
$naked_body = preg_replace('/\[(.+?)\]/','',$arr['body']);
$l = new Text_LanguageDetect;
//$lng = $l->detectConfidence($naked_body);
//$arr['postopts'] = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : '');
$lng = $l->detect($naked_body, 3);
if (sizeof($lng) > 0) {
$postopts = "";
foreach ($lng as $language => $score) {
if ($postopts == "")
$postopts = "lang=";
else
$postopts .= ":";
$postopts .= $language.";".$score;
}
$arr['postopts'] = $postopts;
}
}
item_add_language_opt($arr);
if ($notify)
$guid_prefix = "";
else
$guid_prefix = $arr['network'];
else {
$parsed = parse_url($arr["author-link"]);
$guid_prefix = hash("crc32", $parsed["host"]);
}
$arr['wall'] = ((x($arr,'wall')) ? intval($arr['wall']) : 0);
$arr['guid'] = ((x($arr,'guid')) ? notags(trim($arr['guid'])) : get_guid(32, $guid_prefix));
$arr['uri'] = ((x($arr,'uri')) ? notags(trim($arr['uri'])) : $arr['guid']);
$arr['extid'] = ((x($arr,'extid')) ? notags(trim($arr['extid'])) : '');
$arr['author-name'] = ((x($arr,'author-name')) ? notags(trim($arr['author-name'])) : '');
$arr['author-name'] = ((x($arr,'author-name')) ? trim($arr['author-name']) : '');
$arr['author-link'] = ((x($arr,'author-link')) ? notags(trim($arr['author-link'])) : '');
$arr['author-avatar'] = ((x($arr,'author-avatar')) ? notags(trim($arr['author-avatar'])) : '');
$arr['owner-name'] = ((x($arr,'owner-name')) ? notags(trim($arr['owner-name'])) : '');
$arr['owner-name'] = ((x($arr,'owner-name')) ? trim($arr['owner-name']) : '');
$arr['owner-link'] = ((x($arr,'owner-link')) ? notags(trim($arr['owner-link'])) : '');
$arr['owner-avatar'] = ((x($arr,'owner-avatar')) ? notags(trim($arr['owner-avatar'])) : '');
$arr['created'] = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert());
@ -1229,8 +1270,8 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
$arr['commented'] = ((x($arr,'commented') !== false) ? datetime_convert('UTC','UTC',$arr['commented']) : datetime_convert());
$arr['received'] = ((x($arr,'received') !== false) ? datetime_convert('UTC','UTC',$arr['received']) : datetime_convert());
$arr['changed'] = ((x($arr,'changed') !== false) ? datetime_convert('UTC','UTC',$arr['changed']) : datetime_convert());
$arr['title'] = ((x($arr,'title')) ? notags(trim($arr['title'])) : '');
$arr['location'] = ((x($arr,'location')) ? notags(trim($arr['location'])) : '');
$arr['title'] = ((x($arr,'title')) ? trim($arr['title']) : '');
$arr['location'] = ((x($arr,'location')) ? trim($arr['location']) : '');
$arr['coord'] = ((x($arr,'coord')) ? notags(trim($arr['coord'])) : '');
$arr['last-child'] = ((x($arr,'last-child')) ? intval($arr['last-child']) : 0 );
$arr['visible'] = ((x($arr,'visible') !== false) ? intval($arr['visible']) : 1 );
@ -1266,11 +1307,24 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
}
if ($arr['network'] == "") {
$r = q("SELECT `network` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($arr['contact-id']),
$r = q("SELECT `network` FROM `contact` WHERE `network` IN ('%s', '%s', '%s') AND `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS),
dbesc(normalise_link($arr['author-link'])),
intval($arr['uid'])
);
if(!count($r))
$r = q("SELECT `network` FROM `gcontact` WHERE `network` IN ('%s', '%s', '%s') AND `nurl` = '%s' LIMIT 1",
dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS),
dbesc(normalise_link($arr['author-link']))
);
if(!count($r))
$r = q("SELECT `network` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($arr['contact-id']),
intval($arr['uid'])
);
if(count($r))
$arr['network'] = $r[0]["network"];
@ -1391,9 +1445,10 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
}
}
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1",
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `network` IN ('%s', '%s') AND `uid` = %d LIMIT 1",
dbesc($arr['uri']),
dbesc($arr['network']),
dbesc(NETWORK_DFRN),
intval($arr['uid'])
);
if($r && count($r)) {
@ -1454,13 +1509,24 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
// And restore it
$arr = $unescaped;
// find the item we just created
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC ",
// find the item that we just created
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `network` = '%s' ORDER BY `id` ASC",
dbesc($arr['uri']),
intval($arr['uid'])
intval($arr['uid']),
dbesc($arr['network'])
);
if(count($r)) {
if(count($r) > 1) {
// There are duplicates. Keep the oldest one, delete the others
logger('item_store: duplicated post occurred. Removing newer duplicates. uri = '.$arr['uri'].' uid = '.$arr['uid']);
q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `network` = '%s' AND `id` > %d",
dbesc($arr['uri']),
intval($arr['uid']),
dbesc($arr['network']),
intval($r[0]["id"])
);
return 0;
} elseif(count($r)) {
// Store the guid and other relevant data
add_guid($arr);
@ -1493,14 +1559,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
logger('item_store: could not locate created item');
return 0;
}
if(count($r) > 1) {
logger('item_store: duplicated post occurred. Removing duplicates. uri = '.$arr['uri'].' uid = '.$arr['uid']);
q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `id` != %d ",
dbesc($arr['uri']),
intval($arr['uid']),
intval($current_post)
);
}
if((! $parent_id) || ($arr['parent-uri'] === $arr['uri']))
$parent_id = $current_post;
@ -2265,15 +2323,22 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if ($contact['network'] === NETWORK_OSTATUS) {
if ($pass < 2) {
// Test - remove before flight
//$tempfile = tempnam(get_temppath(), "ostatus");
//$tempfile = tempnam(get_temppath(), "ostatus2");
//file_put_contents($tempfile, $xml);
logger("Consume OStatus messages ", LOGGER_DEBUG);
ostatus_import($xml,$importer,$contact, $hub);
}
return;
}
if ($contact['network'] === NETWORK_FEED) {
if ($pass < 2) {
logger("Consume feeds", LOGGER_DEBUG);
feed_import($xml,$importer,$contact, $hub);
}
return;
}
require_once('library/simplepie/simplepie.inc');
require_once('include/contact_selectors.php');
@ -2342,85 +2407,45 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$contact_updated = $photo_timestamp;
require_once("include/Photo.php");
$photo_failure = false;
$have_photo = false;
$photos = import_profile_photo($photo_url,$contact['uid'],$contact['id']);
$r = q("SELECT `resource-id` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d LIMIT 1",
intval($contact['id']),
intval($contact['uid'])
q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'
WHERE `uid` = %d AND `id` = %d AND NOT `self`",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
intval($contact['uid']),
intval($contact['id'])
);
if(count($r)) {
$resource_id = $r[0]['resource-id'];
$have_photo = true;
}
else {
$resource_id = photo_new_resource();
}
$img_str = fetch_url($photo_url,true);
// guess mimetype from headers or filename
$type = guess_image_type($photo_url,true);
$img = new Photo($img_str, $type);
if($img->is_valid()) {
if($have_photo) {
q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `contact-id` = %d AND `uid` = %d",
dbesc($resource_id),
intval($contact['id']),
intval($contact['uid'])
);
}
$img->scaleImageSquare(175);
$hash = $resource_id;
$r = $img->store($contact['uid'], $contact['id'], $hash, basename($photo_url), 'Contact Photos', 4);
$img->scaleImage(80);
$r = $img->store($contact['uid'], $contact['id'], $hash, basename($photo_url), 'Contact Photos', 5);
$img->scaleImage(48);
$r = $img->store($contact['uid'], $contact['id'], $hash, basename($photo_url), 'Contact Photos', 6);
$a = get_app();
q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'
WHERE `uid` = %d AND `id` = %d",
dbesc(datetime_convert()),
dbesc($a->get_baseurl() . '/photo/' . $hash . '-4.'.$img->getExt()),
dbesc($a->get_baseurl() . '/photo/' . $hash . '-5.'.$img->getExt()),
dbesc($a->get_baseurl() . '/photo/' . $hash . '-6.'.$img->getExt()),
intval($contact['uid']),
intval($contact['id'])
);
}
}
if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
if ($name_updated > $contact_updated)
$contact_updated = $name_updated;
$r = q("select * from contact where uid = %d and id = %d limit 1",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1",
intval($contact['uid']),
intval($contact['id'])
);
$x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d",
$x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d AND `name` != '%s' AND NOT `self`",
dbesc(notags(trim($new_name))),
dbesc(datetime_convert()),
intval($contact['uid']),
intval($contact['id'])
intval($contact['id']),
dbesc(notags(trim($new_name)))
);
// do our best to update the name on content items
if(count($r)) {
q("update item set `author-name` = '%s' where `author-name` = '%s' and `author-link` = '%s' and uid = %d",
if(count($r) AND (notags(trim($new_name)) != $r[0]['name'])) {
q("UPDATE `item` SET `author-name` = '%s' WHERE `author-name` = '%s' AND `author-link` = '%s' AND `uid` = %d AND `author-name` != '%s'",
dbesc(notags(trim($new_name))),
dbesc($r[0]['name']),
dbesc($r[0]['url']),
intval($contact['uid'])
intval($contact['uid']),
dbesc(notags(trim($new_name)))
);
}
}
@ -2519,6 +2544,11 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if(! $item['deleted'])
logger('consume_feed: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG);
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)) {
$xo = parse_xml_string($item['object'],false);
$xt = parse_xml_string($item['target'],false);
@ -2726,7 +2756,11 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
$datarray['parent-uri'] = $parent_uri;
$datarray['uid'] = $importer['uid'];
$datarray['contact-id'] = $contact['id'];
if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) {
if(($datarray['verb'] === ACTIVITY_LIKE)
|| ($datarray['verb'] === ACTIVITY_DISLIKE)
|| ($datarray['verb'] === ACTIVITY_ATTEND)
|| ($datarray['verb'] === ACTIVITY_ATTENDNO)
|| ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
// only one like or dislike per person
@ -2806,11 +2840,12 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
$ev = bbtoevent($datarray['body']);
if(x($ev,'desc') && x($ev,'start')) {
if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
$ev['uid'] = $importer['uid'];
$ev['uri'] = $item_id;
$ev['edited'] = $datarray['edited'];
$ev['private'] = $datarray['private'];
$ev['guid'] = $datarray['guid'];
if(is_array($contact))
$ev['cid'] = $contact['id'];
@ -3070,85 +3105,46 @@ function local_delivery($importer,$data) {
logger('local_delivery: Updating photo for ' . $importer['name']);
require_once("include/Photo.php");
$photo_failure = false;
$have_photo = false;
$r = q("SELECT `resource-id` FROM `photo` WHERE `contact-id` = %d AND `uid` = %d LIMIT 1",
intval($importer['id']),
intval($importer['importer_uid'])
$photos = import_profile_photo($photo_url,$importer['importer_uid'],$importer['id']);
q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'
WHERE `uid` = %d AND `id` = %d AND NOT `self`",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
intval($importer['importer_uid']),
intval($importer['id'])
);
if(count($r)) {
$resource_id = $r[0]['resource-id'];
$have_photo = true;
}
else {
$resource_id = photo_new_resource();
}
$img_str = fetch_url($photo_url,true);
// guess mimetype from headers or filename
$type = guess_image_type($photo_url,true);
$img = new Photo($img_str, $type);
if($img->is_valid()) {
if($have_photo) {
q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `contact-id` = %d AND `uid` = %d",
dbesc($resource_id),
intval($importer['id']),
intval($importer['importer_uid'])
);
}
$img->scaleImageSquare(175);
$hash = $resource_id;
$r = $img->store($importer['importer_uid'], $importer['id'], $hash, basename($photo_url), 'Contact Photos', 4);
$img->scaleImage(80);
$r = $img->store($importer['importer_uid'], $importer['id'], $hash, basename($photo_url), 'Contact Photos', 5);
$img->scaleImage(48);
$r = $img->store($importer['importer_uid'], $importer['id'], $hash, basename($photo_url), 'Contact Photos', 6);
$a = get_app();
q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'
WHERE `uid` = %d AND `id` = %d",
dbesc(datetime_convert()),
dbesc($a->get_baseurl() . '/photo/' . $hash . '-4.'.$img->getExt()),
dbesc($a->get_baseurl() . '/photo/' . $hash . '-5.'.$img->getExt()),
dbesc($a->get_baseurl() . '/photo/' . $hash . '-6.'.$img->getExt()),
intval($importer['importer_uid']),
intval($importer['id'])
);
}
}
if(($name_updated) && (strlen($new_name)) && ($name_updated > $importer['name-date'])) {
if ($name_updated > $contact_updated)
$contact_updated = $name_updated;
$r = q("select * from contact where uid = %d and id = %d limit 1",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1",
intval($importer['importer_uid']),
intval($importer['id'])
);
$x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d",
$x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d AND `name` != '%s' AND NOT `self`",
dbesc(notags(trim($new_name))),
dbesc(datetime_convert()),
intval($importer['importer_uid']),
intval($importer['id'])
intval($importer['id']),
dbesc(notags(trim($new_name)))
);
// do our best to update the name on content items
if(count($r)) {
q("update item set `author-name` = '%s' where `author-name` = '%s' and `author-link` = '%s' and uid = %d",
if(count($r) AND (notags(trim($new_name)) != $r[0]['name'])) {
q("UPDATE `item` SET `author-name` = '%s' WHERE `author-name` = '%s' AND `author-link` = '%s' AND `uid` = %d AND `author-name` != '%s'",
dbesc(notags(trim($new_name))),
dbesc($r[0]['name']),
dbesc($r[0]['url']),
intval($importer['importer_uid'])
intval($importer['importer_uid']),
dbesc(notags(trim($new_name)))
);
}
}
@ -3500,6 +3496,11 @@ function local_delivery($importer,$data) {
logger('local_delivery: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG);
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)) {
$xo = parse_xml_string($item['object'],false);
$xt = parse_xml_string($item['target'],false);
@ -3713,7 +3714,11 @@ function local_delivery($importer,$data) {
$datarray['owner-avatar'] = $own[0]['thumb'];
$datarray['contact-id'] = $importer['id'];
if(($datarray['verb'] === ACTIVITY_LIKE) || ($datarray['verb'] === ACTIVITY_DISLIKE)) {
if(($datarray['verb'] === ACTIVITY_LIKE)
|| ($datarray['verb'] === ACTIVITY_DISLIKE)
|| ($datarray['verb'] === ACTIVITY_ATTEND)
|| ($datarray['verb'] === ACTIVITY_ATTENDNO)
|| ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
$is_like = true;
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
@ -3902,7 +3907,11 @@ function local_delivery($importer,$data) {
$datarray['parent-uri'] = $parent_uri;
$datarray['uid'] = $importer['importer_uid'];
$datarray['contact-id'] = $importer['id'];
if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) {
if(($datarray['verb'] === ACTIVITY_LIKE)
|| ($datarray['verb'] === ACTIVITY_DISLIKE)
|| ($datarray['verb'] === ACTIVITY_ATTEND)
|| ($datarray['verb'] === ACTIVITY_ATTENDNO)
|| ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
$datarray['type'] = 'activity';
$datarray['gravity'] = GRAVITY_LIKE;
// only one like or dislike per person
@ -4022,12 +4031,13 @@ function local_delivery($importer,$data) {
if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
$ev = bbtoevent($datarray['body']);
if(x($ev,'desc') && x($ev,'start')) {
if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
$ev['cid'] = $importer['id'];
$ev['uid'] = $importer['uid'];
$ev['uri'] = $item_id;
$ev['edited'] = $datarray['edited'];
$ev['private'] = $datarray['private'];
$ev['guid'] = $datarray['guid'];
$r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($item_id),
@ -4187,14 +4197,13 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
);
}
// send email notification to owner?
}
else {
} else {
// create contact record
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,
`blocked`, `readonly`, `pending`, `writable` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, 1 ) ",
$r = q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,
`blocked`, `readonly`, `pending`, `writable`)
VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, 1)",
intval($importer['uid']),
dbesc(datetime_convert()),
dbesc($url),
@ -4209,27 +4218,38 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
intval($importer['uid']),
dbesc($url)
);
if(count($r))
if(count($r)) {
$contact_record = $r[0];
// create notification
$hash = random_string();
$photos = import_profile_photo($photo,$importer["uid"],$contact_record["id"]);
if(is_array($contact_record)) {
$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `hash`, `datetime`)
VALUES ( %d, %d, 0, 0, '%s', '%s' )",
intval($importer['uid']),
intval($contact_record['id']),
dbesc($hash),
dbesc(datetime_convert())
);
q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `id` = %d",
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
intval($contact_record["id"])
);
}
$r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
intval($importer['uid'])
);
$a = get_app();
if(count($r)) {
if(count($r) AND !in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE))) {
// create notification
$hash = random_string();
if(is_array($contact_record)) {
$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `hash`, `datetime`)
VALUES ( %d, %d, 0, 0, '%s', '%s' )",
intval($importer['uid']),
intval($contact_record['id']),
dbesc($hash),
dbesc(datetime_convert())
);
}
if(intval($r[0]['def_gid'])) {
require_once('include/group.php');
@ -4237,7 +4257,7 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
}
if(($r[0]['notify-flags'] & NOTIFY_INTRO) &&
in_array($r[0]['page-flags'], array(PAGE_NORMAL, PAGE_SOAPBOX, PAGE_FREELOVE))) {
in_array($r[0]['page-flags'], array(PAGE_NORMAL))) {
notification(array(
'type' => NOTIFY_INTRO,
@ -4255,7 +4275,13 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
));
}
} elseif (count($r) AND in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE))) {
$r = q("UPDATE `contact` SET `pending` = 0 WHERE `uid` = %d AND `url` = '%s' AND `pending` LIMIT 1",
intval($importer['uid']),
dbesc($url)
);
}
}
}
@ -4329,7 +4355,7 @@ function subscribe_to_hub($url,$importer,$contact,$hubmode = 'subscribe') {
}
function atom_author($tag,$name,$uri,$h,$w,$photo) {
function atom_author($tag,$name,$uri,$h,$w,$photo,$geo) {
$o = '';
if(! $tag)
return $o;
@ -4347,6 +4373,10 @@ function atom_author($tag,$name,$uri,$h,$w,$photo) {
$o .= "\t".'<link rel="avatar" type="image/jpeg" media:width="' . $w . '" media:height="' . $h . '" href="' . $photo . '" />' . "\r\n";
if ($tag == "author") {
if($geo)
$o .= '<georss:point>'.xmlify($geo).'</georss:point>'."\r\n";
$r = q("SELECT `profile`.`locality`, `profile`.`region`, `profile`.`country-name`,
`profile`.`name`, `profile`.`pub_keywords`, `profile`.`about`,
`profile`.`homepage`,`contact`.`nick` FROM `profile`
@ -4372,7 +4402,7 @@ function atom_author($tag,$name,$uri,$h,$w,$photo) {
$o .= "\t<poco:preferredUsername>".xmlify($r[0]["nick"])."</poco:preferredUsername>\r\n";
$o .= "\t<poco:displayName>".xmlify($r[0]["name"])."</poco:displayName>\r\n";
$o .= "\t<poco:note>".xmlify($r[0]["about"])."</poco:note>\r\n";
$o .= "\t<poco:note>".xmlify(bbcode($r[0]["about"]))."</poco:note>\r\n";
$o .= "\t<poco:address>\r\n";
$o .= "\t\t<poco:formatted>".xmlify($location)."</poco:formatted>\r\n";
$o .= "\t</poco:address>\r\n";
@ -4410,11 +4440,11 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
$o = "\r\n\r\n<entry>\r\n";
if(is_array($author))
$o .= atom_author('author',$author['name'],$author['url'],80,80,$author['thumb']);
$o .= atom_author('author',$author['name'],$author['url'],80,80,$author['thumb'], $item['coord']);
else
$o .= atom_author('author',(($item['author-name']) ? $item['author-name'] : $item['name']),(($item['author-link']) ? $item['author-link'] : $item['url']),80,80,(($item['author-avatar']) ? $item['author-avatar'] : $item['thumb']));
$o .= atom_author('author',(($item['author-name']) ? $item['author-name'] : $item['name']),(($item['author-link']) ? $item['author-link'] : $item['url']),80,80,(($item['author-avatar']) ? $item['author-avatar'] : $item['thumb']), $item['coord']);
if(strlen($item['owner-name']))
$o .= atom_author('dfrn:owner',$item['owner-name'],$item['owner-link'],80,80,$item['owner-avatar']);
$o .= atom_author('dfrn:owner',$item['owner-name'],$item['owner-link'],80,80,$item['owner-avatar'], $item['coord']);
if(($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
$parent = q("SELECT `guid` FROM `item` WHERE `id` = %d", intval($item["parent"]));
@ -4491,7 +4521,8 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) {
//$o .= "\t".'<link rel="self" type="application/atom+xml" href="'.xmlify($a->get_baseurl().'/api/statuses/show/'.$item['id'].'.atom').'"/>'."\r\n";
//$o .= "\t".'<link rel="edit" type="application/atom+xml" href="'.xmlify($a->get_baseurl().'/api/statuses/show/'.$item['id'].'.atom').'"/>'."\r\n";
$o .= item_get_attachment($item);
// Deactivated since it was meant only for OStatus
//$o .= item_get_attachment($item);
$o .= item_getfeedattach($item);
@ -4656,7 +4687,7 @@ function item_getfeedtags($item) {
if($cnt) {
for($x = 0; $x < $cnt; $x ++) {
if($matches[1][$x])
$ret[] = array('#',$matches[1][$x], $matches[2][$x]);
$ret[$matches[2][$x]] = array('#',$matches[1][$x], $matches[2][$x]);
}
}
$matches = false;

View File

@ -27,7 +27,6 @@ function nav(&$a) {
$a->page['nav'] .= replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
'$langselector' => lang_selector(),
'$sitelocation' => $nav_info['sitelocation'],
'$nav' => $nav_info['nav'],
'$banner' => $nav_info['banner'],
@ -48,7 +47,7 @@ function nav_info(&$a) {
/**
*
* Our network is distributed, and as you visit friends some of the
* 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.
* Display the current site location as a navigation aid.
*
@ -138,6 +137,8 @@ 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'));
$nav['directory'] = array($gdirpath, t('Directory'), "", t('People directory'));
$nav['about'] = Array('friendica', t('Information'), "", t('Information about this friendica instance'));
@ -205,7 +206,7 @@ function nav_info(&$a) {
$banner = get_config('system','banner');
if($banner === false)
if($banner === false)
$banner .= '<a href="http://friendica.com"><img id="logo-img" src="images/friendica-32.png" alt="logo" /></a><span id="logo-text"><a href="http://friendica.com">Friendica</a></span>';
call_hooks('nav_info', $nav);
@ -222,7 +223,7 @@ function nav_info(&$a) {
/*
* Set a menu item in navbar as selected
*
*
*/
function nav_set_selected($item){
$a = get_app();
@ -238,6 +239,7 @@ function nav_set_selected($item){
'settings' => null,
'contacts' => null,
'manage' => null,
'events' => null,
'register' => null,
);
$a->nav_sel[$item] = 'selected';

View File

@ -86,10 +86,9 @@ function z_fetch_url($url,$binary = false, &$redirects = 0, $opts=array()) {
if(x($opts,'nobody')){
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
}
if(intval($timeout)) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
}
else {
if(x($opts,'timeout')){
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
} else {
$curl_time = intval(get_config('system','curl_timeout'));
@curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
}
@ -309,16 +308,25 @@ function xml_status($st, $message = '') {
if(! function_exists('http_status_exit')) {
function http_status_exit($val) {
function http_status_exit($val, $description = array()) {
$err = '';
if($val >= 400)
if($val >= 400) {
$err = 'Error';
if (!isset($description["title"]))
$description["title"] = $err." ".$val;
}
if($val >= 200 && $val < 300)
$err = 'OK';
logger('http_status_exit ' . $val);
header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err);
if (isset($description["title"])) {
$tpl = get_markup_template('http_status.tpl');
echo replace_macros($tpl, array('$title' => $description["title"],
'$description' => $description["description"]));
}
killme();
}}

View File

@ -4,6 +4,7 @@ require_once('include/queue_fn.php');
require_once('include/html2plain.php');
require_once("include/Scrape.php");
require_once('include/diaspora.php');
require_once("include/ostatus.php");
/*
* This file was at one time responsible for doing all deliveries, but this caused
@ -529,7 +530,8 @@ function notifier_run(&$argv, &$argc){
unset($photos);
} else {
$slap = atom_entry($target_item,'html',null,$owner,false);
$slap = ostatus_salmon($target_item,$owner);
//$slap = atom_entry($target_item,'html',null,$owner,false);
if($followup) {
foreach($items as $item) { // there is only one item
@ -569,7 +571,8 @@ function notifier_run(&$argv, &$argc){
$atom .= atom_entry($item,'text',null,$owner,true);
if(($top_level) && ($public_message) && ($item['author-link'] === $item['owner-link']) && (! $expire))
$slaps[] = atom_entry($item,'html',null,$owner,true);
$slaps[] = ostatus_salmon($item,$owner);
//$slaps[] = atom_entry($item,'html',null,$owner,true);
}
}
}
@ -615,6 +618,10 @@ function notifier_run(&$argv, &$argc){
$interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker"))
$interval = false;
// delivery loop
if(count($r)) {
@ -634,7 +641,7 @@ function notifier_run(&$argv, &$argc){
// This controls the number of deliveries to execute with each separate delivery process.
// By default we'll perform one delivery per process. Assuming a hostile shared hosting
// provider, this provides the greatest chance of deliveries if processes start getting
// provider, this provides the greatest chance of deliveries if processes start getting
// killed. We can also space them out with the delivery_interval to also help avoid them
// getting whacked.
@ -642,8 +649,10 @@ function notifier_run(&$argv, &$argc){
// together into a single process. This will reduce the overall number of processes
// spawned for each delivery, but they will run longer.
// When using the workerqueue, we don't need this functionality.
$deliveries_per_process = intval(get_config('system','delivery_batch_count'));
if($deliveries_per_process <= 0)
if (($deliveries_per_process <= 0) OR get_config("system", "worker"))
$deliveries_per_process = 1;
$this_batch = array();
@ -728,9 +737,9 @@ function notifier_run(&$argv, &$argc){
$ssl_policy = get_config('system','ssl_policy');
fix_contact_ssl_policy($x[0],$ssl_policy);
// If we are setup as a soapbox we aren't accepting input from this person
// If we are setup as a soapbox we aren't accepting top level posts from this person
if($x[0]['page-flags'] == PAGE_SOAPBOX)
if (($x[0]['page-flags'] == PAGE_SOAPBOX) AND $top_level)
break;
require_once('library/simplepie/simplepie.inc');
@ -902,11 +911,16 @@ function notifier_run(&$argv, &$argc){
if(! $contact['pubkey'])
break;
if($target_item['verb'] === ACTIVITY_DISLIKE) {
// unsupported
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)) {
break 2;
}
}
elseif(($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
if(($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
// send both top-level retractions and relayable retractions for owner to relay
diaspora_send_retraction($target_item,$owner,$contact);
break;

View File

@ -157,7 +157,7 @@ function oembed_format_object($j){
case "rich": {
// not so safe..
if (!get_config("system","no_oembed_rich_content"))
$ret.= $jhtml;
$ret.= proxy_parse_html($jhtml);
}; break;
}

View File

@ -18,10 +18,10 @@ function onepoll_run(&$argv, &$argc){
}
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);
@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);
};
@ -168,8 +168,18 @@ function onepoll_run(&$argv, &$argc){
);
// Update the contact entry
if(($contact['network'] === NETWORK_OSTATUS) || ($contact['network'] === NETWORK_DIASPORA) || ($contact['network'] === NETWORK_DFRN))
update_contact($contact["id"]);
if(($contact['network'] === NETWORK_OSTATUS) || ($contact['network'] === NETWORK_DIASPORA) || ($contact['network'] === NETWORK_DFRN)) {
if (!poco_reachable($contact['url'])) {
logger("Skipping probably dead contact ".$contact['url']);
return;
}
if (!update_contact($contact["id"])) {
mark_for_death($contact);
return;
} else
unmark_for_death($contact);
}
if($contact['network'] === NETWORK_DFRN) {
@ -360,7 +370,7 @@ function onepoll_run(&$argv, &$argc){
);
logger("Mail: Connected to " . $mailconf[0]['user']);
} else
logger("Mail: Connection error ".$mailconf[0]['user']." ".print_r(imap_errors()));
logger("Mail: Connection error ".$mailconf[0]['user']." ".print_r(imap_errors(), true));
}
if($mbox) {
@ -669,6 +679,6 @@ function onepoll_run(&$argv, &$argc){
}
if (array_search(__file__,get_included_files())===0){
onepoll_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
onepoll_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View File

@ -2,6 +2,7 @@
require_once("include/Contact.php");
require_once("include/threads.php");
require_once("include/html2bbcode.php");
require_once("include/bbcode.php");
require_once("include/items.php");
require_once("mod/share.php");
require_once("include/enotify.php");
@ -9,11 +10,21 @@ require_once("include/socgraph.php");
require_once("include/Photo.php");
require_once("include/Scrape.php");
require_once("include/follow.php");
require_once("mod/proxy.php");
define('OSTATUS_DEFAULT_POLL_INTERVAL', 30); // given in minutes
define('OSTATUS_DEFAULT_POLL_TIMEFRAME', 1440); // given in minutes
define('OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS', 14400); // given in minutes
define("NS_ATOM", "http://www.w3.org/2005/Atom");
define("NS_THR", "http://purl.org/syndication/thread/1.0");
define("NS_GEORSS", "http://www.georss.org/georss");
define("NS_ACTIVITY", "http://activitystrea.ms/spec/1.0/");
define("NS_MEDIA", "http://purl.org/syndication/atommedia");
define("NS_POCO", "http://portablecontacts.net/spec/1.0");
define("NS_OSTATUS", "http://ostatus.org/schema/1.0");
define("NS_STATUSNET", "http://status.net/schema/api/1/");
function ostatus_check_follow_friends() {
$r = q("SELECT `uid`,`v` FROM `pconfig` WHERE `cat`='system' AND `k`='ostatus_legacy_contact' AND `v` != ''");
@ -48,7 +59,7 @@ function ostatus_follow_friends($uid, $url) {
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND
(`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND
`network` != '%s' LIMIT 1",
intval($uid), dbesc(normalise_link($url)),
intval($uid), dbesc(normalise_link($url)),
dbesc(normalise_link($url)), dbesc($url), dbesc(NETWORK_STATUSNET));
if (!$r) {
$data = probe_url($friend->statusnet_profile_url);
@ -131,15 +142,15 @@ function ostatus_fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch)
$value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
if ($value != "")
$contact["about"] = $value;
$contact["about"] = html2bbcode($value);
$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
if ($value != "")
$contact["location"] = $value;
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
dbesc(datetime_convert()), intval($contact["id"]));
dbesc(datetime_convert()), intval($contact["id"]), dbesc(NETWORK_OSTATUS));
poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"],
"", "", "", datetime_convert(), 2, $contact["id"], $contact["uid"]);
@ -152,9 +163,9 @@ function ostatus_fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch)
$photos = import_profile_photo($author["author-avatar"], $importer["uid"], $contact["id"]);
q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d",
q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]),
dbesc(datetime_convert()), intval($contact["id"]));
dbesc(datetime_convert()), intval($contact["id"]), dbesc(NETWORK_OSTATUS));
}
}
@ -315,7 +326,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
$orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue;
logger("Favorite ".$orig_uri." ".print_r($item, true));
$item["verb"] = ACTIVITY_LIKE;
$item["verb"] = ACTIVITY_LIKE;
$item["parent-uri"] = $orig_uri;
$item["gravity"] = GRAVITY_LIKE;
}
@ -702,9 +713,13 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
$conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as);
$conv_as = json_decode($conv_as);
$no_of_items = sizeof($items);
if (@is_array($conv_as->items))
$items = array_merge($items, $conv_as->items);
else
foreach ($conv_as->items AS $single_item)
$items[$single_item->id] = $single_item;
if ($no_of_items == sizeof($items))
break;
$pageno++;
@ -1063,4 +1078,461 @@ function ostatus_store_conversation($itemid, $conversation_url) {
logger('Storing conversation url '.$conversation_url.' for id '.$itemid);
}
}
function xml_add_element($doc, $parent, $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);
}
$parent->appendChild($element);
}
function ostatus_format_picture_post($body) {
$siteinfo = get_attached_data($body);
if (($siteinfo["type"] == "photo")) {
if (isset($siteinfo["preview"]))
$preview = $siteinfo["preview"];
else
$preview = $siteinfo["image"];
// Is it a remote picture? Then make a smaller preview here
$preview = proxy_url($preview, false, PROXY_SIZE_SMALL);
// Is it a local picture? Then make it smaller here
$preview = str_replace(array("-0.jpg", "-0.png"), array("-2.jpg", "-2.png"), $preview);
$preview = str_replace(array("-1.jpg", "-1.png"), array("-2.jpg", "-2.png"), $preview);
if (isset($siteinfo["url"]))
$url = $siteinfo["url"];
else
$url = $siteinfo["image"];
$body = trim($siteinfo["text"])." [url]".$url."[/url]\n[img]".$preview."[/img]";
}
return $body;
}
function ostatus_add_header($doc, $owner) {
$a = get_app();
$r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default`",
intval($owner["uid"]));
if (!$r)
return;
$profile = $r[0];
$root = $doc->createElementNS(NS_ATOM, 'feed');
$doc->appendChild($root);
$root->setAttribute("xmlns:thr", NS_THR);
$root->setAttribute("xmlns:georss", NS_GEORSS);
$root->setAttribute("xmlns:activity", NS_ACTIVITY);
$root->setAttribute("xmlns:media", NS_MEDIA);
$root->setAttribute("xmlns:poco", NS_POCO);
$root->setAttribute("xmlns:ostatus", NS_OSTATUS);
$root->setAttribute("xmlns:statusnet", NS_STATUSNET);
$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, "id", $a->get_baseurl()."/profile/".$owner["nick"]);
xml_add_element($doc, $root, "title", sprintf("%s timeline", $profile["name"]));
xml_add_element($doc, $root, "subtitle", sprintf("Updates from %s on %s", $profile["name"], $a->config["sitename"]));
xml_add_element($doc, $root, "logo", $profile["photo"]);
xml_add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
$author = ostatus_add_author($doc, $owner, $profile);
$root->appendChild($author);
$attributes = array("href" => $owner["url"], "rel" => "alternate", "type" => "text/html");
xml_add_element($doc, $root, "link", "", $attributes);
// To-Do: We have to find out what this is
//$attributes = array("href" => $a->get_baseurl()."/sup",
// "rel" => "http://api.friendfeed.com/2008/03#sup",
// "type" => "application/json");
//xml_add_element($doc, $root, "link", "", $attributes);
ostatus_hublinks($doc, $root);
$attributes = array("href" => $a->get_baseurl()."/salmon/".$owner["nick"], "rel" => "salmon");
xml_add_element($doc, $root, "link", "", $attributes);
$attributes = array("href" => $a->get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-replies");
xml_add_element($doc, $root, "link", "", $attributes);
$attributes = array("href" => $a->get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-mention");
xml_add_element($doc, $root, "link", "", $attributes);
$attributes = array("href" => $a->get_baseurl()."/api/statuses/user_timeline/".$owner["nick"].".atom",
"rel" => "self", "type" => "application/atom+xml");
xml_add_element($doc, $root, "link", "", $attributes);
return $root;
}
function ostatus_hublinks($doc, $root) {
$a = get_app();
$hub = get_config('system','huburl');
$hubxml = '';
if(strlen($hub)) {
$hubs = explode(',', $hub);
if(count($hubs)) {
foreach($hubs as $h) {
$h = trim($h);
if(! strlen($h))
continue;
if ($h === '[internal]')
$h = $a->get_baseurl() . '/pubsubhubbub';
xml_add_element($doc, $root, "link", "", array("href" => $h, "rel" => "hub"));
}
}
}
}
function ostatus_get_attachment($doc, $root, $item) {
$o = "";
$siteinfo = get_attached_data($item["body"]);
switch($siteinfo["type"]) {
case 'link':
$attributes = array("rel" => "enclosure",
"href" => $siteinfo["url"],
"type" => "text/html; charset=UTF-8",
"length" => "",
"title" => $siteinfo["title"]);
xml_add_element($doc, $root, "link", "", $attributes);
break;
case 'photo':
$imgdata = get_photo_info($siteinfo["image"]);
$attributes = array("rel" => "enclosure",
"href" => $siteinfo["image"],
"type" => $imgdata["mime"],
"length" => intval($imgdata["size"]));
xml_add_element($doc, $root, "link", "", $attributes);
break;
case 'video':
$attributes = array("rel" => "enclosure",
"href" => $siteinfo["url"],
"type" => "text/html; charset=UTF-8",
"length" => "",
"title" => $siteinfo["title"]);
xml_add_element($doc, $root, "link", "", $attributes);
break;
default:
break;
}
if (($siteinfo["type"] != "photo") AND isset($siteinfo["image"])) {
$photodata = get_photo_info($siteinfo["image"]);
$attributes = array("rel" => "preview", "href" => $siteinfo["image"], "media:width" => $photodata[0], "media:height" => $photodata[1]);
xml_add_element($doc, $root, "link", "", $attributes);
}
$arr = explode('[/attach],',$item['attach']);
if(count($arr)) {
foreach($arr as $r) {
$matches = false;
$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches);
if($cnt) {
$attributes = array("rel" => "enclosure",
"href" => $matches[1],
"type" => $matches[3]);
if(intval($matches[2]))
$attributes["length"] = intval($matches[2]);
if(trim($matches[4]) != "")
$attributes["title"] = trim($matches[4]);
xml_add_element($doc, $root, "link", "", $attributes);
}
}
}
}
function ostatus_add_author($doc, $owner, $profile) {
$a = get_app();
$author = $doc->createElement("author");
xml_add_element($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
xml_add_element($doc, $author, "uri", $owner["url"]);
xml_add_element($doc, $author, "name", $profile["name"]);
$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $owner["url"]);
xml_add_element($doc, $author, "link", "", $attributes);
$attributes = array(
"rel" => "avatar",
"type" => "image/jpeg", // To-Do?
"media:width" => 175,
"media:height" => 175,
"href" => $profile["photo"]);
xml_add_element($doc, $author, "link", "", $attributes);
$attributes = array(
"rel" => "avatar",
"type" => "image/jpeg", // To-Do?
"media:width" => 80,
"media:height" => 80,
"href" => $profile["thumb"]);
xml_add_element($doc, $author, "link", "", $attributes);
xml_add_element($doc, $author, "poco:preferredUsername", $owner["nick"]);
xml_add_element($doc, $author, "poco:displayName", $profile["name"]);
xml_add_element($doc, $author, "poco:note", bbcode($profile["about"]));
if (trim($owner["location"]) != "") {
$element = $doc->createElement("poco:address");
xml_add_element($doc, $element, "poco:formatted", $owner["location"]);
$author->appendChild($element);
}
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");
$author->appendChild($urls);
}
xml_add_element($doc, $author, "followers", "", array("url" => $a->get_baseurl()."/viewcontacts/".$owner["nick"]));
xml_add_element($doc, $author, "statusnet:profile_info", "", array("local_id" => $owner["uid"]));
return $author;
}
/*
To-Do: Picture attachments should look like this:
<a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
*/
function ostatus_entry($doc, $item, $owner, $toplevel = false) {
$a = get_app();
if (!$toplevel) {
$entry = $doc->createElement("entry");
$title = sprintf("New note by %s", $owner["nick"]);
} else {
$entry = $doc->createElementNS(NS_ATOM, "entry");
$entry->setAttribute("xmlns:thr", NS_THR);
$entry->setAttribute("xmlns:georss", NS_GEORSS);
$entry->setAttribute("xmlns:activity", NS_ACTIVITY);
$entry->setAttribute("xmlns:media", NS_MEDIA);
$entry->setAttribute("xmlns:poco", NS_POCO);
$entry->setAttribute("xmlns:ostatus", NS_OSTATUS);
$entry->setAttribute("xmlns:statusnet", NS_STATUSNET);
$r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default`",
intval($owner["uid"]));
if (!$r)
return;
$profile = $r[0];
$author = ostatus_add_author($doc, $owner, $profile);
$entry->appendChild($author);
$title = sprintf("New comment by %s", $owner["nick"]);
}
// To use the object-type "bookmark" we have to implement these elements:
//
// <activity:object-type>http://activitystrea.ms/schema/1.0/bookmark</activity:object-type>
// <title>Historic Rocket Landing</title>
// <summary>Nur ein Testbeitrag.</summary>
// <link rel="related" href="https://www.youtube.com/watch?v=9pillaOxGCo"/>
// <link rel="preview" href="https://pirati.cc/file/thumb-4526-450x338-b48c8055f0c2fed0c3f67adc234c4b99484a90c42ed3cac73dc1081a4d0a7bc1.jpg.jpg" media:width="450" media:height="338"/>
//
// But: it seems as if it doesn't federate well between the GS servers
// So we just set it to "note" to be sure that it reaches their target systems
xml_add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
xml_add_element($doc, $entry, "id", $item["uri"]);
xml_add_element($doc, $entry, "title", $title);
if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid'])
$body = fix_private_photos($item['body'],$owner['uid'],$item, 0);
else
$body = $item['body'];
$body = ostatus_format_picture_post($body);
if ($item['title'] != "")
$body = "[b]".$item['title']."[/b]\n\n".$body;
//$body = bb_remove_share_information($body);
$body = bbcode($body, false, false, 7);
xml_add_element($doc, $entry, "content", $body, array("type" => "html"));
xml_add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
"href" => $a->get_baseurl()."/display/".$item["guid"]));
xml_add_element($doc, $entry, "status_net", "", array("notice_id" => $item["id"]));
xml_add_element($doc, $entry, "activity:verb", construct_verb($item));
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));
$mentioned = array();
if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
$parent = q("SELECT `guid` FROM `item` WHERE `id` = %d", intval($item["parent"]));
$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
$attributes = array(
"ref" => $parent_item,
"type" => "text/html",
"href" => $a->get_baseurl()."/display/".$parent[0]["guid"]);
xml_add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
$attributes = array(
"rel" => "related",
"href" => $a->get_baseurl()."/display/".$parent[0]["guid"]);
xml_add_element($doc, $entry, "link", "", $attributes);
$mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"];
$mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"];
$thrparent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
intval($owner["uid"]),
dbesc($parent_item));
if ($thrparent) {
$mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"];
$mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"];
}
}
xml_add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation",
"href" => $a->get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]));
xml_add_element($doc, $entry, "ostatus:conversation", $a->get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]);
$tags = item_getfeedtags($item);
if(count($tags))
foreach($tags as $t)
if ($t[0] == "@")
$mentioned[$t[1]] = $t[1];
// Make sure that mentions are accepted (GNU Social has problems with mixing HTTP and HTTPS)
$newmentions = array();
foreach ($mentioned AS $mention) {
$newmentions[str_replace("http://", "https://", $mention)] = str_replace("http://", "https://", $mention);
$newmentions[str_replace("https://", "http://", $mention)] = str_replace("https://", "http://", $mention);
}
$mentioned = $newmentions;
foreach ($mentioned AS $mention) {
$r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'",
intval($owner["uid"]),
dbesc(normalise_link($mention)));
if ($r[0]["forum"] OR $r[0]["prv"])
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",
"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
"href" => $mention));
}
if (!$item["private"])
xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/collection",
"href" => "http://activityschema.org/collection/public"));
if(count($tags))
foreach($tags as $t)
if ($t[0] != "@")
xml_add_element($doc, $entry, "category", "", array("term" => $t[2]));
ostatus_get_attachment($doc, $entry, $item);
// To-Do:
// The API call has yet to be implemented
//$attributes = array("href" => $a->get_baseurl()."/api/statuses/show/".$item["id"].".atom",
// "rel" => "self", "type" => "application/atom+xml");
//xml_add_element($doc, $entry, "link", "", $attributes);
//$attributes = array("href" => $a->get_baseurl()."/api/statuses/show/".$item["id"].".atom",
// "rel" => "edit", "type" => "application/atom+xml");
//xml_add_element($doc, $entry, "link", "", $attributes);
$app = $item["app"];
if ($app == "")
$app = "web";
xml_add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item["id"], "source" => $app));
return $entry;
}
function ostatus_feed(&$a, $owner_nick, $last_update) {
$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1",
dbesc($owner_nick));
if (!$r)
return;
$owner = $r[0];
if(!strlen($last_update))
$last_update = 'now -30 days';
$check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
$items = q("SELECT STRAIGHT_JOIN `item`.*, `item`.`id` AS `item_id` FROM `item`
INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
LEFT JOIN `item` AS `thritem` ON `thritem`.`uri`=`item`.`thr-parent` AND `thritem`.`uid`=`item`.`uid`
WHERE `item`.`uid` = %d AND `item`.`received` > '%s' AND NOT `item`.`private` AND NOT `item`.`deleted`
AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
AND ((`item`.`wall` AND (`item`.`parent` = `item`.`id`))
OR (`item`.`network` = '%s' AND ((`thread`.`network`='%s') OR (`thritem`.`network` = '%s'))) AND `thread`.`mention`)
AND (`item`.`owner-link` IN ('%s', '%s'))
ORDER BY `item`.`received` DESC
LIMIT 0, 300",
intval($owner["uid"]), dbesc($check_date),
dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"]))
);
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
$root = ostatus_add_header($doc, $owner);
foreach ($items AS $item) {
$entry = ostatus_entry($doc, $item, $owner);
$root->appendChild($entry);
}
return(trim($doc->saveXML()));
}
function ostatus_salmon($item,$owner) {
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
$entry = ostatus_entry($doc, $item, $owner, true);
$doc->appendChild($entry);
return(trim($doc->saveXML()));
}
?>

View File

@ -11,7 +11,7 @@ require_once("include/dba.php");
*
* Get the language setting directly from system variables, bypassing get_config()
* as database may not yet be configured.
*
*
* If possible, we use the value from the browser.
*
*/
@ -21,22 +21,22 @@ if(! function_exists('get_browser_language')) {
function get_browser_language() {
if (x($_SERVER,'HTTP_ACCEPT_LANGUAGE')) {
// break up string into pieces (languages and q factors)
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
// break up string into pieces (languages and q factors)
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i',
$_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
if (count($lang_parse[1])) {
// create a list like "en" => 0.8
$langs = array_combine($lang_parse[1], $lang_parse[4]);
// set default to 1 for any without q factor
foreach ($langs as $lang => $val) {
if ($val === '') $langs[$lang] = 1;
}
if (count($lang_parse[1])) {
// create a list like "en" => 0.8
$langs = array_combine($lang_parse[1], $lang_parse[4]);
// sort list based on value
arsort($langs, SORT_NUMERIC);
}
// set default to 1 for any without q factor
foreach ($langs as $lang => $val) {
if ($val === '') $langs[$lang] = 1;
}
// sort list based on value
arsort($langs, SORT_NUMERIC);
}
}
if(isset($langs) && count($langs)) {
@ -94,7 +94,7 @@ if(! function_exists('load_translation_table')) {
* load string translation table for alternate language
*
* first plugin strings are loaded, then globals
*
*
* @param string $lang language code to load
*/
function load_translation_table($lang) {
@ -111,7 +111,7 @@ function load_translation_table($lang) {
}
}
}
if(file_exists("view/$lang/strings.php")) {
include("view/$lang/strings.php");
}
@ -145,7 +145,7 @@ function tt($singular, $plural, $count){
$k = $f($count);
return is_array($t)?$t[$k]:$t;
}
if ($count!=1){
return $plural;
} else {
@ -153,11 +153,34 @@ function tt($singular, $plural, $count){
}
}}
// provide a fallback which will not collide with
// a function defined in any language file
// provide a fallback which will not collide with
// a function defined in any language file
if(! function_exists('string_plural_select_default')) {
function string_plural_select_default($n) {
return ($n != 1);
}}
/**
* Return installed languages as associative array
* [
* lang => lang,
* ...
* ]
*/
function get_avaiable_languages() {
$lang_choices = array();
$langs = glob('view/*/strings.php'); /**/
if(is_array($langs) && count($langs)) {
if(! in_array('view/en/strings.php',$langs))
$langs[] = 'view/en/';
asort($langs);
foreach($langs as $l) {
$t = explode("/",$l);
$lang_choices[$t[1]] = $t[1];
}
}
return $lang_choices;
}

27
include/photos.php Normal file
View File

@ -0,0 +1,27 @@
<?php
/**
* @file include/photos.php
* @brief Functions related to photo handling.
*/
function getGps($exifCoord, $hemi) {
$degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
$flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;
return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600)));
}
function gps2Num($coordPart) {
$parts = explode('/', $coordPart);
if (count($parts) <= 0)
return 0;
if (count($parts) == 1)
return $parts[0];
return floatval($parts[0]) / floatval($parts[1]);
}

View File

@ -7,8 +7,8 @@ class pidfile {
$this->_file = "$dir/$name.pid";
if (file_exists($this->_file)) {
$pid = trim(file_get_contents($this->_file));
if (posix_kill($pid, 0)) {
$pid = trim(@file_get_contents($this->_file));
if (($pid != "") AND posix_kill($pid, 0)) {
$this->_running = true;
}
}
@ -21,7 +21,7 @@ class pidfile {
public function __destruct() {
if ((! $this->_running) && file_exists($this->_file)) {
unlink($this->_file);
@unlink($this->_file);
}
}
@ -30,7 +30,7 @@ class pidfile {
}
public function running_time() {
return(time() - filectime($this->_file));
return(time() - @filectime($this->_file));
}
public function kill() {

View File

@ -55,9 +55,10 @@ function get_attached_data($body) {
$data = parseurl_getsiteinfo_cached($pictures[0][1], true);
if ($data["type"] == "photo") {
$post["type"] = "photo";
if (isset($data["images"][0]))
if (isset($data["images"][0])) {
$post["image"] = $data["images"][0]["src"];
else
$post["url"] = $data["url"];
} else
$post["image"] = $data["url"];
$post["preview"] = $pictures[0][2];

View File

@ -1,7 +1,17 @@
<?php
/**
* @file include/identity.php
*
* @brief Some functions to handle addons and themes.
*/
// install and uninstall plugin
/**
* @brief uninstalls an addon.
*
* @param string $plugin name of the addon
* @return boolean
*/
if (! function_exists('uninstall_plugin')){
function uninstall_plugin($plugin){
logger("Addons: uninstalling " . $plugin);
@ -16,6 +26,12 @@ function uninstall_plugin($plugin){
}
}}
/**
* @brief installs an addon.
*
* @param string $plugin name of the addon
* @return bool
*/
if (! function_exists('install_plugin')){
function install_plugin($plugin) {
// silently fail if plugin was removed
@ -42,7 +58,7 @@ function install_plugin($plugin) {
// This way the system won't fall over dead during the update.
if(file_exists('addon/' . $plugin . '/.hidden')) {
q("update addon set hidden = 1 where name = '%s'",
q("UPDATE `addon` SET `hidden` = 1 WHERE `name` = '%s'",
dbesc($plugin)
);
}
@ -105,10 +121,27 @@ function reload_plugins() {
}}
/**
* @brief check if addon is enabled
*
* @param string $plugin
* @return boolean
*/
function plugin_enabled($plugin) {
$r = q("SELECT * FROM `addon` WHERE `installed` = 1 AND `name` = '%s'", $plugin);
return((bool)(count($r) > 0));
}
/**
* @brief registers a hook.
*
* @param string $hook the name of the hook
* @param string $file the name of the file that hooks into
* @param string $function the name of the function that the hook will call
* @param int $priority A priority (defaults to 0)
* @return mixed|bool
*/
if(! function_exists('register_hook')) {
function register_hook($hook,$file,$function,$priority=0) {
@ -129,6 +162,14 @@ function register_hook($hook,$file,$function,$priority=0) {
return $r;
}}
/**
* @brief unregisters a hook.
*
* @param string $hook the name of the hook
* @param string $file the name of the file that hooks into
* @param string $function the name of the function that the hook called
* @return array
*/
if(! function_exists('unregister_hook')) {
function unregister_hook($hook,$file,$function) {
@ -155,7 +196,15 @@ function load_hooks() {
}
}}
/**
* @brief Calls a hook.
*
* Use this function when you want to be able to allow a hook to manipulate
* the provided data.
*
* @param string $name of the hook to call
* @param string|array &$data to transmit to the callback handler
*/
if(! function_exists('call_hooks')) {
function call_hooks($name, &$data = null) {
$stamp1 = microtime(true);
@ -178,7 +227,7 @@ function call_hooks($name, &$data = null) {
}
else {
// remove orphan hooks
q("delete from hook where hook = '%s' and file = '%s' and function = '%s'",
q("DELETE FROM `hook` WHERE `hook` = '%s' AND `file` = '%s' AND `function` = '%s'",
dbesc($name),
dbesc($hook[0]),
dbesc($hook[1])
@ -204,16 +253,20 @@ function plugin_is_app($name) {
return false;
}}
/*
* parse plugin comment in search of plugin infos.
* like
/**
* @brief Parse plugin comment in search of plugin infos.
*
* * Name: Plugin
* like
* \code
*...* Name: Plugin
* * Description: A plugin which plugs in
* * Version: 1.2.3
* . * Version: 1.2.3
* * Author: John <profile url>
* * Author: Jane <email>
* *
* *\endcode
* @param string $plugin the name of the plugin
* @return array with the plugin information
*/
if (! function_exists('get_plugin_info')){
@ -265,16 +318,20 @@ function get_plugin_info($plugin){
}}
/*
* parse theme comment in search of theme infos.
/**
* @brief Parse theme comment in search of theme infos.
*
* like
*
* * Name: My Theme
* \code
* ..* Name: My Theme
* * Description: My Cool Theme
* * Version: 1.2.3
* . * Version: 1.2.3
* * Author: John <profile url>
* * Maintainer: Jane <profile url>
* *
* \endcode
* @param string $theme the name of the theme
* @return array
*/
if (! function_exists('get_theme_info')){
@ -340,7 +397,14 @@ function get_theme_info($theme){
return $info;
}}
/**
* @brief Returns the theme's screenshot.
*
* The screenshot is expected as view/theme/$theme/screenshot.[png|jpg].
*
* @param sring $theme The name of the theme
* @return string
*/
function get_theme_screenshot($theme) {
$a = get_app();
$exts = array('.png','.jpg');
@ -402,7 +466,7 @@ function service_class_allows($uid,$property,$usage = false) {
$service_class = $a->user['service_class'];
}
else {
$r = q("select service_class from user where uid = %d limit 1",
$r = q("SELECT `service_class` FROM `user` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if($r !== false and count($r)) {
@ -432,7 +496,7 @@ function service_class_fetch($uid,$property) {
$service_class = $a->user['service_class'];
}
else {
$r = q("select service_class from user where uid = %d limit 1",
$r = q("SELECT `service_class` FROM `user` WHERE `uid` = %d LIMIT 1",
intval($uid)
);
if($r !== false and count($r)) {

View File

@ -12,7 +12,6 @@ if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
require_once("boot.php");
function poller_run(&$argv, &$argc){
global $a, $db;
@ -21,303 +20,148 @@ function poller_run(&$argv, &$argc){
}
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);
};
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
$load = current_load();
if($load) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
require_once('include/session.php');
require_once('include/datetime.php');
require_once('library/simplepie/simplepie.inc');
require_once('include/items.php');
require_once('include/Contact.php');
require_once('include/email.php');
require_once('include/socgraph.php');
require_once('include/pidfile.php');
require_once('mod/nodeinfo.php');
load_config('config');
load_config('system');
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload) {
logger('system: load ' . $load[0] . ' too high. Poller deferred to next scheduled run.');
if(intval($load) > $maxsysload) {
logger('system: load ' . $load . ' too high. poller deferred to next scheduled run.');
return;
}
}
$lockpath = get_lockpath();
if ($lockpath != '') {
$pidfile = new pidfile($lockpath, 'poller');
if($pidfile->is_already_running()) {
logger("poller: Already running");
if ($pidfile->running_time() > 9*60) {
$pidfile->kill();
logger("poller: killed stale process");
// Calling a new instance
proc_run('php','include/poller.php');
}
exit;
}
}
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('poller: start');
// run queue delivery process in the background
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");
// run the process to update locally stored global contacts in the background
proc_run('php',"include/discover_poco.php", "checkcontact");
// expire any expired accounts
q("UPDATE user SET `account_expired` = 1 where `account_expired` = 0
AND `account_expires_on` != '0000-00-00 00:00:00'
AND `account_expires_on` < UTC_TIMESTAMP() ");
// delete user and contact records for recently removed accounts
$r = q("SELECT * FROM `user` WHERE `account_removed` = 1 AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY");
if ($r) {
foreach($r as $user) {
q("DELETE FROM `contact` WHERE `uid` = %d", intval($user['uid']));
q("DELETE FROM `user` WHERE `uid` = %d", intval($user['uid']));
}
}
$abandon_days = intval(get_config('system','account_abandon_days'));
if($abandon_days < 1)
$abandon_days = 0;
// Check OStatus conversations
// Check only conversations with mentions (for a longer time)
check_conversations(true);
// Check every conversation
check_conversations(false);
// Follow your friends from your legacy OStatus account
ostatus_check_follow_friends();
// update nodeinfo data
nodeinfo_cron();
// To-Do: Regenerate usage statistics
// q("ANALYZE TABLE `item`");
// once daily run birthday_updates and then expire in background
$d1 = get_config('system','last_expire_day');
$d2 = intval(datetime_convert('UTC','UTC','now','d'));
if($d2 != intval($d1)) {
update_contact_birthdays();
update_suggestions();
set_config('system','last_expire_day',$d2);
proc_run('php','include/expire.php');
}
$last = get_config('system','cache_last_cleared');
if($last) {
$next = $last + (3600); // Once per hour
$clear_cache = ($next <= time());
} else
$clear_cache = true;
if ($clear_cache) {
// clear old cache
Cache::clear();
// clear old item cache files
clear_cache();
// clear cache for photos
clear_cache($a->get_basepath(), $a->get_basepath()."/photo");
// clear smarty cache
clear_cache($a->get_basepath()."/view/smarty3/compiled", $a->get_basepath()."/view/smarty3/compiled");
// clear cache for image proxy
if (!get_config("system", "proxy_disabled")) {
clear_cache($a->get_basepath(), $a->get_basepath()."/proxy");
$cachetime = get_config('system','proxy_cache_time');
if (!$cachetime) $cachetime = PROXY_DEFAULT_TIME;
q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
}
set_config('system','cache_last_cleared', time());
}
$manual_id = 0;
$generation = 0;
$force = false;
$restart = false;
if(($argc > 1) && ($argv[1] == 'force'))
$force = true;
if(($argc > 1) && ($argv[1] == 'restart')) {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
killme();
}
if(($argc > 1) && intval($argv[1])) {
$manual_id = intval($argv[1]);
$force = true;
}
$interval = intval(get_config('system','poll_interval'));
if(! $interval)
$interval = ((get_config('system','delivery_interval') === false) ? 3 : intval(get_config('system','delivery_interval')));
$sql_extra = (($manual_id) ? " AND `id` = $manual_id " : "");
reload_plugins();
$d = datetime_convert();
if(! $restart)
proc_run('php','include/cronhooks.php');
// Only poll from those with suitable relationships,
// and which have a polling address and ignore Diaspora since
// we are unable to match those posts with a Diaspora GUID and prevent duplicates.
$abandon_sql = (($abandon_days)
? sprintf(" AND `user`.`login_date` > UTC_TIMESTAMP() - INTERVAL %d DAY ", intval($abandon_days))
: ''
);
$contacts = q("SELECT `contact`.`id` FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `rel` IN (%d, %d) AND `poll` != '' AND `network` IN ('%s', '%s', '%s', '%s', '%s', '%s')
$sql_extra
AND NOT `self` AND NOT `contact`.`blocked` AND NOT `contact`.`readonly` AND NOT `contact`.`archive`
AND NOT `user`.`account_expired` AND NOT `user`.`account_removed` $abandon_sql ORDER BY RAND()",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN),
dbesc(NETWORK_ZOT),
dbesc(NETWORK_OSTATUS),
dbesc(NETWORK_FEED),
dbesc(NETWORK_MAIL),
dbesc(NETWORK_MAIL2)
);
if(! count($contacts)) {
// Checking the number of workers
if (poller_too_much_workers(1))
return;
}
foreach($contacts as $c) {
if(($argc <= 1) OR ($argv[1] != "no_cron")) {
// Run the cron job that calls all other jobs
proc_run("php","include/cron.php");
$res = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
intval($c['id'])
);
// Run the cronhooks job separately from cron for being able to use a different timing
proc_run("php","include/cronhooks.php");
if((! $res) || (! count($res)))
// Cleaning dead processes
$r = q("SELECT DISTINCT(`pid`) FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
foreach($r AS $pid)
if (!posix_kill($pid["pid"], 0))
q("UPDATE `workerqueue` SET `executed` = '0000-00-00 00:00:00', `pid` = 0 WHERE `pid` = %d",
intval($pid["pid"]));
else {
// To-Do: Kill long running processes
// But: Update processes (like the database update) mustn't be killed
}
} else
// Sleep four seconds before checking for running processes again to avoid having too many workers
sleep(4);
// Checking number of workers
if (poller_too_much_workers(2))
return;
$starttime = time();
while ($r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `created` LIMIT 1")) {
// Count active workers and compare them with a maximum value that depends on the load
if (poller_too_much_workers(3))
return;
q("UPDATE `workerqueue` SET `executed` = '%s', `pid` = %d WHERE `id` = %d AND `executed` = '0000-00-00 00:00:00'",
dbesc(datetime_convert()),
intval(getmypid()),
intval($r[0]["id"]));
// Assure that there are no tasks executed twice
$id = q("SELECT `id` FROM `workerqueue` WHERE `id` = %d AND `pid` = %d",
intval($r[0]["id"]),
intval(getmypid()));
if (!$id) {
logger("Queue item ".$r[0]["id"]." was executed multiple times - skip this execution", LOGGER_DEBUG);
continue;
foreach($res as $contact) {
$xml = false;
if($manual_id)
$contact['last-update'] = '0000-00-00 00:00:00';
if(in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS)))
$contact['priority'] = 2;
if($contact['subhub'] AND in_array($contact['network'], array(NETWORK_DFRN, NETWORK_ZOT, NETWORK_OSTATUS))) {
// We should be getting everything via a hub. But just to be sure, let's check once a day.
// (You can make this more or less frequent if desired by setting 'pushpoll_frequency' appropriately)
// This also lets us update our subscription to the hub, and add or replace hubs in case it
// changed. We will only update hubs once a day, regardless of 'pushpoll_frequency'.
$poll_interval = get_config('system','pushpoll_frequency');
$contact['priority'] = (($poll_interval !== false) ? intval($poll_interval) : 3);
}
if($contact['priority'] AND !$force) {
$update = false;
$t = $contact['last-update'];
/**
* Based on $contact['priority'], should we poll this site now? Or later?
*/
switch ($contact['priority']) {
case 5:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 month"))
$update = true;
break;
case 4:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 week"))
$update = true;
break;
case 3:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 day"))
$update = true;
break;
case 2:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 12 hour"))
$update = true;
break;
case 1:
default:
if(datetime_convert('UTC','UTC', 'now') > datetime_convert('UTC','UTC', $t . " + 1 hour"))
$update = true;
break;
}
if(!$update)
continue;
}
logger("Polling ".$contact["network"]." ".$contact["id"]." ".$contact["nick"]." ".$contact["name"]);
proc_run('php','include/onepoll.php',$contact['id']);
if($interval)
@time_sleep_until(microtime(true) + (float) $interval);
}
$argv = json_decode($r[0]["parameter"]);
$argc = count($argv);
// Check for existance and validity of the include file
$include = $argv[0];
if (!validate_include($include)) {
logger("Include file ".$argv[0]." is not valid!");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
continue;
}
require_once($include);
$funcname=str_replace(".php", "", basename($argv[0]))."_run";
if (function_exists($funcname)) {
logger("Process ".getmypid()." - ID ".$r[0]["id"].": ".$funcname." ".$r[0]["parameter"]);
$funcname($argv, $argc);
logger("Process ".getmypid()." - ID ".$r[0]["id"].": ".$funcname." - done");
q("DELETE FROM `workerqueue` WHERE `id` = %d", intval($r[0]["id"]));
} else
logger("Function ".$funcname." does not exist");
// Quit the poller once every hour
if (time() > ($starttime + 3600))
return;
}
logger('poller: end');
}
return;
function poller_too_much_workers($stage) {
$queues = get_config("system", "worker_queues");
if ($queues == 0)
$queues = 4;
$active = poller_active_workers();
// Decrease the number of workers at higher load
$load = current_load();
if($load) {
$maxsysload = intval(get_config('system','maxloadavg'));
if($maxsysload < 1)
$maxsysload = 50;
$maxworkers = $queues;
// Some magical mathemathics to reduce the workers
$exponent = 3;
$slope = $maxworkers / pow($maxsysload, $exponent);
$queues = ceil($slope * pow(max(0, $maxsysload - $load), $exponent));
logger("Current load stage ".$stage.": ".$load." - maximum: ".$maxsysload." - current queues: ".$active." - maximum: ".$queues, LOGGER_DEBUG);
}
return($active >= $queues);
}
function poller_active_workers() {
$workers = q("SELECT COUNT(*) AS `workers` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
return($workers[0]["workers"]);
}
if (array_search(__file__,get_included_files())===0){
poller_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}
?>

View File

@ -1,5 +1,6 @@
<?php
require_once("boot.php");
require_once("include/ostatus.php");
function handle_pubsubhubbub() {
global $a, $db;
@ -12,17 +13,17 @@ function handle_pubsubhubbub() {
$r = q("SELECT * FROM `push_subscriber` WHERE `push` > 0");
foreach($r as $rr) {
$params = get_feed_for($a, '', $rr['nickname'], $rr['last_update'], 0, true);
//$params = get_feed_for($a, '', $rr['nickname'], $rr['last_update'], 0, true);
$params = ostatus_feed($a, $rr['nickname'], $rr['last_update']);
$hmac_sig = hash_hmac("sha1", $params, $rr['secret']);
$headers = array("Content-type: application/atom+xml",
sprintf("Link: <%s>;rel=hub," .
"<%s>;rel=self",
$a->get_baseurl() . '/pubsubhubbub',
$rr['topic']),
"X-Hub-Signature: sha1=" . $hmac_sig);
sprintf("Link: <%s>;rel=hub,<%s>;rel=self",
$a->get_baseurl().'/pubsubhubbub',
$rr['topic']),
"X-Hub-Signature: sha1=".$hmac_sig);
logger('POST '. print_r($headers, true)."\n".$params, LOGGER_DEBUG);
logger('POST '.print_r($headers, true)."\n".$params, LOGGER_DEBUG);
post_url($rr['callback_url'], $params, $headers);
$ret = $a->get_curl_code();

View File

@ -22,6 +22,7 @@ function queue_run(&$argv, &$argc){
require_once('include/items.php');
require_once('include/bbcode.php');
require_once('include/pidfile.php');
require_once('include/socgraph.php');
load_config('config');
load_config('system');
@ -59,6 +60,10 @@ function queue_run(&$argv, &$argc){
$interval = ((get_config('system','delivery_interval') === false) ? 2 : intval(get_config('system','delivery_interval')));
// If we are using the worker we don't need a delivery interval
if (get_config("system", "worker"))
$interval = false;
$r = q("select * from deliverq where 1");
if($r) {
foreach($r as $rr) {
@ -88,7 +93,7 @@ function queue_run(&$argv, &$argc){
else {
// For the first 12 hours we'll try to deliver every 15 minutes
// After that, we'll only attempt delivery once per hour.
// After that, we'll only attempt delivery once per hour.
$r = q("SELECT `id` FROM `queue` WHERE (( `created` > UTC_TIMESTAMP() - INTERVAL 12 HOUR && `last` < UTC_TIMESTAMP() - INTERVAL 15 MINUTE ) OR ( `last` < UTC_TIMESTAMP() - INTERVAL 1 HOUR ))");
}
@ -107,7 +112,7 @@ function queue_run(&$argv, &$argc){
foreach($r as $q_item) {
// queue_predeliver hooks may have changed the queue db details,
// queue_predeliver hooks may have changed the queue db details,
// so check again if this entry still needs processing
if($queue_id) {
@ -132,12 +137,18 @@ function queue_run(&$argv, &$argc){
continue;
}
if(in_array($c[0]['notify'],$deadguys)) {
logger('queue: skipping known dead url: ' . $c[0]['notify']);
update_queue_time($q_item['id']);
continue;
logger('queue: skipping known dead url: ' . $c[0]['notify']);
update_queue_time($q_item['id']);
continue;
}
$u = q("SELECT `user`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`
if (!poco_reachable($c[0]['url'])) {
logger('queue: skipping probably dead url: ' . $c[0]['url']);
update_queue_time($q_item['id']);
continue;
}
$u = q("SELECT `user`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`
FROM `user` WHERE `uid` = %d LIMIT 1",
intval($c[0]['uid'])
);
@ -194,9 +205,9 @@ function queue_run(&$argv, &$argc){
call_hooks('queue_deliver', $a, $params);
if($params['result'])
remove_queue_item($q_item['id']);
remove_queue_item($q_item['id']);
else
update_queue_time($q_item['id']);
update_queue_time($q_item['id']);
break;

View File

@ -66,8 +66,6 @@ function get_salmon_key($uri,$keyhash) {
function slapper($owner,$url,$slap) {
logger('slapper called for '.$url.'. Data: ' . $slap);
// does contact have a salmon endpoint?
if(! strlen($url))
@ -97,6 +95,8 @@ EOT;
$slap = str_replace('<entry>',$namespaces,$slap);
logger('slapper called for '.$url.'. Data: ' . $slap);
// create a magic envelope
$data = base64url_encode($slap);

View File

@ -225,15 +225,17 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$created = $x[0]["created"];
$server_url = $x[0]["server_url"];
$nick = $x[0]["nick"];
$addr = $x[0]["addr"];
} else {
$created = "0000-00-00 00:00:00";
$server_url = "";
$urlparts = parse_url($profile_url);
$nick = end(explode("/", $urlparts["path"]));
$addr = "";
}
if ((($network == "") OR ($name == "") OR ($profile_photo == "") OR ($server_url == "") OR $alternate)
if ((($network == "") OR ($name == "") OR ($addr == "") OR ($profile_photo == "") OR ($server_url == "") OR $alternate)
AND poco_reachable($profile_url, $server_url, $network, false)) {
$data = probe_url($profile_url);
@ -242,6 +244,7 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
$network = $data["network"];
$name = $data["name"];
$nick = $data["nick"];
$addr = $data["addr"];
$profile_url = $data["url"];
$profile_photo = $data["photo"];
$server_url = $data["baseurl"];
@ -294,14 +297,18 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
if (($keywords == "") AND ($x[0]['keywords'] != ""))
$keywords = $x[0]['keywords'];
if (($addr == "") AND ($x[0]['addr'] != ""))
$addr = $x[0]['addr'];
if (($generation == 0) AND ($x[0]['generation'] > 0))
$generation = $x[0]['generation'];
if($x[0]['name'] != $name || $x[0]['photo'] != $profile_photo || $x[0]['updated'] < $updated) {
q("UPDATE `gcontact` SET `name` = '%s', `network` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s', `server_url` = '%s',
q("UPDATE `gcontact` SET `name` = '%s', `addr` = '%s', `network` = '%s', `photo` = '%s', `connect` = '%s', `url` = '%s', `server_url` = '%s',
`updated` = '%s', `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s', `generation` = %d
WHERE (`generation` >= %d OR `generation` = 0) AND `nurl` = '%s'",
dbesc($name),
dbesc($addr),
dbesc($network),
dbesc($profile_photo),
dbesc($connect_url),
@ -318,10 +325,11 @@ function poco_check($profile_url, $name, $network, $profile_photo, $about, $loca
);
}
} else {
q("INSERT INTO `gcontact` (`name`, `nick`, `network`, `url`, `nurl`, `photo`, `connect`, `server_url`, `created`, `updated`, `location`, `about`, `keywords`, `gender`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
q("INSERT INTO `gcontact` (`name`, `nick`, `addr`, `network`, `url`, `nurl`, `photo`, `connect`, `server_url`, `created`, `updated`, `location`, `about`, `keywords`, `gender`, `generation`)
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)",
dbesc($name),
dbesc($nick),
dbesc($addr),
dbesc($network),
dbesc($profile_url),
dbesc(normalise_link($profile_url)),
@ -570,7 +578,7 @@ function poco_last_updated($profile, $force = false) {
return false;
}
if (($data["poll"] == "") OR ($data["network"] == NETWORK_FEED)) {
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)));
return false;
@ -748,8 +756,11 @@ function poco_check_server($server_url, $network = "", $force = false) {
}
if (!$serverret["success"] OR ($serverret["body"] == "") OR (sizeof($xmlobj) == 0) OR !is_object($xmlobj)) {
$last_failure = datetime_convert();
$failure = true;
// Workaround for bad configured servers (known nginx problem)
if ($serverret["debug"]["http_code"] != "403") {
$last_failure = datetime_convert();
$failure = true;
}
} elseif ($network == NETWORK_DIASPORA)
$last_contact = datetime_convert();
@ -1036,15 +1047,16 @@ function count_common_friends($uid,$cid) {
$r = q("SELECT count(*) as `total`
FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
where `glink`.`cid` = %d and `glink`.`uid` = %d
and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) ",
WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))
AND `gcontact`.`nurl` IN (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d ) ",
intval($cid),
intval($uid),
intval($uid),
intval($cid)
);
// logger("count_common_friends: $uid $cid {$r[0]['total']}");
// logger("count_common_friends: $uid $cid {$r[0]['total']}");
if(count($r))
return $r[0]['total'];
return 0;
@ -1059,11 +1071,15 @@ function common_friends($uid,$cid,$start = 0,$limit=9999,$shuffle = false) {
else
$sql_extra = " order by `gcontact`.`name` asc ";
$r = q("SELECT `gcontact`.*
FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
where `glink`.`cid` = %d and `glink`.`uid` = %d
and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 and id != %d )
$sql_extra limit %d, %d",
$r = q("SELECT `gcontact`.*, `contact`.`id` AS `cid`
FROM `glink`
INNER JOIN `gcontact` ON `glink`.`gcid` = `gcontact`.`id`
INNER JOIN `contact` ON `gcontact`.`nurl` = `contact`.`nurl`
WHERE `glink`.`cid` = %d and `glink`.`uid` = %d
AND `contact`.`uid` = %d AND `contact`.`self` = 0 AND `contact`.`blocked` = 0
AND `contact`.`hidden` = 0 AND `contact`.`id` != %d
AND ((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))
$sql_extra LIMIT %d, %d",
intval($cid),
intval($uid),
intval($uid),
@ -1120,7 +1136,8 @@ function count_all_friends($uid,$cid) {
$r = q("SELECT count(*) as `total`
FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
where `glink`.`cid` = %d and `glink`.`uid` = %d ",
where `glink`.`cid` = %d and `glink`.`uid` = %d AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))",
intval($cid),
intval($uid)
);
@ -1134,10 +1151,14 @@ function count_all_friends($uid,$cid) {
function all_friends($uid,$cid,$start = 0, $limit = 80) {
$r = q("SELECT `gcontact`.*
FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
where `glink`.`cid` = %d and `glink`.`uid` = %d
order by `gcontact`.`name` asc LIMIT %d, %d ",
$r = q("SELECT `gcontact`.*, `contact`.`id` AS `cid`
FROM `glink`
INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl` AND `contact`.`uid` = %d
WHERE `glink`.`cid` = %d AND `glink`.`uid` = %d AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`))
ORDER BY `gcontact`.`name` ASC LIMIT %d, %d ",
intval($uid),
intval($cid),
intval($uid),
intval($start),
@ -1167,14 +1188,14 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
$sql_network = "'".$sql_network."'";
$r = q("SELECT count(glink.gcid) as `total`, gcontact.* from gcontact
INNER JOIN glink on glink.gcid = gcontact.id
INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id`
where uid = %d and not gcontact.nurl in ( select nurl from contact where uid = %d )
and not gcontact.name in ( select name from contact where uid = %d )
and not gcontact.id in ( select gcid from gcign where uid = %d )
AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d)
AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d)
AND `gcontact`.`updated` != '0000-00-00 00:00:00'
AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
AND `gcontact`.`network` IN (%s)
group by glink.gcid order by gcontact.updated desc,total desc limit %d, %d ",
GROUP BY `glink`.`gcid` ORDER BY `gcontact`.`updated` DESC,`total` DESC LIMIT %d, %d",
intval($uid),
intval($uid),
intval($uid),
@ -1187,14 +1208,15 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
if(count($r) && count($r) >= ($limit -1))
return $r;
$r2 = q("SELECT gcontact.* from gcontact
INNER JOIN glink on glink.gcid = gcontact.id
where glink.uid = 0 and glink.cid = 0 and glink.zcid = 0 and not gcontact.nurl in ( select nurl from contact where uid = %d )
and not gcontact.name in ( select name from contact where uid = %d )
and not gcontact.id in ( select gcid from gcign where uid = %d )
$r2 = q("SELECT gcontact.* FROM gcontact
INNER JOIN `glink` ON `glink`.`gcid` = `gcontact`.`id`
WHERE `glink`.`uid` = 0 AND `glink`.`cid` = 0 AND `glink`.`zcid` = 0 AND NOT `gcontact`.`nurl` IN (SELECT `nurl` FROM `contact` WHERE `uid` = %d)
AND NOT `gcontact`.`name` IN (SELECT `name` FROM `contact` WHERE `uid` = %d)
AND NOT `gcontact`.`id` IN (SELECT `gcid` FROM `gcign` WHERE `uid` = %d)
AND `gcontact`.`updated` != '0000-00-00 00:00:00'
AND `gcontact`.`last_contact` >= `gcontact`.`last_failure`
AND `gcontact`.`network` IN (%s)
order by rand() limit %d, %d ",
ORDER BY rand() LIMIT %d, %d",
intval($uid),
intval($uid),
intval($uid),
@ -1210,6 +1232,9 @@ function suggestion_query($uid, $start = 0, $limit = 80) {
foreach ($r AS $suggestion)
$list[$suggestion["nurl"]] = $suggestion;
while (sizeof($list) > ($limit))
array_pop($list);
return $list;
}

View File

@ -20,6 +20,10 @@ function replace_macros($s,$r) {
$stamp1 = microtime(true);
$a = get_app();
// pass $baseurl to all templates
$r['$baseurl'] = z_root();
$t = $a->template_engine();
try {
@ -138,31 +142,31 @@ function autoname($len) {
'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh');
$start = mt_rand(0,2);
if($start == 0)
$table = $vowels;
else
$table = $cons;
if($start == 0)
$table = $vowels;
else
$table = $cons;
$word = '';
for ($x = 0; $x < $len; $x ++) {
$r = mt_rand(0,count($table) - 1);
$word .= $table[$r];
$r = mt_rand(0,count($table) - 1);
$word .= $table[$r];
if($table == $vowels)
$table = array_merge($cons,$midcons);
else
$table = $vowels;
if($table == $vowels)
$table = array_merge($cons,$midcons);
else
$table = $vowels;
}
$word = substr($word,0,$len);
foreach($noend as $noe) {
if((strlen($word) > 2) && (substr($word,-2) == $noe)) {
$word = substr($word,0,-1);
break;
}
if((strlen($word) > 2) && (substr($word,-2) == $noe)) {
$word = substr($word,0,-1);
break;
}
}
if(substr($word,-1) == 'q')
$word = substr($word,0,-1);
@ -281,7 +285,7 @@ function paginate_data(&$a, $count=null) {
if (($a->page_offset != "") AND !preg_match('/[?&].offset=/', $stripped))
$stripped .= "&offset=".urlencode($a->page_offset);
$url = $a->get_baseurl() . '/' . $stripped;
$url = z_root() . '/' . $stripped;
$data = array();
function _l(&$d, $name, $url, $text, $class="") {
@ -939,13 +943,16 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
if($class)
$class = ' ' . $class;
if ($contact["addr"] == "")
$contact["addr"] = $contact["url"];
$url = $contact['url'];
$sparkle = '';
$redir = false;
if($redirect) {
$a = get_app();
$redirect_url = $a->get_baseurl() . '/redir/' . $contact['id'];
$redirect_url = z_root() . '/redir/' . $contact['id'];
if(local_user() && ($contact['uid'] == local_user()) && ($contact['network'] === NETWORK_DFRN)) {
$redir = true;
$url = $redirect_url;
@ -962,7 +969,7 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
. (($click) ? ' fakelink' : '') . '" '
. (($redir) ? ' target="redir" ' : '')
. (($url) ? ' href="' . $url . '"' : '') . $click
. '" title="' . $contact['name'] . ' [' . $contact['url'] . ']" alt="' . $contact['name']
. '" title="' . $contact['name'] . ' [' . $contact['addr'] . ']" alt="' . $contact['name']
. '" >'. $contact['name'] . '</a></div>' . "\r\n";
}
else {
@ -970,7 +977,7 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
. (($click) ? ' fakelink' : '') . '" '
. (($redir) ? ' target="redir" ' : '')
. (($url) ? ' href="' . $url . '"' : '') . $click . ' ><img class="contact-block-img' . $class . $sparkle . '" src="'
. proxy_url($contact['micro']) . '" title="' . $contact['name'] . ' [' . $contact['url'] . ']" alt="' . $contact['name']
. proxy_url($contact['micro'], false, PROXY_SIZE_THUMB) . '" title="' . $contact['name'] . ' [' . $contact['addr'] . ']" alt="' . $contact['name']
. '" /></a></div>' . "\r\n";
}
}}
@ -1008,7 +1015,7 @@ function search($s,$id='search-box',$url='/search',$save = false, $aside = true)
$values['$searchoption'][] = t("Forums");
}
return replace_macros(get_markup_template('searchbox.tpl'), $values);
return replace_macros(get_markup_template('searchbox.tpl'), $values);
}}
if(! function_exists('valid_email')) {
@ -1020,8 +1027,9 @@ if(! function_exists('valid_email')) {
*/
function valid_email($x){
if(get_config('system','disable_email_validation'))
return true;
// Removed because Fabio told me so.
//if(get_config('system','disable_email_validation'))
// return true;
if(preg_match('/^[_a-zA-Z0-9\-\+]+(\.[_a-zA-Z0-9\-\+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/',$x))
return true;
@ -1162,48 +1170,48 @@ function smilies($s, $sample = false) {
':facepalm',
':like',
':dislike',
'~friendica',
'red#',
'~friendica',
'red#',
'red#matrix'
);
$icons = array(
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;/3" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-smile.gif" alt=":-)" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-wink.gif" alt=";-)" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-frown.gif" alt=":-(" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-p" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-\"" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt=":-O" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-thumbsup.gif" alt="\\o/" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="o.O" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="O.o" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="o_O" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-Oo.gif" alt="O_o" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-cry.gif" alt=":\'(" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-foot-in-mouth.gif" alt=":-!" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-undecided.gif" alt=":-/" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-embarassed.gif" alt=":-[" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-cool.gif" alt="8-)" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/beer_mug.gif" alt=":beer" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/beer_mug.gif" alt=":homebrew" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/coffee.gif" alt=":coffee" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/like.gif" alt=":like" />',
'<img class="smiley" src="' . $a->get_baseurl() . '/images/dislike.gif" alt=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . $a->get_baseurl() . '/images/friendica-16.png" alt="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . $a->get_baseurl() . '/images/rm-16.png" alt="red" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . $a->get_baseurl() . '/images/rm-16.png" alt="red" />matrix</a>'
'<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);
@ -1248,7 +1256,7 @@ function preg_heart($x) {
return $x[0];
$t = '';
for($cnt = 0; $cnt < strlen($x[1]); $cnt ++)
$t .= '<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" />';
$t .= '<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" />';
$r = str_replace($x[0],$t,$x[0]);
return $r;
}
@ -1326,7 +1334,7 @@ function redir_private_images($a, &$item) {
if((local_user() == $item['uid']) && ($item['private'] != 0) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN)) {
//logger("redir_private_images: redir");
$img_url = $a->get_baseurl() . '/redir?f=1&quiet=1&url=' . $mtch[1] . '&conurl=' . $item['author-link'];
$img_url = z_root() . '/redir?f=1&quiet=1&url=' . $mtch[1] . '&conurl=' . $item['author-link'];
$item['body'] = str_replace($mtch[0], "[img]".$img_url."[/img]", $item['body']);
}
}
@ -1377,7 +1385,7 @@ function prepare_body(&$item,$attach = false, $preview = false) {
$a = get_app();
call_hooks('prepare_body_init', $item);
$searchpath = $a->get_baseurl()."/search?tag=";
$searchpath = z_root()."/search?tag=";
$tags=array();
$hashtags = array();
@ -1410,9 +1418,6 @@ function prepare_body(&$item,$attach = false, $preview = false) {
put_item_in_cache($item, true);
$s = $item["rendered-html"];
require_once("mod/proxy.php");
$s = proxy_parse_html($s);
$prep_arr = array('item' => $item, 'html' => $s, 'preview' => $preview);
call_hooks('prepare_body', $prep_arr);
$s = $prep_arr['html'];
@ -1438,7 +1443,7 @@ function prepare_body(&$item,$attach = false, $preview = false) {
$mime = $mtch[3];
if((local_user() == $item['uid']) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN))
$the_url = $a->get_baseurl() . '/redir/' . $item['contact-id'] . '?f=1&url=' . $mtch[1];
$the_url = z_root() . '/redir/' . $item['contact-id'] . '?f=1&url=' . $mtch[1];
else
$the_url = $mtch[1];
@ -1446,10 +1451,10 @@ function prepare_body(&$item,$attach = false, $preview = false) {
if(!$vhead) {
$vhead = true;
$a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), array(
'$baseurl' => $a->get_baseurl(),
'$baseurl' => z_root(),
));
$a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), array(
'$baseurl' => $a->get_baseurl(),
'$baseurl' => z_root(),
));
}
@ -1505,7 +1510,7 @@ function prepare_body(&$item,$attach = false, $preview = false) {
if($x) {
$s = preg_replace('/\<div class\=\"map\"\>/','$0' . $x,$s);
}
}
}
// Look for spoiler
@ -1522,7 +1527,7 @@ function prepare_body(&$item,$attach = false, $preview = false) {
$pos = strpos($s, $spoilersearch);
$rnd = random_string(8);
$spoilerreplace = '<br /> <span id="spoiler-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'spoiler-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'.
'<blockquote class="spoiler" id="spoiler-'.$rnd.'" style="display: none;">';
'<blockquote class="spoiler" id="spoiler-'.$rnd.'" style="display: none;">';
$s = substr($s, 0, $pos).$spoilerreplace.substr($s, $pos+strlen($spoilersearch));
}
@ -1534,16 +1539,16 @@ function prepare_body(&$item,$attach = false, $preview = false) {
$pos = strpos($s, $authorsearch);
$rnd = random_string(8);
$authorreplace = '<br /> <span id="author-wrap-'.$rnd.'" style="white-space:nowrap;" class="fakelink" onclick="openClose(\'author-'.$rnd.'\');">'.sprintf(t('Click to open/close')).'</span>'.
'<blockquote class="author" id="author-'.$rnd.'" style="display: block;">';
'<blockquote class="author" id="author-'.$rnd.'" style="display: block;">';
$s = substr($s, 0, $pos).$authorreplace.substr($s, $pos+strlen($authorsearch));
}
// replace friendica image url size with theme preference
if (x($a->theme_info,'item_image_size')){
$ps = $a->theme_info['item_image_size'];
// replace friendica image url size with theme preference
if (x($a->theme_info,'item_image_size')){
$ps = $a->theme_info['item_image_size'];
$s = preg_replace('|(<img[^>]+src="[^"]+/photo/[0-9a-f]+)-[0-9]|',"$1-".$ps, $s);
}
$s = preg_replace('|(<img[^>]+src="[^"]+/photo/[0-9a-f]+)-[0-9]|',"$1-".$ps, $s);
}
$prep_arr = array('item' => $item, 'html' => $s);
call_hooks('prepare_body_final', $prep_arr);
@ -1602,47 +1607,47 @@ function prepare_text($text) {
*/
function get_cats_and_terms($item) {
$a = get_app();
$categories = array();
$folders = array();
$a = get_app();
$categories = array();
$folders = array();
$matches = false; $first = true;
$cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$categories[] = array(
'name' => xmlify(file_tag_decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid'])?$a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&cat=' . xmlify(file_tag_decode($mtch[1])):""),
'first' => $first,
'last' => false
);
$first = false;
}
}
if (count($categories)) $categories[count($categories)-1]['last'] = true;
$matches = false; $first = true;
$cnt = preg_match_all('/<(.*?)>/',$item['file'],$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$categories[] = array(
'name' => xmlify(file_tag_decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid'])?z_root() . '/filerm/' . $item['id'] . '?f=&cat=' . xmlify(file_tag_decode($mtch[1])):""),
'first' => $first,
'last' => false
);
$first = false;
}
}
if (count($categories)) $categories[count($categories)-1]['last'] = true;
if(local_user() == $item['uid']) {
$matches = false; $first = true;
$cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$folders[] = array(
'name' => xmlify(file_tag_decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid'])?$a->get_baseurl() . '/filerm/' . $item['id'] . '?f=&term=' . xmlify(file_tag_decode($mtch[1])):""),
'first' => $first,
'last' => false
);
$first = false;
$matches = false; $first = true;
$cnt = preg_match_all('/\[(.*?)\]/',$item['file'],$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$folders[] = array(
'name' => xmlify(file_tag_decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid'])?z_root() . '/filerm/' . $item['id'] . '?f=&term=' . xmlify(file_tag_decode($mtch[1])):""),
'first' => $first,
'last' => false
);
$first = false;
}
}
}
}
}
if (count($folders)) $folders[count($folders)-1]['last'] = true;
if (count($folders)) $folders[count($folders)-1]['last'] = true;
return array($categories, $folders);
return array($categories, $folders);
}
@ -1665,7 +1670,7 @@ function feed_hublinks() {
if(! strlen($h))
continue;
if ($h === '[internal]')
$h = $a->get_baseurl() . '/pubsubhubbub';
$h = z_root() . '/pubsubhubbub';
$hubxml .= '<link rel="hub" href="' . xmlify($h) . '" />' . "\n" ;
}
}
@ -1684,12 +1689,12 @@ function feed_salmonlinks($nick) {
$a = get_app();
$salmon = '<link rel="salmon" href="' . xmlify($a->get_baseurl() . '/salmon/' . $nick) . '" />' . "\n" ;
$salmon = '<link rel="salmon" href="' . xmlify(z_root() . '/salmon/' . $nick) . '" />' . "\n" ;
// old style links that status.net still needed as of 12/2010
$salmon .= ' <link rel="http://salmon-protocol.org/ns/salmon-replies" href="' . xmlify($a->get_baseurl() . '/salmon/' . $nick) . '" />' . "\n" ;
$salmon .= ' <link rel="http://salmon-protocol.org/ns/salmon-mention" href="' . xmlify($a->get_baseurl() . '/salmon/' . $nick) . '" />' . "\n" ;
$salmon .= ' <link rel="http://salmon-protocol.org/ns/salmon-replies" href="' . xmlify(z_root() . '/salmon/' . $nick) . '" />' . "\n" ;
$salmon .= ' <link rel="http://salmon-protocol.org/ns/salmon-mention" href="' . xmlify(z_root() . '/salmon/' . $nick) . '" />' . "\n" ;
return $salmon;
}}
@ -1704,9 +1709,9 @@ function get_plink($item) {
if ($a->user['nickname'] != "") {
$ret = array(
//'href' => $a->get_baseurl()."/display/".$a->user['nickname']."/".$item['id'],
'href' => $a->get_baseurl()."/display/".$item['guid'],
'orig' => $a->get_baseurl()."/display/".$item['guid'],
//'href' => z_root()."/display/".$a->user['nickname']."/".$item['id'],
'href' => z_root()."/display/".$item['guid'],
'orig' => z_root()."/display/".$item['guid'],
'title' => t('View on separate page'),
'orig_title' => t('view on separate page'),
);
@ -1741,50 +1746,6 @@ function unamp($s) {
}}
if(! function_exists('lang_selector')) {
/**
* get html for language selector
* @global string $lang
* @return string
* @template lang_selector.tpl
*/
function lang_selector() {
global $lang;
$langs = glob('view/*/strings.php');
$lang_options = array();
$selected = "";
if(is_array($langs) && count($langs)) {
$langs[] = '';
if(! in_array('view/en/strings.php',$langs))
$langs[] = 'view/en/';
asort($langs);
foreach($langs as $l) {
if($l == '') {
$lang_options[""] = t('default');
continue;
}
$ll = substr($l,5);
$ll = substr($ll,0,strrpos($ll,'/'));
$selected = (($ll === $lang && (x($_SESSION, 'language'))) ? $ll : $selected);
$lang_options[$ll]=$ll;
}
}
$tpl = get_markup_template("lang_selector.tpl");
$o = replace_macros($tpl, array(
'$title' => t('Select an alternate language'),
'$langs' => array($lang_options, $selected),
));
return $o;
}}
if(! function_exists('return_bytes')) {
/**
* return number of bytes in size (K, M, G)
@ -1792,13 +1753,12 @@ if(! function_exists('return_bytes')) {
* @return number
*/
function return_bytes ($size_str) {
switch (substr ($size_str, -1))
{
case 'M': case 'm': return (int)$size_str * 1048576;
case 'K': case 'k': return (int)$size_str * 1024;
case 'G': case 'g': return (int)$size_str * 1073741824;
default: return $size_str;
}
switch (substr ($size_str, -1)) {
case 'M': case 'm': return (int)$size_str * 1048576;
case 'K': case 'k': return (int)$size_str * 1024;
case 'G': case 'g': return (int)$size_str * 1073741824;
default: return $size_str;
}
}}
/**
@ -1875,60 +1835,60 @@ if (!function_exists('str_getcsv')) {
* @param string $eol
* @return boolean|array False on error, otherwise array[row][column]
*/
function str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = '\\', $eol = '\n') {
if (is_string($input) && !empty($input)) {
$output = array();
$tmp = preg_split("/".$eol."/",$input);
if (is_array($tmp) && !empty($tmp)) {
while (list($line_num, $line) = each($tmp)) {
if (preg_match("/".$escape.$enclosure."/",$line)) {
while ($strlen = strlen($line)) {
$pos_delimiter = strpos($line,$delimiter);
$pos_enclosure_start = strpos($line,$enclosure);
if (
is_int($pos_delimiter) && is_int($pos_enclosure_start)
&& ($pos_enclosure_start < $pos_delimiter)
) {
$enclosed_str = substr($line,1);
$pos_enclosure_end = strpos($enclosed_str,$enclosure);
$enclosed_str = substr($enclosed_str,0,$pos_enclosure_end);
$output[$line_num][] = $enclosed_str;
$offset = $pos_enclosure_end+3;
} else {
if (empty($pos_delimiter) && empty($pos_enclosure_start)) {
$output[$line_num][] = substr($line,0);
$offset = strlen($line);
} else {
$output[$line_num][] = substr($line,0,$pos_delimiter);
$offset = (
!empty($pos_enclosure_start)
&& ($pos_enclosure_start < $pos_delimiter)
)
?$pos_enclosure_start
:$pos_delimiter+1;
}
}
$line = substr($line,$offset);
}
} else {
$line = preg_split("/".$delimiter."/",$line);
function str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = '\\', $eol = '\n') {
if (is_string($input) && !empty($input)) {
$output = array();
$tmp = preg_split("/".$eol."/",$input);
if (is_array($tmp) && !empty($tmp)) {
while (list($line_num, $line) = each($tmp)) {
if (preg_match("/".$escape.$enclosure."/",$line)) {
while ($strlen = strlen($line)) {
$pos_delimiter = strpos($line,$delimiter);
$pos_enclosure_start = strpos($line,$enclosure);
if (
is_int($pos_delimiter) && is_int($pos_enclosure_start)
&& ($pos_enclosure_start < $pos_delimiter)
) {
$enclosed_str = substr($line,1);
$pos_enclosure_end = strpos($enclosed_str,$enclosure);
$enclosed_str = substr($enclosed_str,0,$pos_enclosure_end);
$output[$line_num][] = $enclosed_str;
$offset = $pos_enclosure_end+3;
} else {
if (empty($pos_delimiter) && empty($pos_enclosure_start)) {
$output[$line_num][] = substr($line,0);
$offset = strlen($line);
} else {
$output[$line_num][] = substr($line,0,$pos_delimiter);
$offset = (
!empty($pos_enclosure_start)
&& ($pos_enclosure_start < $pos_delimiter)
)
?$pos_enclosure_start
:$pos_delimiter+1;
}
}
$line = substr($line,$offset);
}
} else {
$line = preg_split("/".$delimiter."/",$line);
/*
* Validating against pesky extra line breaks creating false rows.
*/
if (is_array($line) && !empty($line[0])) {
$output[$line_num] = $line;
}
}
}
return $output;
} else {
return false;
}
} else {
return false;
}
}
/*
* Validating against pesky extra line breaks creating false rows.
*/
if (is_array($line) && !empty($line[0])) {
$output[$line_num] = $line;
}
}
}
return $output;
} else {
return false;
}
} else {
return false;
}
}
}
/**
@ -1989,36 +1949,35 @@ function array_xmlify($val){
* @param string $base base url
* @return string
*/
function reltoabs($text, $base)
{
if (empty($base))
return $text;
function reltoabs($text, $base) {
if (empty($base))
return $text;
$base = rtrim($base,'/');
$base = rtrim($base,'/');
$base2 = $base . "/";
$base2 = $base . "/";
// Replace links
$pattern = "/<a([^>]*) href=\"(?!http|https|\/)([^\"]*)\"/";
$replace = "<a\${1} href=\"" . $base2 . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
// Replace links
$pattern = "/<a([^>]*) href=\"(?!http|https|\/)([^\"]*)\"/";
$replace = "<a\${1} href=\"" . $base2 . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
$pattern = "/<a([^>]*) href=\"(?!http|https)([^\"]*)\"/";
$replace = "<a\${1} href=\"" . $base . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
$pattern = "/<a([^>]*) href=\"(?!http|https)([^\"]*)\"/";
$replace = "<a\${1} href=\"" . $base . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
// Replace images
$pattern = "/<img([^>]*) src=\"(?!http|https|\/)([^\"]*)\"/";
$replace = "<img\${1} src=\"" . $base2 . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
// Replace images
$pattern = "/<img([^>]*) src=\"(?!http|https|\/)([^\"]*)\"/";
$replace = "<img\${1} src=\"" . $base2 . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
$pattern = "/<img([^>]*) src=\"(?!http|https)([^\"]*)\"/";
$replace = "<img\${1} src=\"" . $base . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
$pattern = "/<img([^>]*) src=\"(?!http|https)([^\"]*)\"/";
$replace = "<img\${1} src=\"" . $base . "\${2}\"";
$text = preg_replace($pattern, $replace, $text);
// Done
return $text;
// Done
return $text;
}
/**
@ -2063,36 +2022,36 @@ function file_tag_file_query($table,$s,$type = 'file') {
// ex. given music,video return <music><video> or [music][video]
function file_tag_list_to_file($list,$type = 'file') {
$tag_list = '';
if(strlen($list)) {
$list_array = explode(",",$list);
if($type == 'file') {
$lbracket = '[';
$rbracket = ']';
}
else {
$lbracket = '<';
$rbracket = '>';
}
$tag_list = '';
if(strlen($list)) {
$list_array = explode(",",$list);
if($type == 'file') {
$lbracket = '[';
$rbracket = ']';
}
else {
$lbracket = '<';
$rbracket = '>';
}
foreach($list_array as $item) {
foreach($list_array as $item) {
if(strlen($item)) {
$tag_list .= $lbracket . file_tag_encode(trim($item)) . $rbracket;
$tag_list .= $lbracket . file_tag_encode(trim($item)) . $rbracket;
}
}
}
}
return $tag_list;
return $tag_list;
}
// ex. given <music><video>[friends], return music,video or friends
function file_tag_file_to_list($file,$type = 'file') {
$matches = false;
$list = '';
if($type == 'file') {
$cnt = preg_match_all('/\[(.*?)\]/',$file,$matches,PREG_SET_ORDER);
$matches = false;
$list = '';
if($type == 'file') {
$cnt = preg_match_all('/\[(.*?)\]/',$file,$matches,PREG_SET_ORDER);
}
else {
$cnt = preg_match_all('/<(.*?)>/',$file,$matches,PREG_SET_ORDER);
else {
$cnt = preg_match_all('/<(.*?)>/',$file,$matches,PREG_SET_ORDER);
}
if($cnt) {
foreach($matches as $mtch) {
@ -2102,55 +2061,55 @@ function file_tag_file_to_list($file,$type = 'file') {
}
}
return $list;
return $list;
}
function file_tag_update_pconfig($uid,$file_old,$file_new,$type = 'file') {
// $file_old - categories previously associated with an item
// $file_new - new list of categories for an item
// $file_old - categories previously associated with an item
// $file_new - new list of categories for an item
if(! intval($uid))
return false;
if($file_old == $file_new)
return true;
if($file_old == $file_new)
return true;
$saved = get_pconfig($uid,'system','filetags');
if(strlen($saved)) {
if($type == 'file') {
$lbracket = '[';
$rbracket = ']';
if(strlen($saved)) {
if($type == 'file') {
$lbracket = '[';
$rbracket = ']';
$termtype = TERM_FILE;
}
else {
$lbracket = '<';
$rbracket = '>';
}
else {
$lbracket = '<';
$rbracket = '>';
$termtype = TERM_CATEGORY;
}
}
$filetags_updated = $saved;
$filetags_updated = $saved;
// check for new tags to be added as filetags in pconfig
$new_tags = array();
$check_new_tags = explode(",",file_tag_file_to_list($file_new,$type));
$new_tags = array();
$check_new_tags = explode(",",file_tag_file_to_list($file_new,$type));
foreach($check_new_tags as $tag) {
if(! stristr($saved,$lbracket . file_tag_encode($tag) . $rbracket))
$new_tags[] = $tag;
}
foreach($check_new_tags as $tag) {
if(! stristr($saved,$lbracket . file_tag_encode($tag) . $rbracket))
$new_tags[] = $tag;
}
$filetags_updated .= file_tag_list_to_file(implode(",",$new_tags),$type);
// check for deleted tags to be removed from filetags in pconfig
$deleted_tags = array();
$check_deleted_tags = explode(",",file_tag_file_to_list($file_old,$type));
$deleted_tags = array();
$check_deleted_tags = explode(",",file_tag_file_to_list($file_old,$type));
foreach($check_deleted_tags as $tag) {
if(! stristr($file_new,$lbracket . file_tag_encode($tag) . $rbracket))
$deleted_tags[] = $tag;
}
foreach($check_deleted_tags as $tag) {
if(! stristr($file_new,$lbracket . file_tag_encode($tag) . $rbracket))
$deleted_tags[] = $tag;
}
foreach($deleted_tags as $key => $tag) {
foreach($deleted_tags as $key => $tag) {
$r = q("SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d",
dbesc($tag),
intval(TERM_OBJ_POST),
@ -2161,23 +2120,23 @@ function file_tag_update_pconfig($uid,$file_old,$file_new,$type = 'file') {
// intval($uid)
//);
if(count($r)) {
unset($deleted_tags[$key]);
}
if(count($r)) {
unset($deleted_tags[$key]);
}
else {
$filetags_updated = str_replace($lbracket . file_tag_encode($tag) . $rbracket,'',$filetags_updated);
$filetags_updated = str_replace($lbracket . file_tag_encode($tag) . $rbracket,'',$filetags_updated);
}
}
if($saved != $filetags_updated) {
set_pconfig($uid,'system','filetags', $filetags_updated);
}
if($saved != $filetags_updated) {
set_pconfig($uid,'system','filetags', $filetags_updated);
}
return true;
}
else
if(strlen($file_new)) {
set_pconfig($uid,'system','filetags', $file_new);
}
else
if(strlen($file_new)) {
set_pconfig($uid,'system','filetags', $file_new);
}
return true;
}
@ -2187,13 +2146,13 @@ function file_tag_save_file($uid,$item,$file) {
$result = false;
if(! intval($uid))
return false;
$r = q("select file from item where id = %d and uid = %d limit 1",
$r = q("SELECT `file` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($item),
intval($uid)
);
if(count($r)) {
if(! stristr($r[0]['file'],'[' . file_tag_encode($file) . ']'))
q("update item set file = '%s' where id = %d and uid = %d",
q("UPDATE `item` SET `file` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'),
intval($item),
intval($uid)
@ -2225,14 +2184,14 @@ function file_tag_unsave_file($uid,$item,$file,$cat = false) {
}
$r = q("select file from item where id = %d and uid = %d limit 1",
$r = q("SELECT `file` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($item),
intval($uid)
);
if(! count($r))
return false;
q("update item set file = '%s' where id = %d and uid = %d",
q("UPDATE `item` SET `file` = '%s' WHERE `id` = %d AND `uid` = %d",
dbesc(str_replace($pattern,'',$r[0]['file'])),
intval($item),
intval($uid)
@ -2317,14 +2276,36 @@ function deindent($text, $chr="[\t ]", $count=NULL) {
return implode("\n", $lines);
}
function formatBytes($bytes, $precision = 2) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
function formatBytes($bytes, $precision = 2) {
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
return round($bytes, $precision) . ' ' . $units[$pow];
}
/**
* @brief translate and format the networkname of a contact
*
* @param string $network
* Networkname of the contact (e.g. dfrn, rss and so on)
* @param sting $url
* The contact url
* @return string
*/
function format_network_name($network, $url = 0) {
if ($network != "") {
require_once('include/contact_selectors.php');
if ($url != "")
$network_name = '<a href="'.$url.'">'.network_to_name($network, $url)."</a>";
else
$network_name = network_to_name($network);
return $network_name;
}
}

View File

@ -87,7 +87,6 @@ function add_shadow_entry($item) {
// Is there already a shadow entry?
$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item['uri']));
if (count($r))
return;

113
include/update_gcontact.php Normal file
View File

@ -0,0 +1,113 @@
<?php
require_once("boot.php");
function update_gcontact_run(&$argv, &$argc){
global $a, $db;
if(is_null($a)) {
$a = new App;
}
if(is_null($db)) {
@include(".htconfig.php");
require_once("include/dba.php");
$db = new dba($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
};
require_once('include/pidfile.php');
require_once('include/Scrape.php');
require_once("include/socgraph.php");
load_config('config');
load_config('system');
$a->set_baseurl(get_config('system','url'));
load_hooks();
logger('update_gcontact: start');
if(($argc > 1) && (intval($argv[1])))
$contact_id = intval($argv[1]);
if(!$contact_id) {
logger('update_gcontact: no contact');
return;
}
$lockpath = get_lockpath();
if ($lockpath != '') {
$pidfile = new pidfile($lockpath, 'update_gcontact'.$contact_id);
if ($pidfile->is_already_running()) {
logger("update_gcontact: Already running for contact ".$contact_id);
if ($pidfile->running_time() > 9*60) {
$pidfile->kill();
logger("killed stale process");
}
exit;
}
}
$r = q("SELECT * FROM `gcontact` WHERE `id` = %d", intval($contact_id));
if (!$r)
return;
if (!in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
return;
$data = probe_url($r[0]["url"]);
if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) {
if ($r[0]["server_url"] != "")
poco_check_server($r[0]["server_url"], $r[0]["network"]);
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `id` = %d",
dbesc(datetime_convert()), intval($contact_id));
return;
}
if (($data["name"] == "") AND ($r[0]['name'] != ""))
$data["name"] = $r[0]['name'];
if (($data["nick"] == "") AND ($r[0]['nick'] != ""))
$data["nick"] = $r[0]['nick'];
if (($data["addr"] == "") AND ($r[0]['addr'] != ""))
$data["addr"] = $r[0]['addr'];
if (($data["photo"] == "") AND ($r[0]['photo'] != ""))
$data["photo"] = $r[0]['photo'];
q("UPDATE `gcontact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `photo` = '%s'
WHERE `id` = %d",
dbesc($data["name"]),
dbesc($data["nick"]),
dbesc($data["addr"]),
dbesc($data["photo"]),
intval($contact_id)
);
q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `photo` = '%s'
WHERE `uid` = 0 AND `addr` = '' AND `nurl` = '%s'",
dbesc($data["name"]),
dbesc($data["nick"]),
dbesc($data["addr"]),
dbesc($data["photo"]),
dbesc(normalise_link($data["url"]))
);
q("UPDATE `contact` SET `addr` = '%s'
WHERE `uid` != 0 AND `addr` = '' AND `nurl` = '%s'",
dbesc($data["addr"]),
dbesc(normalise_link($data["url"]))
);
}
if (array_search(__file__,get_included_files())===0){
update_gcontact_run($_SERVER["argv"],$_SERVER["argc"]);
killme();
}

View File

@ -48,7 +48,7 @@ function create_user($arr) {
$result['message'] .= t('An invitation is required.') . EOL;
return $result;
}
$r = q("select * from register where `hash` = '%s' limit 1", dbesc($invite_id));
$r = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", dbesc($invite_id));
if(! results($r)) {
$result['message'] .= t('Invitation could not be verified.') . EOL;
return $result;
@ -66,7 +66,7 @@ function create_user($arr) {
require_once('library/openid.php');
$openid = new LightOpenID;
$openid->identity = $openid_url;
$openid->returnUrl = $a->get_baseurl() . '/openid';
$openid->returnUrl = z_root() . '/openid';
$openid->required = array('namePerson/friendly', 'contact/email', 'namePerson');
$openid->optional = array('namePerson/first','media/image/aspect11','media/image/default');
try {
@ -138,9 +138,10 @@ function create_user($arr) {
if(! preg_match("/^[a-z0-9][a-z0-9\_]*$/",$nickname))
$result['message'] .= t('Your "nickname" can only contain "a-z", "0-9" and "_".') . EOL;
$r = q("SELECT `uid` FROM `user`
WHERE `nickname` = '%s' LIMIT 1",
dbesc($nickname)
WHERE `nickname` = '%s' LIMIT 1",
dbesc($nickname)
);
if(count($r))
$result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
@ -149,8 +150,8 @@ function create_user($arr) {
// but could be a security issue for federated platforms.
$r = q("SELECT * FROM `userd`
WHERE `username` = '%s' LIMIT 1",
dbesc($nickname)
WHERE `username` = '%s' LIMIT 1",
dbesc($nickname)
);
if(count($r))
$result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL;
@ -237,8 +238,8 @@ function create_user($arr) {
*/
$r = q("SELECT `uid` FROM `user`
WHERE `nickname` = '%s' ",
dbesc($nickname)
WHERE `nickname` = '%s' ",
dbesc($nickname)
);
if((count($r) > 1) && $newuid) {
$result['message'] .= t('Nickname is already registered. Please choose another.') . EOL;
@ -255,8 +256,8 @@ function create_user($arr) {
t('default'),
1,
dbesc($username),
dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"),
dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"),
dbesc(z_root() . "/photo/profile/{$newuid}.jpg"),
dbesc(z_root() . "/photo/avatar/{$newuid}.jpg"),
intval($publish),
intval($netpublish)
@ -269,22 +270,23 @@ function create_user($arr) {
return $result;
}
$r = q("INSERT INTO `contact` ( `uid`, `created`, `self`, `name`, `nick`, `photo`, `thumb`, `micro`, `blocked`, `pending`, `url`, `nurl`,
`request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness` )
VALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0 ) ",
`addr`, `request`, `notify`, `poll`, `confirm`, `poco`, `name-date`, `uri-date`, `avatar-date`, `closeness` )
VALUES ( %d, '%s', 1, '%s', '%s', '%s', '%s', '%s', 0, 0, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', 0 ) ",
intval($newuid),
datetime_convert(),
dbesc($username),
dbesc($nickname),
dbesc($a->get_baseurl() . "/photo/profile/{$newuid}.jpg"),
dbesc($a->get_baseurl() . "/photo/avatar/{$newuid}.jpg"),
dbesc($a->get_baseurl() . "/photo/micro/{$newuid}.jpg"),
dbesc($a->get_baseurl() . "/profile/$nickname"),
dbesc(normalise_link($a->get_baseurl() . "/profile/$nickname")),
dbesc($a->get_baseurl() . "/dfrn_request/$nickname"),
dbesc($a->get_baseurl() . "/dfrn_notify/$nickname"),
dbesc($a->get_baseurl() . "/dfrn_poll/$nickname"),
dbesc($a->get_baseurl() . "/dfrn_confirm/$nickname"),
dbesc($a->get_baseurl() . "/poco/$nickname"),
dbesc(z_root() . "/photo/profile/{$newuid}.jpg"),
dbesc(z_root() . "/photo/avatar/{$newuid}.jpg"),
dbesc(z_root() . "/photo/micro/{$newuid}.jpg"),
dbesc(z_root() . "/profile/$nickname"),
dbesc(normalise_link(z_root() . "/profile/$nickname")),
dbesc($nickname . '@' . substr(z_root(), strpos(z_root(),'://') + 3 )),
dbesc(z_root() . "/dfrn_request/$nickname"),
dbesc(z_root() . "/dfrn_notify/$nickname"),
dbesc(z_root() . "/dfrn_poll/$nickname"),
dbesc(z_root() . "/dfrn_confirm/$nickname"),
dbesc(z_root() . "/poco/$nickname"),
dbesc(datetime_convert()),
dbesc(datetime_convert()),
dbesc(datetime_convert())
@ -296,23 +298,23 @@ function create_user($arr) {
require_once('include/group.php');
group_add($newuid, t('Friends'));
$r = q("SELECT id FROM `group` WHERE uid = %d AND name = '%s'",
$r = q("SELECT `id` FROM `group` WHERE `uid` = %d AND `name` = '%s'",
intval($newuid),
dbesc(t('Friends'))
);
if($r && count($r)) {
$def_gid = $r[0]['id'];
q("UPDATE user SET def_gid = %d WHERE uid = %d",
q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d",
intval($r[0]['id']),
intval($newuid)
);
}
if(get_config('system', 'newuser_private') && $def_gid) {
q("UPDATE user SET allow_gid = '%s' WHERE uid = %d",
dbesc("<" . $def_gid . ">"),
intval($newuid)
q("UPDATE `user` SET `allow_gid` = '%s' WHERE `uid` = %d",
dbesc("<" . $def_gid . ">"),
intval($newuid)
);
}

View File

@ -56,10 +56,11 @@ if(!$install) {
$maxsysload_frontend = intval(get_config('system','maxloadavg_frontend'));
if($maxsysload_frontend < 1)
$maxsysload_frontend = 50;
if(function_exists('sys_getloadavg')) {
$load = sys_getloadavg();
if(intval($load[0]) > $maxsysload_frontend) {
logger('system: load ' . $load[0] . ' too high. Service Temporarily Unavailable.');
$load = current_load();
if($load) {
if($load > $maxsysload_frontend) {
logger('system: load ' . $load . ' too high. Service Temporarily Unavailable.');
header($_SERVER["SERVER_PROTOCOL"].' 503 Service Temporarily Unavailable');
header('Retry-After: 300');
die("System is currently unavailable. Please try again later");
@ -102,13 +103,13 @@ session_start();
* Language was set earlier, but we can over-ride it in the session.
* We have to do it here because the session was just now opened.
*/
if(array_key_exists('system_language',$_POST)) {
if(strlen($_POST['system_language']))
$_SESSION['language'] = $_POST['system_language'];
else
unset($_SESSION['language']);
if (x($_SESSION,'authenticated') && !x($_SESSION,'language')) {
// we didn't loaded user data yet, but we need user language
$r = q("SELECT language FROM user WHERE uid=%d", intval($_SESSION['uid']));
$_SESSION['language'] = $lang;
if (count($r)>0) $_SESSION['language'] = $r[0]['language'];
}
if((x($_SESSION,'language')) && ($_SESSION['language'] !== $lang)) {
$lang = $_SESSION['language'];
load_translation_table($lang);

View File

@ -1,7 +1,7 @@
/**
* Filebrowser - Friendica Communications Server
*
* Copyright (c) 2010-2013 the Friendica Project
* Copyright (c) 2010-2015 the Friendica Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@ -13,33 +13,34 @@
*
* To load filebrowser in colorbox, call
*
* $.colorbox({href: ulr, iframe:true,innerWidth:'500px',innerHeight:'400px'})
* Dialog.doImageBrowser(eventname, id);
*
* where url is:
* or
*
* <baseurl>/fbrowser/<type>/?mode=minimal[#<eventname>-<id>]
* Dialog.doFileBrowser(eventname, id);
*
* where:
*
* baseurl: baseurl from friendica
* type: one of "image", "file"
* eventname: event name to catch return value
* id: id returned to event handler
*
* When user select an item, an event in fired in parent page, on body element
* The event is named
* When user select an item, an event in fired in parent page, on body element
* The event is named
*
* fbrowser.<type>.[<eventname>]
*
* with params:
* <type> will be one of "image" or "file", and the event handler will
* get the following params:
*
* filemane: filename of item choosed by user
* embed: bbcode to embed element into posts
* id: id from url
* id: id from caller code
*
* example:
* example:
*
* // open dialog for select an image for a textarea with id "myeditor"
* var id="myeditor";
* $.colorbox({href: baseurl + "/fbrowser/image/?mode=minimal#example-"+id, iframe:true,innerWidth:'500px',innerHeight:'400px'})
* // open dialog for select an image for a textarea with id "myeditor"
* var id="myeditor";
* Dialog.doImageBrowser("example", id);
*
* // setup event handler to get user selection
* $("body").on("fbrowser.image.example", function(event, filename, bbcode, id) {

View File

@ -3,9 +3,9 @@
*
* require jQuery, jquery.textareas
*/
function ACPopup(elm,backend_url){
this.idsel=-1;
this.element = elm;
@ -23,18 +23,19 @@ function ACPopup(elm,backend_url){
var h = 130;
if(typeof elm.editorId == "undefined") {
if(tinyMCE.activeEditor == null) {
style = $(elm).offset();
w = $(elm).width();
h = $(elm).height();
}
else {
var container = elm.getContainer();
if(typeof container != "undefined") {
style = $(container).offset();
w = $(container).width();
h = $(container).height();
}
// 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;
@ -43,15 +44,15 @@ function ACPopup(elm,backend_url){
/* 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(){
@ -64,7 +65,7 @@ ACPopup.prototype.search = function(text){
if (this.kp_timer) clearTimeout(this.kp_timer);
this.kp_timer = setTimeout( function(){that._search();}, 500);
}
ACPopup.prototype._search = function(){
ACPopup.prototype._search = function(){
console.log("_search");
var that = this;
var postdata = {
@ -74,7 +75,7 @@ ACPopup.prototype._search = function(){
type:'c',
conversation: this.conversation_id,
}
$.ajax({
type:'POST',
url: this.url,
@ -87,15 +88,15 @@ ACPopup.prototype._search = function(){
$(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;
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;
@ -141,12 +142,12 @@ ACPopup.prototype.onkey = function(event){
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();
}
@ -156,14 +157,14 @@ 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){
@ -174,15 +175,15 @@ function ContactAutocomplete(element,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;}
}
}
});
});
}
@ -199,4 +200,4 @@ function ContactAutocomplete(element,backend_url){

View File

@ -1,23 +1,38 @@
function resizeIframe(obj) {
obj.style.height = 0;
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
_resizeIframe(obj, 0);
}
function _resizeIframe(obj, desth) {
var h = obj.style.height;
var ch = obj.contentWindow.document.body.scrollHeight + 'px';
if (h==ch) {
return;
}
console.log("_resizeIframe", obj, desth, ch);
if (desth!=ch) {
setTimeout(_resizeIframe, 500, obj, ch);
} else {
obj.style.height = ch;
setTimeout(_resizeIframe, 1000, obj, ch);
}
}
function openClose(theID) {
if(document.getElementById(theID).style.display == "block") {
document.getElementById(theID).style.display = "none"
if(document.getElementById(theID).style.display == "block") {
document.getElementById(theID).style.display = "none"
}
else {
document.getElementById(theID).style.display = "block"
}
else {
document.getElementById(theID).style.display = "block"
}
}
function openMenu(theID) {
document.getElementById(theID).style.display = "block"
document.getElementById(theID).style.display = "block"
}
function closeMenu(theID) {
document.getElementById(theID).style.display = "none"
document.getElementById(theID).style.display = "none"
}
@ -50,14 +65,14 @@
if (e.hasClass("ttright")) pos="right";
e.tipTip({defaultPosition: pos, edgeOffset: 8});
});*/
/* setup comment textarea buttons */
/* comment textarea buttons needs some "data-*" attributes to work:
* data-role="insert-formatting" : to mark the element as a formatting button
* data-comment="<string>" : string for "Comment", used by insertFormatting() function
* data-bbcode="<string>" : name of the bbcode element to insert. insertFormatting() will insert it as "[name][/name]"
* data-id="<string>" : id of the comment, used to find other comment-related element, like the textarea
* */
* */
$('body').on('click','[data-role="insert-formatting"]', function(e) {
e.preventDefault();
var o = $(this);
@ -65,10 +80,9 @@
var bbcode = o.data('bbcode');
var id = o.data('id');
if (bbcode=="img") {
$.colorbox({href: baseurl + "/fbrowser/image/?mode=minimal#comment-"+id, iframe:true,innerWidth:'500px',innerHeight:'400px'})
return;
Dialog.doImageBrowser("comment", id);
return;
}
insertFormatting(comment, bbcode, id);
});
@ -82,18 +96,18 @@
var end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start) + bbcode + textarea.value.substring(end, textarea.value.length);
});
/* setup onoff widgets */
$(".onoff input").each(function(){
val = $(this).val();
id = $(this).attr("id");
$("#"+id+"_onoff ."+ (val==0?"on":"off")).addClass("hidden");
});
$(".onoff > a").click(function(event){
event.preventDefault();
event.preventDefault();
var input = $(this).siblings("input");
var val = 1-input.val();
var id = input.attr("id");
@ -102,7 +116,7 @@
input.val(val);
//console.log(id);
});
/* setup field_richtext */
setupFieldRichtext();
@ -139,22 +153,22 @@
$('html').click(function() {
close_last_popup_menu();
});
// fancyboxes
$("a.popupbox").colorbox({
'inline' : true,
'transition' : 'elastic'
});
/* notifications template */
var notifications_tpl= unescape($("#nav-notifications-template[rel=template]").html());
var notifications_all = unescape($('<div>').append( $("#nav-notifications-see-all").clone() ).html()); //outerHtml hack
var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
var notifications_empty = unescape($("#nav-notifications-menu").html());
/* nav update event */
$('nav').bind('nav-update', function(e,data){;
$('nav').bind('nav-update', function(e,data){
var invalid = $(data).find('invalid').text();
if(invalid == 1) { window.location.href=window.location.href }
@ -165,7 +179,7 @@
var home = $(data).find('home').text();
if(home == 0) { home = ''; $('#home-update').removeClass('show') } else { $('#home-update').addClass('show') }
$('#home-update').html(home);
var intro = $(data).find('intro').text();
if(intro == 0) { intro = ''; $('#intro-update').removeClass('show') } else { $('#intro-update').addClass('show') }
$('#intro-update').html(intro);
@ -173,7 +187,7 @@
var mail = $(data).find('mail').text();
if(mail == 0) { mail = ''; $('#mail-update').removeClass('show') } else { $('#mail-update').addClass('show') }
$('#mail-update').html(mail);
var intro = $(data).find('intro').text();
if(intro == 0) { intro = ''; $('#intro-update-li').removeClass('show') } else { $('#intro-update-li').addClass('show') }
$('#intro-update-li').html(intro);
@ -204,9 +218,23 @@
var birthdaystoday = $(data).find('birthdays-today').text();
if(birthdaystoday == 0) { $('#birthdays-update').removeClass('notif-birthdays-today') } else { $('#birthdays-update').addClass('notif-birthdays-today') }
$(".sidebar-group-li .notify").removeClass("show");
$(data).find("group").each(function() {
var gid = this.id;
var gcount = this.innerHTML;
$(".group-"+gid+" .notify").addClass("show").text(gcount);
});
$(".forum-widget-entry .notify").removeClass("show");
$(data).find("forum").each(function() {
var fid = this.id;
var fcount = this.innerHTML;
$(".forum-"+fid+" .notify").addClass("show").text(fcount);
});
var eNotif = $(data).find('notif')
if (eNotif.children("note").length==0){
$("#nav-notifications-menu").html(notifications_empty);
} else {
@ -244,7 +272,7 @@
});
}
}
});
notification_lastitem = notification_id;
localStorage.setItem("notification-lastitem", notification_lastitem)
@ -267,7 +295,7 @@
}
if(notif == 0) { notif = ''; $('#notify-update').removeClass('show') } else { $('#notify-update').addClass('show') }
$('#notify-update').html(notif);
var eSysmsg = $(data).find('sysmsgs');
eSysmsg.children("notice").each(function(){
text = $(this).text();
@ -277,10 +305,10 @@
text = $(this).text();
$.jGrowl(text, { sticky: false, theme: 'info', life: 5000 });
});
});
NavUpdate();
NavUpdate();
// Allow folks to stop the ajax page updates with the pause/break key
$(document).keydown(function(event) {
if(event.keyCode == '8') {
@ -306,8 +334,8 @@
}
}
});
});
function NavUpdate() {
@ -318,8 +346,8 @@
$(data).find('result').each(function() {
// send nav-update event
$('nav').trigger('nav-update', this);
// start live update
if($('#live-network').length) { src = 'network'; liveUpdate(); }
@ -330,19 +358,19 @@
/* if($('#live-display').length) {
if(liking) {
liking = 0;
window.location.href=window.location.href
window.location.href=window.location.href
}
}*/
if($('#live-photos').length) {
if($('#live-photos').length) {
if(liking) {
liking = 0;
window.location.href=window.location.href
window.location.href=window.location.href
}
}
});
}) ;
}
@ -432,8 +460,8 @@
});
$('#' + prev).after($(this));
}
else {
$('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
else {
$('#' + ident + ' ' + '.wall-item-ago').replaceWith($(this).find('.wall-item-ago'));
if($('#' + ident + ' ' + '.comment-edit-text-empty').length)
$('#' + ident + ' ' + '.wall-item-comment-wrapper').replaceWith($(this).find('.wall-item-comment-wrapper'));
$('#' + ident + ' ' + '.hide-comments-total').replaceWith($(this).find('.hide-comments-total'));
@ -443,7 +471,7 @@
$(this).attr('src',$(this).attr('dst'));
});
}
prev = ident;
prev = ident;
});
*/
$('.like-rotator').hide();
@ -467,10 +495,10 @@
$(node).removeClass("drop").addClass("drophide");
}
// Since our ajax calls are asynchronous, we will give a few
// seconds for the first ajax call (setting like/dislike), then
// Since our ajax calls are asynchronous, we will give a few
// seconds for the first ajax call (setting like/dislike), then
// run the updater to pick up any changes and display on the page.
// The updater will turn any rotators off when it's done.
// The updater will turn any rotators off when it's done.
// This function will have returned long before any of these
// events have completed and therefore there won't be any
// visible feedback that anything changed without all this
@ -582,14 +610,14 @@
commentBusy = true;
$('body').css('cursor', 'wait');
$("#comment-preview-inp-" + id).val("0");
$.post(
"item",
$("#comment-edit-form-" + id).serialize(),
$.post(
"item",
$("#comment-edit-form-" + id).serialize(),
function(data) {
if(data.success) {
$("#comment-edit-wrapper-" + id).hide();
$("#comment-edit-text-" + id).val('');
var tarea = document.getElementById("comment-edit-text-" + id);
var tarea = document.getElementById("comment-edit-text-" + id);
if(tarea)
commentClose(tarea,id);
if(timer) clearTimeout(timer);
@ -600,28 +628,27 @@
window.location.href=data.reload;
}
},
"json"
);
return false;
"json"
);
return false;
}
function preview_comment(id) {
$("#comment-preview-inp-" + id).val("1");
$("#comment-edit-preview-" + id).show();
$.post(
"item",
$("#comment-edit-form-" + id).serialize(),
$.post(
"item",
$("#comment-edit-form-" + id).serialize(),
function(data) {
if(data.preview) {
$("#comment-edit-preview-" + id).html(data.preview);
$("#comment-edit-preview-" + id + " a").click(function() { return false; });
}
},
"json"
);
return true;
"json"
);
return true;
}
@ -643,19 +670,19 @@
$("#jot-preview").val("1");
$("#jot-preview-content").show();
tinyMCE.triggerSave();
$.post(
"item",
$.post(
"item",
$("#profile-jot-form").serialize(),
function(data) {
if(data.preview) {
if(data.preview) {
$("#jot-preview-content").html(data.preview);
$("#jot-preview-content" + " a").click(function() { return false; });
}
},
"json"
);
"json"
);
$("#jot-preview").val("0");
return true;
return true;
}
@ -663,38 +690,38 @@
// unpause auto reloads if they are currently stopped
totStopped = false;
stopped = false;
$('#pause').html('');
$('#pause').html('');
}
function bin2hex(s){
// Converts the binary representation of data to hex
//
// version: 812.316
// discuss at: http://phpjs.org/functions/bin2hex
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// + bugfixed by: Linuxworld
// * example 1: bin2hex('Kev');
// * returns 1: '4b6576'
// * example 2: bin2hex(String.fromCharCode(0x00));
// * returns 2: '00'
var v,i, f = 0, a = [];
s += '';
f = s.length;
for (i = 0; i<f; i++) {
a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
}
return a.join('');
}
function bin2hex(s){
// Converts the binary representation of data to hex
//
// version: 812.316
// discuss at: http://phpjs.org/functions/bin2hex
// + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// + bugfixed by: Linuxworld
// * example 1: bin2hex('Kev');
// * returns 1: '4b6576'
// * example 2: bin2hex(String.fromCharCode(0x00));
// * returns 2: '00'
var v,i, f = 0, a = [];
s += '';
f = s.length;
for (i = 0; i<f; i++) {
a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/,"0$1");
}
return a.join('');
}
function groupChangeMember(gid, cid, sec_token) {
$('body .fakelink').css('cursor', 'wait');
$.get('group/' + gid + '/' + cid + "?t=" + sec_token, function(data) {
$('#group-update-wrapper').html(data);
$('body .fakelink').css('cursor', 'auto');
$('body .fakelink').css('cursor', 'auto');
});
}
@ -702,7 +729,7 @@
$('body .fakelink').css('cursor', 'wait');
$.get('profperm/' + gid + '/' + cid, function(data) {
$('#prof-update-wrapper').html(data);
$('body .fakelink').css('cursor', 'auto');
$('body .fakelink').css('cursor', 'auto');
});
}
@ -784,9 +811,9 @@ function setupFieldRichtext(){
}
/**
* sprintf in javascript
* "{0} and {1}".format('zero','uno');
/**
* sprintf in javascript
* "{0} and {1}".format('zero','uno');
**/
String.prototype.format = function() {
var formatted = this;
@ -826,3 +853,68 @@ function getNotificationPermission() {
return Notification.permission;
}
}
/**
* Show a dialog loaded from an url
* By defaults this load the url in an iframe in colorbox
* Themes can overwrite `show()` function to personalize it
*/
var Dialog = {
/**
* Show the dialog
*
* @param string url
* @return object colorbox
*/
show : function (url) {
var size = Dialog._get_size();
return $.colorbox({href: url, iframe:true,innerWidth: size.width+'px',innerHeight: size.height+'px'})
},
/**
* Show the Image browser dialog
*
* @param string name
* @param string id (optional)
* @return object
*
* The name will be used to build the event name
* fired by image browser dialog when the user select
* an image. The optional id will be passed as argument
* to the event handler
*/
doImageBrowser : function (name, id) {
var url = Dialog._get_url("image",name,id);
return Dialog.show(url);
},
/**
* Show the File browser dialog
*
* @param string name
* @param string id (optional)
* @return object
*
* The name will be used to build the event name
* fired by file browser dialog when the user select
* a file. The optional id will be passed as argument
* to the event handler
*/
doFileBrowser : function (name, id) {
var url = Dialog._get_url("file",name,id);
return Dialog.show(url);
},
_get_url : function(type, name, id) {
var hash = name;
if (id !== undefined) hash = hash + "-" + id;
return baseurl + "/fbrowser/"+type+"/?mode=minimal#"+hash;
},
_get_size: function() {
return {
width: window.innerWidth-50,
height: window.innerHeight-100
};
}
}

View File

@ -47,12 +47,35 @@ function admin_post(&$a){
return; // NOTREACHED
break;
case 'themes':
if ($a->argc < 2) {
if(is_ajax()) return;
goaway($a->get_baseurl(true) . '/admin/' );
return;
}
$theme = $a->argv[2];
if (is_file("view/theme/$theme/config.php")){
require_once("view/theme/$theme/config.php");
if (function_exists("theme_admin_post")){
theme_admin_post($a);
function __call_theme_admin_post(&$a, $theme) {
$orig_theme = $a->theme;
$orig_page = $a->page;
$orig_session_theme = $_SESSION['theme'];
require_once("view/theme/$theme/theme.php");
require_once("view/theme/$theme/config.php");
$_SESSION['theme'] = $theme;
$init = $theme."_init";
if(function_exists($init)) $init($a);
if(function_exists("theme_admin_post")){
$admin_form = theme_admin_post($a);
}
$_SESSION['theme'] = $orig_session_theme;
$a->theme = $orig_theme;
$a->page = $orig_page;
return $admin_form;
}
__call_theme_admin_post($a, $theme);
}
info(t('Theme settings updated.'));
if(is_ajax()) return;
@ -112,7 +135,7 @@ function admin_content(&$a) {
/* get plugins admin page */
$r = q("SELECT name FROM `addon` WHERE `plugin_admin`=1");
$r = q("SELECT `name` FROM `addon` WHERE `plugin_admin`=1 ORDER BY `name`");
$aside['plugins_admin']=Array();
foreach ($r as $h){
$plugin =$h['name'];
@ -386,6 +409,8 @@ function admin_page_site_post(&$a){
$poll_interval = ((x($_POST,'poll_interval')) ? intval(trim($_POST['poll_interval'])) : 0);
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
$maxloadavg_frontend = ((x($_POST,'maxloadavg_frontend')) ? intval(trim($_POST['maxloadavg_frontend'])) : 50);
$optimize_max_tablesize = ((x($_POST,'optimize_max_tablesize')) ? intval(trim($_POST['optimize_max_tablesize'])): 100);
$optimize_fragmentation = ((x($_POST,'optimize_fragmentation')) ? intval(trim($_POST['optimize_fragmentation'])): 30);
$poco_completion = ((x($_POST,'poco_completion')) ? intval(trim($_POST['poco_completion'])) : false);
$poco_requery_days = ((x($_POST,'poco_requery_days')) ? intval(trim($_POST['poco_requery_days'])) : 7);
$poco_discovery = ((x($_POST,'poco_discovery')) ? intval(trim($_POST['poco_discovery'])) : 0);
@ -416,6 +441,11 @@ function admin_page_site_post(&$a){
$rino = ((x($_POST,'rino')) ? intval($_POST['rino']) : 0);
$embedly = ((x($_POST,'embedly')) ? notags(trim($_POST['embedly'])) : '');
if ($a->get_path() != "")
$diaspora_enabled = false;
if (!$thread_allow)
$ostatus_disabled = true;
if($ssl_policy != intval(get_config('system','ssl_policy'))) {
if($ssl_policy == SSL_POLICY_FULL) {
@ -462,6 +492,8 @@ function admin_page_site_post(&$a){
set_config('system','poll_interval',$poll_interval);
set_config('system','maxloadavg',$maxloadavg);
set_config('system','maxloadavg_frontend',$maxloadavg_frontend);
set_config('system','optimize_max_tablesize',$optimize_max_tablesize);
set_config('system','optimize_fragmentation',$optimize_fragmentation);
set_config('system','poco_completion',$poco_completion);
set_config('system','poco_requery_days',$poco_requery_days);
set_config('system','poco_discovery',$poco_discovery);
@ -535,6 +567,7 @@ function admin_page_site_post(&$a){
set_config('system','ostatus_disabled', $ostatus_disabled);
set_config('system','ostatus_poll_interval', $ostatus_poll_interval);
set_config('system','diaspora_enabled', $diaspora_enabled);
set_config('config','private_addons', $private_addons);
set_config('system','force_ssl', $force_ssl);
@ -551,10 +584,10 @@ function admin_page_site_post(&$a){
set_config('system','old_pager', $old_pager);
set_config('system','only_tag_search', $only_tag_search);
if ($rino==2 and !function_exists('mcrypt_create_iv')){
notice(t("RINO2 needs mcrypt php extension to work."));
} else {
notice(t("RINO2 needs mcrypt php extension to work."));
} else {
set_config('system','rino_encrypt', $rino);
}
@ -574,18 +607,7 @@ function admin_page_site_post(&$a){
function admin_page_site(&$a) {
/* Installed langs */
$lang_choices = array();
$langs = glob('view/*/strings.php'); /**/
if(is_array($langs) && count($langs)) {
if(! in_array('view/en/strings.php',$langs))
$langs[] = 'view/en/';
asort($langs);
foreach($langs as $l) {
$t = explode("/",$l);
$lang_choices[$t[1]] = $t[1];
}
}
$lang_choices = get_avaiable_languages();
if (strlen(get_config('system','directory_submit_url')) AND
!strlen(get_config('system','directory'))) {
@ -597,58 +619,60 @@ function admin_page_site(&$a) {
$theme_choices = array();
$theme_choices_mobile = array();
$theme_choices_mobile["---"] = t("No special theme for mobile devices");
$files = glob('view/theme/*');
$files = glob('view/theme/*'); /**/
if($files) {
foreach($files as $file) {
if (intval(file_exists($file . '/unsupported')))
continue;
$f = basename($file);
$theme_name = ((file_exists($file . '/experimental')) ? sprintf("%s - \x28Experimental\x29", $f) : $f);
if (file_exists($file . '/mobile')) {
$theme_choices_mobile[$f] = $theme_name;
}
else {
} else {
$theme_choices[$f] = $theme_name;
}
}
}
}
/* Community page style */
$community_page_style_choices = array(
CP_NO_COMMUNITY_PAGE => t("No community page"),
CP_USERS_ON_SERVER => t("Public postings from users of this site"),
CP_GLOBAL_COMMUNITY => t("Global community page")
);
/* Community page style */
$community_page_style_choices = array(
CP_NO_COMMUNITY_PAGE => t("No community page"),
CP_USERS_ON_SERVER => t("Public postings from users of this site"),
CP_GLOBAL_COMMUNITY => t("Global community page")
);
/* OStatus conversation poll choices */
$ostatus_poll_choices = array(
"-2" => t("Never"),
"-1" => t("At post arrival"),
"0" => t("Frequently"),
"60" => t("Hourly"),
"720" => t("Twice daily"),
"1440" => t("Daily")
);
/* OStatus conversation poll choices */
$ostatus_poll_choices = array(
"-2" => t("Never"),
"-1" => t("At post arrival"),
"0" => t("Frequently"),
"60" => t("Hourly"),
"720" => t("Twice daily"),
"1440" => t("Daily")
);
$poco_discovery_choices = array(
"0" => t("Disabled"),
"1" => t("Users"),
"2" => t("Users, Global Contacts"),
"3" => t("Users, Global Contacts/fallback"),
);
$poco_discovery_choices = array(
"0" => t("Disabled"),
"1" => t("Users"),
"2" => t("Users, Global Contacts"),
"3" => t("Users, Global Contacts/fallback"),
);
$poco_discovery_since_choices = array(
"30" => t("One month"),
"91" => t("Three months"),
"182" => t("Half a year"),
"365" => t("One year"),
);
$poco_discovery_since_choices = array(
"30" => t("One month"),
"91" => t("Three months"),
"182" => t("Half a year"),
"365" => t("One year"),
);
/* get user names to make the install a personal install of X */
$user_names = array();
$user_names['---'] = t('Multi user instance');
$users = q("SELECT username, nickname FROM `user`");
foreach ($users as $user) {
$user_names[$user['nickname']] = $user['username'];
}
/* 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`");
foreach ($users as $user) {
$user_names[$user['nickname']] = $user['username'];
}
/* Banner */
$banner = get_config('system','banner');
@ -681,6 +705,8 @@ function admin_page_site(&$a) {
if ($a->config['hostname'] == "")
$a->config['hostname'] = $a->get_hostname();
$diaspora_able = ($a->get_path() == "");
$t = get_markup_template("admin_site.tpl");
return replace_macros($t, array(
'$title' => t('Administration'),
@ -737,6 +763,9 @@ function admin_page_site(&$a) {
'$max_author_posts_community_page' => array('max_author_posts_community_page', t("Posts per user on community page"), get_config('system','max_author_posts_community_page'), t("The maximum number of posts per user on the community page. (Not valid for 'Global Community')")),
'$ostatus_disabled' => array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disabled'), t("Provide built-in OStatus \x28StatusNet, GNU Social etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")),
'$ostatus_poll_interval' => array('ostatus_poll_interval', t("OStatus conversation completion interval"), (string) intval(get_config('system','ostatus_poll_interval')), t("How often shall the poller check for new entries in OStatus conversations? This can be a very ressource task."), $ostatus_poll_choices),
'$ostatus_not_able' => t("OStatus support can only be enabled if threading is enabled."),
'$diaspora_able' => $diaspora_able,
'$diaspora_not_able' => t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),
'$diaspora_enabled' => array('diaspora_enabled', t("Enable Diaspora support"), get_config('system','diaspora_enabled'), t("Provide built-in Diaspora network compatibility.")),
'$dfrn_only' => array('dfrn_only', t('Only allow Friendica contacts'), get_config('system','dfrn_only'), t("All contacts must use Friendica protocols. All other built-in communication protocols disabled.")),
'$verifyssl' => array('verifyssl', t("Verify SSL"), get_config('system','verifyssl'), t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites.")),
@ -747,6 +776,8 @@ function admin_page_site(&$a) {
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
'$maxloadavg_frontend' => array('maxloadavg_frontend', t("Maximum Load Average (Frontend)"), ((intval(get_config('system','maxloadavg_frontend')) > 0)?get_config('system','maxloadavg_frontend'):50), t("Maximum system load before the frontend quits service - default 50.")),
'$optimize_max_tablesize'=> array('optimize_max_tablesize', t("Maximum table size for optimization"), ((intval(get_config('system','optimize_max_tablesize')) > 0)?get_config('system','optimize_max_tablesize'):100), t("Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it.")),
'$optimize_fragmentation'=> array('optimize_fragmentation', t("Minimum level of fragmentation"), ((intval(get_config('system','optimize_fragmentation')) > 0)?get_config('system','optimize_fragmentation'):30), t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")),
'$poco_completion' => array('poco_completion', t("Periodical check of global contacts"), get_config('system','poco_completion'), t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")),
'$poco_requery_days' => array('poco_requery_days', t("Days between requery"), get_config('system','poco_requery_days'), t("Number of days after which a server is requeried for his contacts.")),
@ -1206,7 +1237,7 @@ function admin_page_plugins(&$a){
* List plugins
*/
if (x($_GET,"a") && $_GET['a']=="r"){
if (x($_GET,"a") && $_GET['a']=="r"){
check_form_security_token_redirectOnErr($a->get_baseurl().'/admin/plugins', 'admin_themes', 't');
reload_plugins();
info("Plugins reloaded");
@ -1241,6 +1272,7 @@ function admin_page_plugins(&$a){
'$title' => t('Administration'),
'$page' => t('Plugins'),
'$submit' => t('Save Settings'),
'$reload' => t('Reload active plugins'),
'$baseurl' => $a->get_baseurl(true),
'$function' => 'plugins',
'$plugins' => $plugins,
@ -1393,11 +1425,27 @@ function admin_page_themes(&$a){
$admin_form="";
if (is_file("view/theme/$theme/config.php")){
require_once("view/theme/$theme/config.php");
if(function_exists("theme_admin")){
$admin_form = theme_admin($a);
}
function __get_theme_admin_form(&$a, $theme) {
$orig_theme = $a->theme;
$orig_page = $a->page;
$orig_session_theme = $_SESSION['theme'];
require_once("view/theme/$theme/theme.php");
require_once("view/theme/$theme/config.php");
$_SESSION['theme'] = $theme;
$init = $theme."_init";
if(function_exists($init)) $init($a);
if(function_exists("theme_admin")){
$admin_form = theme_admin($a);
}
$_SESSION['theme'] = $orig_session_theme;
$a->theme = $orig_theme;
$a->page = $orig_page;
return $admin_form;
}
$admin_form = __get_theme_admin_form($a, $theme);
}
$screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
@ -1427,6 +1475,22 @@ function admin_page_themes(&$a){
));
}
// reload active themes
if (x($_GET,"a") && $_GET['a']=="r"){
check_form_security_token_redirectOnErr($a->get_baseurl().'/admin/themes', 'admin_themes', 't');
if ($themes) {
foreach($themes as $th) {
if ($th['allowed']) {
uninstall_theme($th['name']);
install_theme($th['name']);
}
}
}
info("Themes reloaded");
goaway($a->get_baseurl().'/admin/themes');
}
/**
* List themes
*/
@ -1438,11 +1502,13 @@ function admin_page_themes(&$a){
}
}
$t = get_markup_template("admin_plugins.tpl");
return replace_macros($t, array(
'$title' => t('Administration'),
'$page' => t('Themes'),
'$submit' => t('Save Settings'),
'$reload' => t('Reload active themes'),
'$baseurl' => $a->get_baseurl(true),
'$function' => 'themes',
'$plugins' => $xthemes,

View File

@ -1,6 +1,9 @@
<?php
require_once('include/socgraph.php');
require_once('include/Contact.php');
require_once('include/contact_selectors.php');
require_once('mod/contacts.php');
function allfriends_content(&$a) {
@ -12,52 +15,85 @@ function allfriends_content(&$a) {
if($a->argc > 1)
$cid = intval($a->argv[1]);
if(! $cid)
return;
$c = q("select name, url, photo from contact where id = %d and uid = %d limit 1",
$uid = $a->user[uid];
$c = q("SELECT `name`, `url`, `photo` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($cid),
intval(local_user())
);
$vcard_widget .= replace_macros(get_markup_template("vcard-widget.tpl"),array(
'$name' => $c[0]['name'],
'$photo' => $c[0]['photo'],
'url' => z_root() . '/contacts/' . $cid
));
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= $vcard_widget;
if(! count($c))
return;
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => sprintf( t('Friends of %s'), $c[0]['name'])
));
$a->page['aside'] = "";
profile_load($a, "", 0, get_contact_details_by_url($c[0]["url"]));
$total = count_all_friends(local_user(), $cid);
$r = all_friends(local_user(),$cid);
if(count($total))
$a->set_pager_total($total);
$r = all_friends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']);
if(! count($r)) {
$o .= t('No friends to display.');
return $o;
}
$tpl = get_markup_template('common_friends.tpl');
$id = 0;
foreach($r as $rr) {
$o .= replace_macros($tpl,array(
'$url' => $rr['url'],
'$name' => $rr['name'],
'$photo' => $rr['photo'],
'$tags' => ''
));
//get further details of the contact
$contact_details = get_contact_details_by_url($rr['url'], $uid);
$photo_menu = '';
// $rr[cid] is only available for common contacts. So if the contact is a common one, use contact_photo_menu to generate the photo_menu
// If the contact is not common to the user, Connect/Follow' will be added to the photo menu
if ($rr[cid]) {
$rr[id] = $rr[cid];
$photo_menu = contact_photo_menu ($rr);
}
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);
}
$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']),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],
'account_type' => (($contact_details['community']) ? t('Forum') : ''),
'network' => network_to_name($contact_details['network'], $contact_details['url']),
'photo_menu' => $photo_menu,
'conntxt' => t('Connect'),
'connlnk' => $connlnk,
'id' => ++$id,
);
$entries[] = $entry;
}
$o .= cleardiv();
// $o .= paginate($a);
$tab_str = contacts_tab($a, $cid, 3);
$tpl = get_markup_template('viewcontact_template.tpl');
$o .= replace_macros($tpl,array(
//'$title' => sprintf( t('Friends of %s'), htmlentities($c[0]['name'])),
'$tab_str' => $tab_str,
'$contacts' => $entries,
'$paginate' => paginate($a),
));
return $o;
}

View File

@ -1,6 +1,9 @@
<?php
require_once('include/socgraph.php');
require_once('include/Contact.php');
require_once('include/contact_selectors.php');
require_once('mod/contacts.php');
function common_content(&$a) {
@ -11,51 +14,53 @@ function common_content(&$a) {
$cid = intval($a->argv[3]);
$zcid = 0;
if (! local_user()) {
notice( t('Permission denied.') . EOL);
return;
}
if($cmd !== 'loc' && $cmd != 'rem')
return;
if(! $uid)
return;
if($cmd === 'loc' && $cid) {
$c = q("select name, url, photo from contact where id = %d and uid = %d limit 1",
if($cmd === 'loc' && $cid) {
$c = q("SELECT `name`, `url`, `photo` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($cid),
intval($uid)
);
}
else {
$c = q("select name, url, photo from contact where self = 1 and uid = %d limit 1",
$a->page['aside'] = "";
profile_load($a, "", 0, get_contact_details_by_url($c[0]["url"]));
} else {
$c = q("SELECT `name`, `url`, `photo` FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
intval($uid)
);
}
$vcard_widget .= replace_macros(get_markup_template("vcard-widget.tpl"),array(
'$name' => $c[0]['name'],
'$photo' => $c[0]['photo'],
'url' => z_root() . '/contacts/' . $cid
));
$vcard_widget .= replace_macros(get_markup_template("vcard-widget.tpl"),array(
'$name' => htmlentities($c[0]['name']),
'$photo' => $c[0]['photo'],
'url' => z_root() . '/contacts/' . $cid
));
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= $vcard_widget;
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= $vcard_widget;
}
if(! count($c))
return;
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => t('Common Friends')
));
if(! $cid) {
if(get_my_url()) {
$r = q("select id from contact where nurl = '%s' and uid = %d limit 1",
$r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc(normalise_link(get_my_url())),
intval($profile_uid)
);
if(count($r))
$cid = $r[0]['id'];
else {
$r = q("select id from gcontact where nurl = '%s' limit 1",
$r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link(get_my_url()))
);
if(count($r))
@ -67,46 +72,75 @@ function common_content(&$a) {
if($cid == 0 && $zcid == 0)
return;
return;
if($cid)
$t = count_common_friends($uid,$cid);
$t = count_common_friends($uid, $cid);
else
$t = count_common_friends_zcid($uid,$zcid);
$t = count_common_friends_zcid($uid, $zcid);
$a->set_pager_total($t);
if(! $t) {
if(count($t))
$a->set_pager_total($t);
else {
notice( t('No contacts in common.') . EOL);
return $o;
}
if($cid)
$r = common_friends($uid,$cid);
$r = common_friends($uid, $cid, $a->pager['start'], $a->pager['itemspage']);
else
$r = common_friends_zcid($uid,$zcid);
$r = common_friends_zcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']);
if(! count($r)) {
return $o;
}
$tpl = get_markup_template('common_friends.tpl');
$id = 0;
foreach($r as $rr) {
$o .= replace_macros($tpl,array(
'$url' => $rr['url'],
'$name' => $rr['name'],
'$photo' => $rr['photo'],
'$tags' => ''
));
//get further details of the contact
$contact_details = get_contact_details_by_url($rr['url'], $uid);
// $rr[id] is needed to use contact_photo_menu()
$rr[id] = $rr[cid];
$photo_menu = '';
$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']),
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],
'account_type' => (($contact_details['community']) ? t('Forum') : ''),
'network' => network_to_name($contact_details['network'], $contact_details['url']),
'photo_menu' => $photo_menu,
'id' => ++$id,
);
$entries[] = $entry;
}
$o .= cleardiv();
// $o .= paginate($a);
if($cmd === 'loc' && $cid && $uid == local_user()) {
$tab_str = contacts_tab($a, $cid, 4);
} else
$title = t('Common Friends');
$tpl = get_markup_template('viewcontact_template.tpl');
$o .= replace_macros($tpl,array(
'$title' => $title,
'$tab_str' => $tab_str,
'$contacts' => $entries,
'$paginate' => paginate($a),
));
return $o;
}

View File

@ -13,7 +13,7 @@ function contacts_init(&$a) {
$contact_id = 0;
if(($a->argc == 2) && intval($a->argv[1])) {
if((($a->argc == 2) && intval($a->argv[1])) OR (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts"))) {
$contact_id = intval($a->argv[1]);
$r = q("SELECT * FROM `contact` WHERE `uid` = %d and `id` = %d LIMIT 1",
intval(local_user()),
@ -27,41 +27,55 @@ function contacts_init(&$a) {
require_once('include/group.php');
require_once('include/contact_widgets.php');
if ($_GET['nets'] == "all")
$_GET['nets'] = "";
if(! x($a->page,'aside'))
$a->page['aside'] = '';
if($contact_id) {
$a->data['contact'] = $r[0];
if (($a->data['contact']['network'] != "") AND ($a->data['contact']['network'] != NETWORK_DFRN)) {
$networkname = format_network_name($a->data['contact']['network'],$a->data['contact']['url']);
} else
$networkname = '';
$vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"),array(
'$name' => $a->data['contact']['name'],
'$name' => htmlentities($a->data['contact']['name']),
'$photo' => $a->data['contact']['photo'],
'$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? $a->get_baseurl()."/redir/".$a->data['contact']['id'] : $a->data['contact']['url']
'$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? z_root()."/redir/".$a->data['contact']['id'] : $a->data['contact']['url'],
'$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""),
'$network_name' => $networkname,
'$network' => t('Network:'),
'account_type' => (($a->data['contact']['forum'] || $a->data['contact']['prv']) ? t('Forum') : '')
));
$finpeople_widget = '';
$follow_widget = '';
$networks_widget = '';
}
else {
$vcard_widget = '';
$networks_widget .= networks_widget('contacts',$_GET['nets']);
if (isset($_GET['add']))
$follow_widget = follow_widget($_GET['add']);
else
$follow_widget = follow_widget();
$findpeople_widget .= findpeople_widget();
}
if ($_GET['nets'] == "all")
$_GET['nets'] = "";
$groups_widget .= group_side('contacts','group','full',0,$contact_id);
$groups_widget .= group_side('contacts','group',false,0,$contact_id);
$findpeople_widget .= findpeople_widget();
$networks_widget .= networks_widget('contacts',$_GET['nets']);
$a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"),array(
'$vcard_widget' => $vcard_widget,
'$findpeople_widget' => $findpeople_widget,
'$follow_widget' => $follow_widget,
'$groups_widget' => $groups_widget,
'$findpeople_widget' => $findpeople_widget,
'$networks_widget' => $networks_widget
));
$base = $a->get_baseurl();
$base = z_root();
$tpl = get_markup_template("contacts-head.tpl");
$a->page['htmlhead'] .= replace_macros($tpl,array(
'$baseurl' => $a->get_baseurl(true),
@ -238,12 +252,12 @@ function _contact_update_profile($contact_id) {
$data = probe_url($r[0]["url"]);
// "Feed" is mostly a sign of communication problems
if (($data["network"] == NETWORK_FEED) AND ($data["network"] != $r[0]["network"]))
// "Feed" or "Unknown" is mostly a sign of communication problems
if ((in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) AND ($data["network"] != $r[0]["network"]))
return;
$updatefields = array("name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm",
"poco", "network", "alias", "pubkey");
"poco", "network", "alias");
$update = array();
if ($data["network"] == NETWORK_OSTATUS) {
@ -432,7 +446,7 @@ function contacts_content(&$a) {
}
$a->page['aside'] = '';
return replace_macros(get_markup_template('contact_drop_confirm.tpl'), array(
'$contact' => _contact_detail_for_template($orig_record[0]),
'$method' => 'get',
@ -460,6 +474,9 @@ function contacts_content(&$a) {
goaway($a->get_baseurl(true) . '/contacts');
return; // NOTREACHED
}
if($cmd === 'posts') {
return contact_posts($a, $contact_id);
}
}
@ -509,7 +526,7 @@ function contacts_content(&$a) {
if(!in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
$relation_text = "";
$relation_text = sprintf($relation_text,$contact['name']);
$relation_text = sprintf($relation_text,htmlentities($contact['name']));
if(($contact['network'] === NETWORK_DFRN) && ($contact['rel'])) {
$url = "redir/{$contact['id']}";
@ -535,48 +552,16 @@ function contacts_content(&$a) {
$nettype = sprintf( t('Network type: %s'),network_to_name($contact['network'], $contact["url"]));
$common = count_common_friends(local_user(),$contact['id']);
$common_text = (($common) ? sprintf( tt('%d contact in common','%d contacts in common', $common),$common) : '');
//$common = count_common_friends(local_user(),$contact['id']);
//$common_text = (($common) ? sprintf( tt('%d contact in common','%d contacts in common', $common),$common) : '');
$polling = (($contact['network'] === NETWORK_MAIL | $contact['network'] === NETWORK_FEED) ? 'polling' : '');
$x = count_all_friends(local_user(), $contact['id']);
$all_friends = (($x) ? t('View all contacts') : '');
//$x = count_all_friends(local_user(), $contact['id']);
//$all_friends = (($x) ? t('View all contacts') : '');
// tabs
$tabs = array(
array(
'label' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/block',
'sel' => '',
'title' => t('Toggle Blocked status'),
'accesskey' => 'b',
),
array(
'label' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/ignore',
'sel' => '',
'title' => t('Toggle Ignored status'),
'accesskey' => 'i',
),
array(
'label' => (($contact['archive']) ? t('Unarchive') : t('Archive') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/archive',
'sel' => '',
'title' => t('Toggle Archive status'),
'accesskey' => 'v',
),
array(
'label' => t('Repair'),
'url' => $a->get_baseurl(true) . '/crepair/' . $contact_id,
'sel' => '',
'title' => t('Advanced Contact Settings'),
'accesskey' => 'r',
)
);
$tab_tpl = get_markup_template('common_tabs.tpl');
$tab_str = replace_macros($tab_tpl, array('$tabs' => $tabs));
$tab_str = contacts_tab($a, $contact_id, 2);
$lost_contact = (($contact['archive'] && $contact['term-date'] != '0000-00-00 00:00:00' && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : '');
@ -590,8 +575,13 @@ function contacts_content(&$a) {
if ($contact['network'] == NETWORK_DFRN)
$profile_select = contact_profile_assign($contact['profile-id'],(($contact['network'] !== NETWORK_DFRN) ? true : false));
if (in_array($contact['network'], array(NETWORK_DIASPORA, NETWORK_OSTATUS)) AND
($contact['rel'] == CONTACT_IS_FOLLOWER))
$follow = $a->get_baseurl(true)."/follow?url=".urlencode($contact["url"]);
$o .= replace_macros($tpl, array(
'$header' => t('Contact Editor'),
//'$header' => t('Contact Editor'),
'$tab_str' => $tab_str,
'$submit' => t('Submit'),
'$lbl_vis1' => t('Profile Visibility'),
@ -617,6 +607,8 @@ function contacts_content(&$a) {
'$updpub' => t('Update public posts'),
'$last_update' => $last_update,
'$udnow' => t('Update now'),
'$follow' => $follow,
'$follow_text' => t("Connect/Follow"),
'$profile_select' => $profile_select,
'$contact_id' => $contact['id'],
'$block_text' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
@ -632,13 +624,19 @@ function contacts_content(&$a) {
'$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'],
'$ffi_keyword_blacklist' => array('ffi_keyword_blacklist', t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')),
'$photo' => $contact['photo'],
'$name' => $contact['name'],
'$name' => htmlentities($contact['name']),
'$dir_icon' => $dir_icon,
'$alt_text' => $alt_text,
'$sparkle' => $sparkle,
'$url' => $url,
'$profileurllabel' => t('Profile URL'),
'$profileurl' => $contact['url'],
'$location' => bbcode($contact["location"]),
'$location_label' => t("Location:"),
'$about' => bbcode($contact["about"], false, false),
'$about_label' => t("About:"),
'$keywords' => $contact["keywords"],
'$keywords_label' => t("Tags:")
));
@ -687,6 +685,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/suggest',
'sel' => '',
'title' => t('Suggest potential friends'),
'id' => 'suggestions-tab',
'accesskey' => 'g',
),
array(
@ -694,6 +693,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/all',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all contacts'),
'id' => 'showall-tab',
'accesskey' => 'l',
),
array(
@ -701,6 +701,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts',
'sel' => ((! $all) && (! $blocked) && (! $hidden) && (! $search) && (! $nets) && (! $ignored) && (! $archived)) ? 'active' : '',
'title' => t('Only show unblocked contacts'),
'id' => 'showunblocked-tab',
'accesskey' => 'o',
),
@ -709,6 +710,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked contacts'),
'id' => 'showblocked-tab',
'accesskey' => 'b',
),
@ -717,6 +719,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored contacts'),
'id' => 'showignored-tab',
'accesskey' => 'i',
),
@ -725,6 +728,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived contacts'),
'id' => 'showarchived-tab',
'accesskey' => 'y',
),
@ -733,6 +737,7 @@ function contacts_content(&$a) {
'url' => $a->get_baseurl(true) . '/contacts/hidden',
'sel' => ($hidden) ? 'active' : '',
'title' => t('Only show hidden contacts'),
'id' => 'showhidden-tab',
'accesskey' => 'h',
),
@ -765,8 +770,9 @@ function contacts_content(&$a) {
$total = $r[0]['total'];
}
$sql_extra3 = unavailable_networks();
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ORDER BY `name` ASC LIMIT %d , %d ",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ",
intval($_SESSION['uid']),
intval($a->pager['start']),
intval($a->pager['itemspage'])
@ -782,7 +788,7 @@ function contacts_content(&$a) {
$tpl = get_markup_template("contacts-template.tpl");
$o .= replace_macros($tpl, array(
'$baseurl' => $a->get_baseurl(),
'$baseurl' => z_root(),
'$header' => t('Contacts') . (($nets) ? ' - ' . network_to_name($nets) : ''),
'$tabs' => $t,
'$total' => $total,
@ -793,6 +799,7 @@ function contacts_content(&$a) {
'$cmd' => $a->cmd,
'$contacts' => $contacts,
'$contact_drop_confirm' => t('Do you really want to delete this contact?'),
'multiselect' => 1,
'$batch_actions' => array(
'contacts_batch_update' => t('Update'),
'contacts_batch_block' => t('Block')."/".t("Unblock"),
@ -807,7 +814,135 @@ function contacts_content(&$a) {
return $o;
}
function contacts_tab($a, $contact_id, $active_tab) {
// tabs
$tabs = array(
array(
'label'=>t('Status'),
'url' => "contacts/".$contact_id."/posts",
'sel' => (($active_tab == 1)?'active':''),
'title' => t('Status Messages and Posts'),
'id' => 'status-tab',
'accesskey' => 'm',
),
array(
'label'=>t('Profile'),
'url' => "contacts/".$contact_id,
'sel' => (($active_tab == 2)?'active':''),
'title' => t('Profile Details'),
'id' => 'status-tab',
'accesskey' => 'o',
)
);
$x = count_all_friends(local_user(), $contact_id);
if ($x)
$tabs[] = array('label'=>t('Contacts'),
'url' => "allfriends/".$contact_id,
'sel' => (($active_tab == 3)?'active':''),
'title' => t('View all contacts'),
'id' => 'allfriends-tab',
'accesskey' => 't');
$common = count_common_friends(local_user(),$contact_id);
if ($common)
$tabs[] = array('label'=>t('Common Friends'),
'url' => "common/loc/".local_user()."/".$contact_id,
'sel' => (($active_tab == 4)?'active':''),
'title' => t('View all common friends'),
'id' => 'common-loc-tab',
'accesskey' => 'd');
$tabs[] = array('label' => t('Repair'),
'url' => $a->get_baseurl(true) . '/crepair/' . $contact_id,
'sel' => (($active_tab == 5)?'active':''),
'title' => t('Advanced Contact Settings'),
'id' => 'repair-tab',
'accesskey' => 'r');
$tabs[] = array('label' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/block',
'sel' => '',
'title' => t('Toggle Blocked status'),
'id' => 'toggle-block-tab',
'accesskey' => 'b');
$tabs[] = array('label' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/ignore',
'sel' => '',
'title' => t('Toggle Ignored status'),
'id' => 'toggle-ignore-tab',
'accesskey' => 'i');
$tabs[] = array('label' => (($contact['archive']) ? t('Unarchive') : t('Archive') ),
'url' => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/archive',
'sel' => '',
'title' => t('Toggle Archive status'),
'id' => 'toggle-archive-tab',
'accesskey' => 'v');
$tab_tpl = get_markup_template('common_tabs.tpl');
$tab_str = replace_macros($tab_tpl, array('$tabs' => $tabs));
return $tab_str;
}
function contact_posts($a, $contact_id) {
require_once('include/conversation.php');
$r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
if ($r) {
$contact = $r[0];
$a->page['aside'] = "";
profile_load($a, "", 0, get_contact_details_by_url($contact["url"]));
}
if(get_config('system', 'old_pager')) {
$r = q("SELECT COUNT(*) AS `total` FROM `item`
WHERE `item`.`uid` = %d AND `author-link` IN ('%s', '%s')",
intval(local_user()),
dbesc(str_replace("https://", "http://", $contact["url"])),
dbesc(str_replace("http://", "https://", $contact["url"])));
$a->set_pager_total($r[0]['total']);
}
$r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
`author-name` AS `name`, `owner-avatar` AS `photo`,
`owner-link` AS `url`, `owner-avatar` AS `thumb`
FROM `item` FORCE INDEX (uid_contactid_created)
WHERE `item`.`uid` = %d AND `contact-id` = %d
AND `author-link` IN ('%s', '%s')
ORDER BY `item`.`created` DESC LIMIT %d, %d",
intval(local_user()),
intval($contact_id),
dbesc(str_replace("https://", "http://", $contact["url"])),
dbesc(str_replace("http://", "https://", $contact["url"])),
intval($a->pager['start']),
intval($a->pager['itemspage'])
);
$tab_str = contacts_tab($a, $contact_id, 1);
$o .= $tab_str;
$o .= conversation($a,$r,'community',false);
if(!get_config('system', 'old_pager')) {
$o .= alt_pager($a,count($r));
} else {
$o .= paginate($a);
}
return $o;
}
function _contact_detail_for_template($rr){
$community = '';
switch($rr['rel']) {
case CONTACT_IS_FRIEND:
$dir_icon = 'images/lrarrow.gif';
@ -832,8 +967,12 @@ function _contact_detail_for_template($rr){
$url = $rr['url'];
$sparkle = '';
}
//test if contact is a forum page
if (isset($rr['forum']) OR isset($rr['prv']))
$community = ($rr['forum'] OR $rr['prv']);
return array(
'img_hover' => sprintf( t('Visit %s\'s profile [%s]'),$rr['name'],$rr['url']),
'edit_hover' => t('Edit contact'),
@ -841,11 +980,12 @@ function _contact_detail_for_template($rr){
'id' => $rr['id'],
'alt_text' => $alt_text,
'dir_icon' => $dir_icon,
'thumb' => proxy_url($rr['thumb']),
'name' => $rr['name'],
'username' => $rr['name'],
'thumb' => proxy_url($rr['thumb'], false, PROXY_SIZE_THUMB),
'name' => htmlentities($rr['name']),
'username' => htmlentities($rr['name']),
'account_type' => ($community ? t('Forum') : ''),
'sparkle' => $sparkle,
'itemurl' => $rr['url'],
'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']),
'url' => $url,
'network' => network_to_name($rr['network'], $rr['url']),
);

View File

@ -11,8 +11,8 @@
// There is no "pagination query", but we will manage the "current page" on the client
// and provide a link to fetch the next page - until there are no pages left to fetch.
// With the exception of complex tag and text searches, this prototype is incredibly
// fast - e.g. one or two milliseconds to fetch parent items for the current content,
// With the exception of complex tag and text searches, this prototype is incredibly
// fast - e.g. one or two milliseconds to fetch parent items for the current content,
// and 10-20 milliseconds to fetch all the child items.
@ -476,7 +476,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'name' => $name_e,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => proxy_url($profile_avatar),
'thumb' => proxy_url($profile_avatar, false, PROXY_SIZE_THUMB),
'title' => $title_e,
'body' => $body_e,
'text' => $text_e,
@ -485,7 +485,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'indent' => '',
'owner_name' => $owner_name_e,
'owner_url' => $owner_url,
'owner_photo' => proxy_url($owner_photo),
'owner_photo' => proxy_url($owner_photo, false, PROXY_SIZE_THUMB),
'plink' => get_plink($item),
'edpost' => false,
'isstarred' => $isstarred,
@ -859,7 +859,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => $name_e,
'thumb' => proxy_url($profile_avatar),
'thumb' => proxy_url($profile_avatar, false, PROXY_SIZE_THUMB),
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => $title_e,
@ -869,7 +869,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
'indent' => $indent,
'shiny' => $shiny,
'owner_url' => $owner_url,
'owner_photo' => proxy_url($owner_photo),
'owner_photo' => proxy_url($owner_photo, false, PROXY_SIZE_THUMB),
'owner_name' => $owner_name_e,
'plink' => get_plink($item),
'edpost' => $edpost,

20
mod/credits.php Normal file
View File

@ -0,0 +1,20 @@
<?php
/**
* Show a credits page for all the developers who helped with the project
* (only contributors to the git repositories for friendica core and the
* addons repository will be listed though ATM)
*/
function credits_content (&$a) {
/* fill the page with credits */
$f = fopen('util/credits.txt','r');
$names = fread($f, filesize('util/credits.txt'));
$arr = explode("\n", htmlspecialchars($names));
fclose($f);
$tpl = get_markup_template('credits.tpl');
return replace_macros( $tpl, array(
'$title' => t('Credits'),
'$thanks' => t('Friendica is a community project, that would not be possible without the help of many people. Here is a list of those who have contributed to the code or the translation of Friendica. Thank you all!'),
'$names' => $arr,
));
}

View File

@ -1,4 +1,6 @@
<?php
require_once("include/contact_selectors.php");
require_once("mod/contacts.php");
function crepair_init(&$a) {
if(! local_user())
@ -21,14 +23,9 @@ function crepair_init(&$a) {
$a->page['aside'] = '';
if($contact_id) {
$a->data['contact'] = $r[0];
$tpl = get_markup_template("vcard-widget.tpl");
$vcard_widget .= replace_macros($tpl, array(
'$name' => $a->data['contact']['name'],
'$photo' => $a->data['contact']['photo']
));
$a->page['aside'] .= $vcard_widget;
$a->data['contact'] = $r[0];
$contact = $r[0];
profile_load($a, "", 0, get_contact_details_by_url($contact["url"]));
}
}
@ -137,16 +134,10 @@ function crepair_content(&$a) {
$contact = $r[0];
$msg1 = t('Repair Contact Settings');
$warning = t('<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working.');
$info = t('Please use your browser \'Back\' button <strong>now</strong> if you are uncertain what to do on this page.');
$msg2 = t('<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working.');
$msg3 = t('Please use your browser \'Back\' button <strong>now</strong> if you are uncertain what to do on this page.');
$o .= '<h2>' . $msg1 . '</h2>';
$o .= '<div class="error-message">' . $msg2 . EOL . EOL. $msg3 . '</div>';
$o .= EOL . '<a href="contacts/' . $cid . '">' . t('Return to contact editor') . '</a>' . EOL;
$returnaddr = "contacts/$cid";
$allow_remote_self = get_config('system','allow_users_remote_self');
@ -163,8 +154,17 @@ function crepair_content(&$a) {
$update_profile = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_DSPR, NETWORK_OSTATUS));
$tab_str = contacts_tab($a, $contact['id'], 5);
$tpl = get_markup_template('crepair.tpl');
$o .= replace_macros($tpl, array(
//'$title' => t('Repair Contact Settings'),
'$tab_str' => $tab_str,
'$warning' => $warning,
'$info' => $info,
'$returnaddr' => $returnaddr,
'$return' => t('Return to contact editor'),
'$update_profile' => update_profile,
'$udprofilenow' => t('Refetch contact data'),
'$label_name' => t('Name'),
@ -178,9 +178,14 @@ function crepair_content(&$a) {
'$label_photo' => t('New photo from this URL'),
'$label_remote_self' => t('Remote Self'),
'$allow_remote_self' => $allow_remote_self,
'$remote_self' => array('remote_self', t('Mirror postings from this contact'), $contact['remote_self'], t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'), $remote_self_options),
'$contact_name' => $contact['name'],
'$contact_nick' => $contact['nick'],
'$remote_self' => array('remote_self',
t('Mirror postings from this contact'),
$contact['remote_self'],
t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'),
$remote_self_options
),
'$contact_name' => htmlentities($contact['name']),
'$contact_nick' => htmlentities($contact['nick']),
'$contact_id' => $contact['id'],
'$contact_url' => $contact['url'],
'$request' => $contact['request'],
@ -189,7 +194,7 @@ function crepair_content(&$a) {
'$poll' => $contact['poll'],
'$contact_attag' => $contact['attag'],
'$lbl_submit' => t('Submit')
));
));
return $o;

View File

@ -382,7 +382,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
if($duplex)
$new_relation = CONTACT_IS_FRIEND;
else
$new_relation = CONTACT_IS_SHARING;
$new_relation = CONTACT_IS_FOLLOWER;
if($new_relation != CONTACT_IS_FOLLOWER)
$writable = 1;

View File

@ -476,8 +476,8 @@ function dfrn_poll_content(&$a) {
// URL reply
if($dfrn_version < 2.2) {
$s = fetch_url($r[0]['poll']
. '?dfrn_id=' . $encrypted_id
$s = fetch_url($r[0]['poll']
. '?dfrn_id=' . $encrypted_id
. '&type=profile-check'
. '&dfrn_version=' . DFRN_PROTOCOL_VERSION
. '&challenge=' . $challenge
@ -493,7 +493,7 @@ function dfrn_poll_content(&$a) {
'sec' => $sec
));
}
$profile = ((count($r) && $r[0]['nickname']) ? $r[0]['nickname'] : $nickname);
switch($destination_url) {
@ -506,7 +506,7 @@ function dfrn_poll_content(&$a) {
case 'status':
case '':
$dest = $a->get_baseurl() . '/profile/' . $profile;
break;
break;
default:
$dest = $destination_url . '?f=&redir=1';
break;
@ -564,5 +564,3 @@ function dfrn_poll_content(&$a) {
}
}
}

View File

@ -136,7 +136,7 @@ function dfrn_request_post(&$a) {
$dfrn_request = $parms['dfrn-request'];
/********* Escape the entire array ********/
/********* Escape the entire array ********/
dbesc_array($parms);
@ -146,13 +146,14 @@ function dfrn_request_post(&$a) {
* Create a contact record on our site for the other person
*/
$r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `nurl`, `name`, `nick`, `photo`, `site-pubkey`,
$r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `nurl`, `addr`, `name`, `nick`, `photo`, `site-pubkey`,
`request`, `confirm`, `notify`, `poll`, `poco`, `network`, `aes_allow`, `hidden`)
VALUES ( %d, '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
VALUES ( %d, '%s', '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
intval(local_user()),
datetime_convert(),
dbesc($dfrn_url),
dbesc(normalise_link($dfrn_url)),
$parms['addr'],
$parms['fn'],
$parms['nick'],
$parms['photo'],
@ -539,13 +540,14 @@ function dfrn_request_post(&$a) {
dbesc_array($parms);
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`,`name`, `nick`, `issued-id`, `photo`, `site-pubkey`,
$r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `name`, `nick`, `issued-id`, `photo`, `site-pubkey`,
`request`, `confirm`, `notify`, `poll`, `poco`, `network` )
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
intval($uid),
dbesc(datetime_convert()),
$parms['url'],
dbesc(normalise_link($parms['url'])),
$parms['addr'],
$parms['fn'],
$parms['nick'],
$parms['issued-id'],

View File

@ -8,6 +8,8 @@ function directory_init(&$a) {
$a->page['aside'] .= findpeople_widget();
$a->page['aside'] .= follow_widget();
}
else {
unset($_SESSION['theme']);
@ -31,7 +33,7 @@ function directory_content(&$a) {
require_once("mod/proxy.php");
if((get_config('system','block_public')) && (! local_user()) && (! remote_user()) ||
(get_config('system','block_local_dir')) && (! local_user()) && (! remote_user())) {
(get_config('system','block_local_dir')) && (! local_user()) && (! remote_user())) {
notice( t('Public access denied.') . EOL);
return;
}
@ -44,51 +46,38 @@ function directory_content(&$a) {
else
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
$tpl = get_markup_template('directory_header.tpl');
$globaldir = '';
$gdirpath = get_config('system','directory');
if(strlen($gdirpath)) {
$globaldir = '<ul><li><div id="global-directory-link"><a href="'
. zrl($gdirpath,true) . '">' . t('Global Directory') . '</a></div></li></ul>';
$gdirpath = '';
$dirurl = get_config('system','directory');
if(strlen($dirurl)) {
$gdirpath = zrl($dirurl,true);
}
$admin = '';
$o .= replace_macros($tpl, array(
'$search' => $search,
'$globaldir' => $globaldir,
'$desc' => t('Find on this site'),
'$admin' => $admin,
'$finding' => (strlen($search) ? '<h4>' . t('Finding: ') . "'" . $search . "'" . '</h4>' : ""),
'$sitedir' => t('Site Directory'),
'$submit' => t('Find')
));
if($search) {
$search = dbesc($search);
$sql_extra = " AND ((`profile`.`name` LIKE '%$search%') OR
(`user`.`nickname` LIKE '%$search%') OR
(`pdesc` LIKE '%$search%') OR
(`locality` LIKE '%$search%') OR
(`region` LIKE '%$search%') OR
(`country-name` LIKE '%$search%') OR
(`gender` LIKE '%$search%') OR
(`marital` LIKE '%$search%') OR
(`sexual` LIKE '%$search%') OR
(`about` LIKE '%$search%') OR
(`romance` LIKE '%$search%') OR
(`work` LIKE '%$search%') OR
(`education` LIKE '%$search%') OR
(`pub_keywords` LIKE '%$search%') OR
(`prv_keywords` LIKE '%$search%'))";
(`profile`.`pdesc` LIKE '%$search%') OR
(`profile`.`locality` LIKE '%$search%') OR
(`profile`.`region` LIKE '%$search%') OR
(`profile`.`country-name` LIKE '%$search%') OR
(`profile`.`gender` LIKE '%$search%') OR
(`profile`.`marital` LIKE '%$search%') OR
(`profile`.`sexual` LIKE '%$search%') OR
(`profile`.`about` LIKE '%$search%') OR
(`profile`.`romance` LIKE '%$search%') OR
(`profile`.`work` LIKE '%$search%') OR
(`profile`.`education` LIKE '%$search%') OR
(`profile`.`pub_keywords` LIKE '%$search%') OR
(`profile`.`prv_keywords` LIKE '%$search%'))";
}
$publish = ((get_config('system','publish_all')) ? '' : " AND `publish` = 1 " );
$r = $db->q("SELECT COUNT(*) AS `total` FROM `profile` LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $sql_extra ");
$r = $db->q("SELECT COUNT(*) AS `total` FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $sql_extra ");
if(count($r))
$a->set_pager_total($r[0]['total']);
@ -96,7 +85,11 @@ function directory_content(&$a) {
$limit = intval($a->pager['start']).",".intval($a->pager['itemspage']);
$r = $db->q("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags` FROM `profile` LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $sql_extra $order LIMIT ".$limit);
$r = $db->q("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`,
`contact`.`addr`, `contact`.`url` AS profile_url FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid`
WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 AND `contact`.`self` $sql_extra $order LIMIT ".$limit);
if(count($r)) {
if(in_array('small', $a->argv))
@ -106,8 +99,12 @@ function directory_content(&$a) {
foreach($r as $rr) {
$community = '';
$itemurl= '';
$profile_link = $a->get_baseurl() . '/profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
$itemurl = (($rr['addr'] != "") ? $rr['addr'] : $rr['profile_url']);
$profile_link = z_root() . '/profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
$pdesc = (($rr['pdesc']) ? $rr['pdesc'] . '<br />' : '');
@ -124,23 +121,19 @@ function directory_content(&$a) {
$details .= ', ';
$details .= $rr['country-name'];
}
if(strlen($rr['dob'])) {
if(($years = age($rr['dob'],$rr['timezone'],'')) != 0)
$details .= '<br />' . t('Age: ') . $years ;
}
if(strlen($rr['gender']))
$details .= '<br />' . t('Gender: ') . $rr['gender'];
// if(strlen($rr['dob'])) {
// if(($years = age($rr['dob'],$rr['timezone'],'')) != 0)
// $details .= '<br />' . t('Age: ') . $years ;
// }
// if(strlen($rr['gender']))
// $details .= '<br />' . t('Gender: ') . $rr['gender'];
if($rr['page-flags'] == PAGE_NORMAL)
$page_type = "Personal Profile";
if($rr['page-flags'] == PAGE_SOAPBOX)
$page_type = "Fan Page";
if($rr['page-flags'] == PAGE_COMMUNITY)
$page_type = "Community Forum";
if($rr['page-flags'] == PAGE_FREELOVE)
$page_type = "Open Forum";
if($rr['page-flags'] == PAGE_PRVGROUP)
$page_type = "Private Group";
// show if account is a community account
// ToDo the other should be also respected, but first we need a good translatiion
// and systemwide consistency for displaying the page type
if((intval($rr['page-flags']) == PAGE_COMMUNITY) OR (intval($rr['page-flags']) == PAGE_PRVGROUP))
$community = true;
$profile = $rr;
@ -159,32 +152,35 @@ function directory_content(&$a) {
$about = ((x($profile,'about') == 1) ? t('About:') : False);
$tpl = get_markup_template('directory_item.tpl');
if($a->theme['template_engine'] === 'internal') {
$location_e = template_escape($location);
}
else {
$location_e = $location;
}
$photo_menu = array(array(t("View Profile"), zrl($profile_link)));
$entry = replace_macros($tpl,array(
'$id' => $rr['id'],
'$profile_link' => $profile_link,
'$photo' => proxy_url($a->get_cached_avatar_image($rr[$photo])),
'$alt_text' => $rr['name'],
'$name' => $rr['name'],
'$details' => $pdesc . $details,
'$page_type' => $page_type,
'$profile' => $profile,
'$location' => $location_e,
'$gender' => $gender,
'$pdesc' => $pdesc,
'$marital' => $marital,
'$homepage' => $homepage,
'$about' => $about,
$entry = array(
'id' => $rr['id'],
'url' => $profile_link,
'itemurl' => $itemurl,
'thumb' => proxy_url($a->get_cached_avatar_image($rr[$photo]), false, PROXY_SIZE_THUMB),
'img_hover' => $rr['name'],
'name' => $rr['name'],
'details' => $details,
'account_type' => ($community ? t('Forum') : ''),
'profile' => $profile,
'location' => $location_e,
'tags' => $rr['pub_keywords'],
'gender' => $gender,
'pdesc' => $pdesc,
'marital' => $marital,
'homepage' => $homepage,
'about' => $about,
'photo_menu' => $photo_menu,
));
);
$arr = array('contact' => $rr, 'entry' => $entry);
@ -193,12 +189,27 @@ function directory_content(&$a) {
unset($profile);
unset($location);
$o .= $entry;
if(! $arr['entry'])
continue;
$entries[] = $arr['entry'];
}
$o .= "<div class=\"directory-end\" ></div>\r\n";
$o .= paginate($a);
$tpl = get_markup_template('directory_header.tpl');
$o .= replace_macros($tpl, array(
'$search' => $search,
'$globaldir' => t('Global Directory'),
'$gdirpath' => $gdirpath,
'$desc' => t('Find on this site'),
'$contacts' => $entries,
'$finding' => t('Finding:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => t('Site Directory'),
'$submit' => t('Find'),
'$paginate' => paginate($a),
));
}
else

View File

@ -1,15 +1,23 @@
<?php
require_once('include/contact_widgets.php');
require_once('include/socgraph.php');
require_once('include/Contact.php');
require_once('include/contact_selectors.php');
require_once('mod/contacts.php');
function dirfind_init(&$a) {
if(! local_user()) {
notice( t('Permission denied.') . EOL );
return;
}
if(! x($a->page,'aside'))
$a->page['aside'] = '';
$a->page['aside'] .= follow_widget();
$a->page['aside'] .= findpeople_widget();
$a->page['aside'] .= follow_widget();
}
@ -17,13 +25,20 @@ function dirfind_init(&$a) {
function dirfind_content(&$a, $prefix = "") {
$community = false;
$discover_user = false;
$local = get_config('system','poco_local_search');
$search = $prefix.notags(trim($_REQUEST['search']));
if(strpos($search,'@') === 0)
if(strpos($search,'@') === 0) {
$search = substr($search,1);
if ((valid_email($search) AND validate_email($search)) OR
(substr(normalise_link($search), 0, 7) == "http://")) {
$user_data = probe_url($search);
$discover_user = (in_array($user_data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)));
}
}
if(strpos($search,'!') === 0) {
$search = substr($search,1);
@ -32,13 +47,34 @@ function dirfind_content(&$a, $prefix = "") {
$o = '';
$o .= replace_macros(get_markup_template("section_title.tpl"),array(
'$title' => sprintf( t('People Search - %s'), $search)
));
if($search) {
if ($local) {
if ($discover_user) {
$j = new stdClass();
$j->total = 1;
$j->items_page = 1;
$j->page = $a->pager['page'];
$objresult = new stdClass();
$objresult->cid = 0;
$objresult->name = $user_data["name"];
$objresult->addr = $user_data["addr"];
$objresult->url = $user_data["url"];
$objresult->photo = $user_data["photo"];
$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"];
$j->results[] = $objresult;
poco_check($user_data["url"], $user_data["name"], $user_data["network"], $user_data["photo"],
"", "", "", "", "", datetime_convert(), 0);
} elseif ($local) {
if ($community)
$extra_sql = " AND `community`";
@ -48,14 +84,24 @@ function dirfind_content(&$a, $prefix = "") {
$perpage = 80;
$startrec = (($a->pager['page']) * $perpage) - $perpage;
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;
$count = q("SELECT count(*) AS `total` FROM `gcontact` WHERE `network` IN ('%s', '%s', '%s') AND
(`url` REGEXP '%s' OR `name` REGEXP '%s' OR `location` REGEXP '%s' OR
`about` REGEXP '%s' OR `keywords` REGEXP '%s')".$extra_sql,
dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA),
dbesc(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)));
$results = q("SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`photo`, `gcontact`.`keywords`
$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`.`uid` = %d AND NOT `contact`.`blocked`
@ -67,7 +113,7 @@ function dirfind_content(&$a, $prefix = "") {
GROUP BY `gcontact`.`nurl`
ORDER BY `gcontact`.`updated` DESC LIMIT %d, %d",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA),
dbesc(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)),
intval($startrec), intval($perpage));
@ -87,9 +133,11 @@ function dirfind_content(&$a, $prefix = "") {
$objresult = new stdClass();
$objresult->cid = $result["cid"];
$objresult->name = $result["name"];
$objresult->addr = $result["addr"];
$objresult->url = $result["url"];
$objresult->photo = $result["photo"];
$objresult->tags = $result["keywords"];
$objresult->network = $result["network"];
$j->results[] = $objresult;
}
@ -113,29 +161,65 @@ function dirfind_content(&$a, $prefix = "") {
if(count($j->results)) {
$tpl = get_markup_template('match.tpl');
$id = 0;
foreach($j->results as $jj) {
$alt_text = "";
$contact_details = get_contact_details_by_url($jj->url, local_user());
$itemurl = (($contact_details["addr"] != "") ? $contact_details["addr"] : $jj->url);
// If We already know this contact then don't show the "connect" button
if ($jj->cid > 0) {
$connlnk = "";
$conntxt = "";
$contact = q("SELECT * FROM `contact` WHERE `id` = %d",
intval($jj->cid));
if ($contact) {
$photo_menu = contact_photo_menu($contact[0]);
$details = _contact_detail_for_template($contact[0]);
$alt_text = $details['alt_text'];
} else
$photo_menu = array();
} 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);
}
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
$o .= replace_macros($tpl,array(
'$url' => zrl($jj->url),
'$name' => $jj->name,
'$photo' => proxy_url($jj->photo),
'$tags' => $jj->tags,
'$conntxt' => $conntxt,
'$connlnk' => $connlnk,
));
$entry = array(
'alt_text' => $alt_text,
'url' => zrl($jj->url),
'itemurl' => $itemurl,
'name' => htmlentities($jj->name),
'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB),
'img_hover' => $jj->tags,
'conntxt' => $conntxt,
'connlnk' => $connlnk,
'photo_menu' => $photo_menu,
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],
'account_type' => (($contact_details['community']) ? t('Forum') : ''),
'network' => network_to_name($jj->network, $jj->url),
'id' => ++$id,
);
$entries[] = $entry;
}
$tpl = get_markup_template('viewcontact_template.tpl');
$o .= replace_macros($tpl,array(
'title' => sprintf( t('People Search - %s'), $search),
'$contacts' => $entries,
'$paginate' => paginate($a),
));
}
else {
info( t('No matches') . EOL);
@ -143,7 +227,5 @@ function dirfind_content(&$a, $prefix = "") {
}
$o .= '<div class="clear"></div>';
$o .= paginate($a);
return $o;
}

View File

@ -89,51 +89,16 @@ function display_init(&$a) {
}
function display_fetchauthor($a, $item) {
require_once("mod/proxy.php");
require_once("include/bbcode.php");
$profiledata = array();
$profiledata["uid"] = -1;
$profiledata["nickname"] = $item["author-name"];
$profiledata["name"] = $item["author-name"];
$profiledata["picdate"] = "";
$profiledata["photo"] = proxy_url($item["author-avatar"]);
$profiledata["photo"] = $item["author-avatar"];
$profiledata["url"] = $item["author-link"];
$profiledata["network"] = $item["network"];
// Fetching further contact data from the contact table
$r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` = '%s'",
dbesc(normalise_link($profiledata["url"])), intval($item["uid"]), dbesc($item["network"]));
if (!count($r))
$r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
dbesc(normalise_link($profiledata["url"])), intval($item["uid"]));
if (!count($r))
$r = q("SELECT `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
dbesc(normalise_link($profiledata["url"])));
if (count($r)) {
$profiledata["photo"] = proxy_url($r[0]["photo"]);
$profiledata["address"] = proxy_parse_html(bbcode($r[0]["location"]));
$profiledata["about"] = proxy_parse_html(bbcode($r[0]["about"]));
if ($r[0]["nick"] != "")
$profiledata["nickname"] = $r[0]["nick"];
}
// Fetching profile data from unique contacts
$r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($profiledata["url"])));
if (count($r)) {
if ($profiledata["photo"] == "")
$profiledata["photo"] = proxy_url($r[0]["avatar"]);
if ($profiledata["address"] == "")
$profiledata["address"] = proxy_parse_html(bbcode($r[0]["location"]));
if ($profiledata["about"] == "")
$profiledata["about"] = proxy_parse_html(bbcode($r[0]["about"]));
if (($profiledata["nickname"] == "") AND ($r[0]["nick"] != ""))
$profiledata["nickname"] = $r[0]["nick"];
}
// Check for a repeated message
$skip = false;
$body = trim($item["body"]);
@ -187,28 +152,49 @@ function display_fetchauthor($a, $item) {
$profiledata["address"] = "";
$profiledata["about"] = "";
}
// Fetching profile data from unique contacts
if ($profiledata["url"] != "") {
$r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($profiledata["url"])));
if (count($r)) {
$profiledata["photo"] = proxy_url($r[0]["avatar"]);
$profiledata["address"] = proxy_parse_html(bbcode($r[0]["location"]));
$profiledata["about"] = proxy_parse_html(bbcode($r[0]["about"]));
if ($r[0]["nick"] != "")
$profiledata["nickname"] = $r[0]["nick"];
}
// Fetching further contact data from the contact table
$r = q("SELECT `uid`, `network`, `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `network` = '%s'",
dbesc(normalise_link($profiledata["url"])), intval($item["uid"]), dbesc($item["network"]));
if (!count($r))
$r = q("SELECT `uid`, `network`, `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
dbesc(normalise_link($profiledata["url"])), intval($item["uid"]));
if (!count($r))
$r = q("SELECT `uid`, `network`, `photo`, `nick`, `location`, `about` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
dbesc(normalise_link($profiledata["url"])));
if (count($r)) {
if ((($r[0]["uid"] != local_user()) OR !local_user()) AND ($profiledata["network"] == NETWORK_DIASPORA)) {
$r[0]["location"] = "";
$r[0]["about"] = "";
}
$profiledata["photo"] = $r[0]["photo"];
$profiledata["address"] = $r[0]["location"];
$profiledata["about"] = $r[0]["about"];
if ($r[0]["nick"] != "")
$profiledata["nickname"] = $r[0]["nick"];
}
// Fetching profile data from unique contacts
$r = q("SELECT `avatar`, `nick`, `location`, `about` FROM `unique_contacts` WHERE `url` = '%s'", dbesc(normalise_link($profiledata["url"])));
if (count($r)) {
if ($profiledata["photo"] == "")
$profiledata["photo"] = $r[0]["avatar"];
if (($profiledata["address"] == "") AND ($profiledata["network"] != NETWORK_DIASPORA))
$profiledata["address"] = $r[0]["location"];
if (($profiledata["about"] == "") AND ($profiledata["network"] != NETWORK_DIASPORA))
$profiledata["about"] = $r[0]["about"];
if (($profiledata["nickname"] == "") AND ($r[0]["nick"] != ""))
$profiledata["nickname"] = $r[0]["nick"];
}
if (local_user()) {
if (in_array($profiledata["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
$profiledata["remoteconnect"] = $a->get_baseurl()."/follow?url=".urlencode($profiledata["url"]);
//if ($profiledata["network"] == NETWORK_DFRN) {
// $connect = str_replace("/profile/", "/dfrn_request/", $profiledata["url"])."&addr=".bin2hex($a->get_baseurl()."/profile/".$a->user["nickname"]);
// $profiledata["remoteconnect"] = $connect;
//} elseif ($profiledata["network"] == NETWORK_DIASPORA)
// $profiledata["remoteconnect"] = $a->get_baseurl()."/contacts?add=".GetProfileUsername($profiledata["url"], "", true);
} elseif ($profiledata["network"] == NETWORK_DFRN) {
$connect = str_replace("/profile/", "/dfrn_request/", $profiledata["url"]);
$profiledata["remoteconnect"] = $connect;
@ -224,7 +210,6 @@ function display_content(&$a, $update = 0) {
return;
}
require_once("include/bbcode.php");
require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');

View File

@ -60,7 +60,7 @@ function editpost_content(&$a) {
$tpl = get_markup_template("jot.tpl");
if(($group) || (is_array($a->user) && ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid'])))))
$lockstate = 'lock';
else
@ -93,17 +93,17 @@ function editpost_content(&$a) {
$jotnets .= '<div class="profile-jot-net"><input type="checkbox" name="pubmail_enable"' . $selected . ' value="1" /> '
. t("Post to Email") . '</div>';
}*/
call_hooks('jot_tool', $jotplugins);
//call_hooks('jot_networks', $jotnets);
//$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins));
//$tpl = replace_macros($tpl,array('$jotplugins' => $jotplugins));
$o .= replace_macros($tpl,array(
'$is_edit' => true,
'$return_path' => $_SESSION['return_url'],
'$action' => 'item',
'$share' => t('Save'),

View File

@ -154,6 +154,7 @@ function events_post(&$a) {
if(! $cid)
proc_run('php',"include/notifier.php","event","$item_id");
goaway($_SESSION['return_url']);
}
@ -165,6 +166,9 @@ function events_content(&$a) {
return;
}
if($a->argc == 1)
$_SESSION['return_url'] = $a->get_baseurl() . '/' . $a->cmd;
if(($a->argc > 2) && ($a->argv[1] === 'ignore') && intval($a->argv[2])) {
$r = q("update event set ignore = 1 where id = %d and uid = %d",
intval($a->argv[2]),
@ -179,14 +183,69 @@ function events_content(&$a) {
);
}
if ($a->theme_events_in_profile)
nav_set_selected('home');
else
nav_set_selected('events');
$editselect = 'none';
if( feature_enabled(local_user(), 'richtext') )
$editselect = 'textareas';
// First day of the week (0 = Sunday)
$firstDay = get_pconfig(local_user(),'system','first_day_of_week');
if ($firstDay === false) $firstDay=0;
$i18n = array(
"firstDay" => $firstDay,
"Sun" => t("Sun"),
"Mon" => t("Mon"),
"Tue" => t("Tue"),
"Wed" => t("Wed"),
"Thu" => t("Thu"),
"Fri" => t("Fri"),
"Sat" => t("Sat"),
"Sunday" => t("Sunday"),
"Monday" => t("Monday"),
"Tuesday" => t("Tuesday"),
"Wednesday" => t("Wednesday"),
"Thursday" => t("Thursday"),
"Friday" => t("Friday"),
"Saturday" => t("Saturday"),
"Jan" => t("Jan"),
"Feb" => t("Feb"),
"Mar" => t("Mar"),
"Apr" => t("Apr"),
"May" => t("May"),
"Jun" => t("Jun"),
"Jul" => t("Jul"),
"Aug" => t("Aug"),
"Sep" => t("Sept"),
"Oct" => t("Oct"),
"Nov" => t("Nov"),
"Dec" => t("Dec"),
"January" => t("January"),
"February" => t("February"),
"March" => t("March"),
"April" => t("April"),
"May" => t("May"),
"June" => t("June"),
"July" => t("July"),
"August" => t("August"),
"September" => t("September"),
"October" => t("October"),
"November" => t("November"),
"December" => t("December"),
"today" => t("today"),
"month" => t("month"),
"week" => t("week"),
"day" => t("day"),
);
$htpl = get_markup_template('event_head.tpl');
$a->page['htmlhead'] .= replace_macros($htpl,array(
'$baseurl' => $a->get_baseurl(),
'$i18n' => $i18n,
'$editselect' => $editselect
));
@ -198,7 +257,8 @@ function events_content(&$a) {
$o ="";
// tabs
$tabs = profile_tabs($a, True);
if ($a->theme_events_in_profile)
$tabs = profile_tabs($a, True);
@ -234,7 +294,7 @@ function events_content(&$a) {
$m = intval($thismonth);
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
if($y < 1901)
$y = 1900;
@ -449,7 +509,7 @@ function events_content(&$a) {
else
$sh_checked = (($orig_event['allow_cid'] === '<' . local_user() . '>' && (! $orig_event['allow_gid']) && (! $orig_event['deny_cid']) && (! $orig_event['deny_gid'])) ? '' : ' checked="checked" ' );
if($cid)
if($cid OR ($mode !== 'new'))
$sh_checked .= ' disabled="disabled" ';
@ -480,6 +540,9 @@ function events_content(&$a) {
require_once('include/acl_selectors.php');
if ($mode === 'new')
$acl = (($cid) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $a->user)));
$tpl = get_markup_template('event_form.tpl');
$o .= replace_macros($tpl,array(
@ -507,7 +570,7 @@ function events_content(&$a) {
'$sh_text' => t('Share this event'),
'$sh_checked' => $sh_checked,
'$preview' => t('Preview'),
'$acl' => (($cid) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $a->user))),
'$acl' => $acl,
'$submit' => t('Submit')
));

View File

@ -35,12 +35,14 @@ function fbrowser_content($a){
$sql_extra2 = " ORDER BY created DESC LIMIT 0, 10";
if ($a->argc==2){
$albums = q("SELECT distinct(`album`) AS `album` FROM `photo` WHERE `uid` = %d ",
intval(local_user())
$albums = q("SELECT distinct(`album`) AS `album` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' ",
intval(local_user()),
dbesc('Contact Photos'),
dbesc( t('Contact Photos'))
);
// anon functions only from 5.3.0... meglio tardi che mai..
$folder1 = function($el) use ($mode) {return array(bin2hex($el['album']),$el['album']);};
$albums = array_map( $folder1 , $albums);
function _map_folder1($el){return array(bin2hex($el['album']),$el['album']);};
$albums = array_map( "_map_folder1" , $albums);
}
@ -53,12 +55,14 @@ function fbrowser_content($a){
}
$r = q("SELECT `resource-id`, `id`, `filename`, type, min(`scale`) AS `hiq`,max(`scale`) AS `loq`, `desc`
FROM `photo` WHERE `uid` = %d $sql_extra
FROM `photo` WHERE `uid` = %d $sql_extra AND `album` != '%s' AND `album` != '%s'
GROUP BY `resource-id` $sql_extra2",
intval(local_user())
intval(local_user()),
dbesc('Contact Photos'),
dbesc( t('Contact Photos'))
);
function files1($rr){
function _map_files1($rr){
global $a;
$types = Photo::supportedTypes();
$ext = $types[$rr['type']];
@ -71,12 +75,12 @@ function fbrowser_content($a){
}
return array(
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '.' .$ext,
$a->get_baseurl() . '/photos/' . $a->user['nickname'] . '/image/' . $rr['resource-id'],
$filename_e,
$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['loq'] . '.'. $ext
);
}
$files = array_map("files1", $r);
$files = array_map("_map_files1", $r);
$tpl = get_markup_template($template_file);
@ -94,11 +98,11 @@ function fbrowser_content($a){
break;
case "file":
if ($a->argc==2){
$files = q("SELECT id, filename, filetype FROM `attach` WHERE `uid` = %d ",
$files = q("SELECT `id`, `filename`, `filetype` FROM `attach` WHERE `uid` = %d ",
intval(local_user())
);
function files2($rr){ global $a;
function _map_files2($rr){ global $a;
list($m1,$m2) = explode("/",$rr['filetype']);
$filetype = ( (file_exists("images/icons/$m1.png"))?$m1:"zip");
@ -111,8 +115,7 @@ function fbrowser_content($a){
return array( $a->get_baseurl() . '/attach/' . $rr['id'], $filename_e, $a->get_baseurl() . '/images/icons/16/' . $filetype . '.png');
}
$files = array_map("files2", $files);
//echo "<pre>"; var_dump($files); killme();
$files = array_map("_map_files2", $files);
$tpl = get_markup_template($template_file);

87
mod/follow.php Executable file → Normal file
View File

@ -15,6 +15,8 @@ function follow_content(&$a) {
$uid = local_user();
$url = notags(trim($_REQUEST['url']));
$submit = t('Submit Request');
// There is a current issue. It seems as if you can't start following a Friendica that is following you
// With Diaspora this works - but Friendica is special, it seems ...
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND ((`rel` != %d) OR (`network` = '%s')) AND
@ -25,12 +27,34 @@ function follow_content(&$a) {
if ($r) {
notice(t('You already added this contact.').EOL);
goaway($_SESSION['return_url']);
$submit = "";
//goaway($_SESSION['return_url']);
// NOTREACHED
}
$ret = probe_url($url);
if (($ret["network"] == NETWORK_DIASPORA) AND !get_config('system','diaspora_enabled')) {
notice( t("Diaspora support isn't enabled. Contact can't be added.") . EOL);
$submit = "";
//goaway($_SESSION['return_url']);
// NOTREACHED
}
if (($ret["network"] == NETWORK_OSTATUS) AND get_config('system','ostatus_disabled')) {
notice( t("OStatus support is disabled. Contact can't be added.") . EOL);
$submit = "";
//goaway($_SESSION['return_url']);
// NOTREACHED
}
if ($ret["network"] == NETWORK_PHANTOM) {
notice( t("The network type couldn't be detected. Contact can't be added.") . EOL);
$submit = "";
//goaway($_SESSION['return_url']);
// NOTREACHED
}
if ($ret["network"] == NETWORK_MAIL)
$ret["url"] = $ret["addr"];
@ -55,35 +79,54 @@ function follow_content(&$a) {
// Makes the connection request for friendica contacts easier
$_SESSION["fastlane"] = $ret["url"];
$r = q("SELECT `location`, `about`, `keywords` FROM `gcontact` WHERE `nurl` = '%s'",
normalise_link($ret["url"]));
if (!$r)
$r = array(array("location" => "", "about" => "", "keywords" => ""));
if($ret['network'] === NETWORK_DIASPORA) {
$r[0]["location"] = "";
$r[0]["about"] = "";
}
$header = $ret["name"];
if ($ret["addr"] != "")
$header .= " <".$ret["addr"].">";
$header .= " (".network_to_name($ret['network']).")";
$header .= " (".network_to_name($ret['network'], $ret['url']).")";
$o = replace_macros($tpl,array(
'$header' => htmlentities($header),
'$photo' => $ret["photo"],
'$desc' => "",
'$pls_answer' => t('Please answer the following:'),
'$does_know_you' => array('knowyou', sprintf(t('Does %s know you?'),$ret["name"]), false, '', array(t('No'),t('Yes'))),
'$add_note' => t('Add a personal note:'),
'$page_desc' => "",
'$friendica' => "",
'$statusnet' => "",
'$diaspora' => "",
'$diasnote' => "",
'$your_address' => t('Your Identity Address:'),
'$invite_desc' => "",
'$emailnet' => "",
'$submit' => t('Submit Request'),
'$cancel' => t('Cancel'),
'$nickname' => "",
'$name' => $ret["name"],
'$url' => $ret["url"],
'$myaddr' => $myaddr,
'$request' => $request
'$photo' => proxy_url($ret["photo"], false, PROXY_SIZE_SMALL),
'$desc' => "",
'$pls_answer' => t('Please answer the following:'),
'$does_know_you' => array('knowyou', sprintf(t('Does %s know you?'),$ret["name"]), false, '', array(t('No'),t('Yes'))),
'$add_note' => t('Add a personal note:'),
'$page_desc' => "",
'$friendica' => "",
'$statusnet' => "",
'$diaspora' => "",
'$diasnote' => "",
'$your_address' => t('Your Identity Address:'),
'$invite_desc' => "",
'$emailnet' => "",
'$submit' => $submit,
'$cancel' => t('Cancel'),
'$nickname' => "",
'$name' => $ret["name"],
'$url' => $ret["url"],
'$zrl' => zrl($ret["url"]),
'$url_label' => t("Profile URL"),
'$myaddr' => $myaddr,
'$request' => $request,
'$location' => bbcode($r[0]["location"]),
'$location_label' => t("Location:"),
'$about' => bbcode($r[0]["about"], false, false),
'$about_label' => t("About:"),
'$keywords' => $r[0]["keywords"],
'$keywords_label' => t("Tags:")
));
return $o;
}

View File

@ -7,7 +7,7 @@ function validate_members(&$item) {
function group_init(&$a) {
if(local_user()) {
require_once('include/group.php');
$a->page['aside'] = group_side('contacts','group',false,(($a->argc > 1) ? intval($a->argv[1]) : 0));
$a->page['aside'] = group_side('contacts','group','extended',(($a->argc > 1) ? intval($a->argv[1]) : 0));
}
}
@ -62,12 +62,12 @@ function group_post(&$a) {
$a->page['aside'] = group_side();
}
return;
return;
}
function group_content(&$a) {
$change = false;
if(! local_user()) {
notice( t('Permission denied') . EOL);
return;
@ -172,7 +172,7 @@ function group_content(&$a) {
'$form_security_token' => get_form_security_token("group_drop"),
));
$context = $context + array(
'$title' => t('Group Editor'),
'$gname' => array('groupname',t('Group Name: '),$group['name'], ''),
@ -190,9 +190,10 @@ function group_content(&$a) {
'label_members' => t('Members'),
'members' => array(),
'label_contacts' => t('All Contacts'),
'group_is_empty' => t('Group is empty'),
'contacts' => array(),
);
$sec_token = addslashes(get_form_security_token('group_member_change'));
$textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
foreach($members as $member) {
@ -204,7 +205,7 @@ function group_content(&$a) {
group_rmv_member(local_user(),$group['name'],$member['id']);
}
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 and `pending` = 0 and `self` = 0 ORDER BY `name` ASC",
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `self` ORDER BY `name` ASC",
intval(local_user())
);
@ -226,8 +227,7 @@ function group_content(&$a) {
echo replace_macros($tpl, $context);
killme();
}
return replace_macros($tpl, $context);
}

View File

@ -1,4 +1,5 @@
<?php
require_once "include/Photo.php";
$install_wizard_pass=1;
@ -10,6 +11,14 @@ function install_init(&$a){
echo "ok";
killme();
}
// We overwrite current theme css, because during install we could not have a working mod_rewrite
// so we could not have a css at all. Here we set a static css file for the install procedure pages
$a->config['system']['theme'] = "../install";
$a->theme['stylesheet'] = $a->get_baseurl()."/view/install/style.css";
global $install_wizard_pass;
if (x($_POST,'pass'))
$install_wizard_pass = intval($_POST['pass']);
@ -84,15 +93,15 @@ function install_post(&$a) {
'$phpath' => $phpath,
'$adminmail' => $adminmail
));
$result = file_put_contents('.htconfig.php', $txt);
if(! $result) {
$a->data['txt'] = $txt;
}
$errors = load_database($db);
if($errors)
$a->data['db_failed'] = $errors;
@ -177,6 +186,8 @@ function install_content(&$a) {
check_funcs($checks);
check_imagik($checks);
check_htconfig($checks);
check_smarty3($checks);
@ -321,7 +332,7 @@ function check_php(&$phpath, &$checks) {
$help = "";
if(!$passed) {
$help .= t('Could not find a command line version of PHP in the web server PATH.'). EOL;
$help .= t("If you don't have a command line version of PHP installed on server, you will not be able to run background polling via cron. See <a href='http://friendica.com/node/27'>'Activating scheduled tasks'</a>") . EOL ;
$help .= t("If you don't have a command line version of PHP installed on server, you will not be able to run background polling via cron. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-poller'>'Setup the poller'</a>") . EOL ;
$help .= EOL . EOL ;
$tpl = get_markup_template('field_input.tpl');
$help .= replace_macros($tpl, array(
@ -428,10 +439,21 @@ function check_funcs(&$checks) {
$ck_funcs[5]['help']= t('Error: mcrypt PHP module required but not installed.');
}
$checks = array_merge($checks, $ck_funcs);
// check for 'mcrypt_create_iv()', needed for RINO2
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";
} else {
$__status = false;
$__help = t('Function mcrypt_create_iv() is not defined. This is needed to enable RINO2 encryption layer.');
}
check_add($checks, t('mcrypt_create_iv() function'), $__status, false, $__help);
}
/*if((x($_SESSION,'sysmsg')) && is_array($_SESSION['sysmsg']) && count($_SESSION['sysmsg']))
notice( t('Please see the file "INSTALL.txt".') . EOL);*/
}
@ -490,6 +512,24 @@ function check_htaccess(&$checks) {
}
}
function check_imagik(&$checks) {
$imagick = false;
$gif = false;
if (class_exists('Imagick')) {
$imagick = true;
$supported = Photo::supportedTypes();
if (array_key_exists('image/gif', $supported)) {
$gif = true;
}
}
check_add($checks, t('ImageMagick PHP extension is installed'), $imagick, false, "");
if ($imagick) {
check_add($checks, t('ImageMagick supports GIF'), $gif, false, "");
}
}
function manual_config(&$a) {
$data = htmlentities($a->data['txt'],ENT_COMPAT,'UTF-8');

View File

@ -18,7 +18,6 @@
require_once('include/crypto.php');
require_once('include/enotify.php');
require_once('include/email.php');
require_once('library/langdet/Text/LanguageDetect.php');
require_once('include/tags.php');
require_once('include/files.php');
require_once('include/threads.php');
@ -268,32 +267,8 @@ function item_post(&$a) {
$guid = get_guid(32);
$naked_body = preg_replace('/\[(.+?)\]/','',$body);
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$l = new Text_LanguageDetect;
//$lng = $l->detectConfidence($naked_body);
//$postopts = (($lng['language']) ? 'lang=' . $lng['language'] . ';' . $lng['confidence'] : '');
$lng = $l->detect($naked_body, 3);
if (sizeof($lng) > 0) {
$postopts = "";
foreach ($lng as $language => $score) {
if ($postopts == "")
$postopts = "lang=";
else
$postopts .= ":";
$postopts .= $language.";".$score;
}
}
logger('mod_item: detect language' . print_r($lng,true) . $naked_body, LOGGER_DATA);
}
else
$postopts = '';
item_add_language_opt($_REQUEST);
$postopts = $_REQUEST['postopts'] ? $_REQUEST['postopts'] : "";
$private = ((strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny)) ? 1 : 0);
@ -387,8 +362,7 @@ function item_post(&$a) {
if((local_user()) && (local_user() == $profile_uid)) {
$self = true;
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
intval($_SESSION['uid'])
);
intval($_SESSION['uid']));
}
elseif(remote_user()) {
if(is_array($_SESSION['remote'])) {

View File

@ -26,6 +26,18 @@ function like_content(&$a) {
case 'undislike':
$activity = ACTIVITY_DISLIKE;
break;
case 'attendyes':
case 'unattendyes':
$activity = ACTIVITY_ATTEND;
break;
case 'attendno':
case 'unattendno':
$activity = ACTIVITY_ATTENDNO;
break;
case 'attendmaybe':
case 'unattendmaybe':
$activity = ACTIVITY_ATTENDMAYBE;
break;
default:
return;
break;
@ -108,11 +120,18 @@ function like_content(&$a) {
// See if we've been passed a return path to redirect to
$return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
$verbs = " '".dbesc($activity)."' ";
$r = q("SELECT `id`, `guid` FROM `item` WHERE `verb` = '%s' AND `deleted` = 0
// event participation are essentially radio toggles. If you make a subsequent choice,
// we need to eradicate your first choice.
if($activity === ACTIVITY_ATTEND || $activity === ACTIVITY_ATTENDNO || $activity === ACTIVITY_ATTENDMAYBE) {
$verbs = " '" . dbesc(ACTIVITY_ATTEND) . "','" . dbesc(ACTIVITY_ATTENDNO) . "','" . dbesc(ACTIVITY_ATTENDMAYBE) . "' ";
}
$r = q("SELECT `id`, `guid` FROM `item` WHERE `verb` IN ( $verbs ) AND `deleted` = 0
AND `contact-id` = %d AND `uid` = %d
AND (`parent` = '%s' OR `parent-uri` = '%s' OR `thr-parent` = '%s') LIMIT 1",
dbesc($activity), intval($contact['id']), intval($owner_uid),
intval($contact['id']), intval($owner_uid),
dbesc($item_id), dbesc($item_id), dbesc($item['uri'])
);
@ -147,6 +166,8 @@ function like_content(&$a) {
$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)
$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") ;
$body = $item['body'];
@ -166,6 +187,12 @@ EOT;
$bodyverb = t('%1$s likes %2$s\'s %3$s');
if($verb === 'dislike')
$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
if($verb === 'attendyes')
$bodyverb = t('%1$s is attending %2$s\'s %3$s');
if($verb === 'attendno')
$bodyverb = t('%1$s is not attending %2$s\'s %3$s');
if($verb === 'attendmaybe')
$bodyverb = t('%1$s may attend %2$s\'s %3$s');
if(! isset($bodyverb))
return;

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