diff --git a/CHANGELOG b/CHANGELOG index 5b51a5511f..b393899df8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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) diff --git a/Vagrantfile b/Vagrantfile index 48af4ae518..4f1181b822 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -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 diff --git a/boot.php b/boot.php index dcf6c65b1e..cc56949009 100644 --- a/boot.php +++ b/boot.php @@ -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-rc' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); -define ( 'DB_UPDATE_VERSION', 1188 ); +define ( 'DB_UPDATE_VERSION', 1191 ); define ( 'EOL', "
\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); +} diff --git a/database.sql b/database.sql index 76df6aec19..e3768c1efb 100644 --- a/database.sql +++ b/database.sql @@ -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; + diff --git a/doc/Accesskeys.md b/doc/Accesskeys.md index 0c00c25476..c49e79c0ab 100644 --- a/doc/Accesskeys.md +++ b/doc/Accesskeys.md @@ -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 diff --git a/doc/Chats.md b/doc/Chats.md index 77b21833a5..3698ad15da 100644 --- a/doc/Chats.md +++ b/doc/Chats.md @@ -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". diff --git a/doc/Developers-Intro.md b/doc/Developers-Intro.md index ff8c3c54c2..7e5caae2b3 100644 --- a/doc/Developers-Intro.md +++ b/doc/Developers-Intro.md @@ -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 diff --git a/doc/FAQ.md b/doc/FAQ.md index 9197c068c5..0343833a25 100644 --- a/doc/FAQ.md +++ b/doc/FAQ.md @@ -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. diff --git a/doc/Home.md b/doc/Home.md index ff991e3d2a..b37c76417c 100644 --- a/doc/Home.md +++ b/doc/Home.md @@ -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) diff --git a/doc/Install.md b/doc/Install.md index bd15f10b5a..5afd5a22c1 100644 --- a/doc/Install.md +++ b/doc/Install.md @@ -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 diff --git a/doc/Plugins.md b/doc/Plugins.md index dcd6e3b052..24d403e1f6 100644 --- a/doc/Plugins.md +++ b/doc/Plugins.md @@ -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 @@ -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); diff --git a/doc/SSL.md b/doc/SSL.md index 0067206e5f..a72eec2a16 100644 --- a/doc/SSL.md +++ b/doc/SSL.md @@ -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 don’t 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. That’s 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 provider’s 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 it’s 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 -StartSSL’s 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 website’s 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. -Don’t 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 it’s 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 StartSSL’s 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 doesn’t 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 can’t 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 - - - DocumentRoot /var/www/anywhere - Servername www.anywhere.net - - - - DocumentRoot /var/www/anywhere - Servername www.anywhere.net - SSLEngine On - - - - - - - DocumentRoot /var/www/somewhere-else - Servername www.somewhere-else.net - - - - DocumentRoot /var/www/somewhere-else - Servername www.somewhere-else.net - SSLEngine On - - - - - -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. \ No newline at end of file +When you are done, visit the test site [SSL Labs](https://www.ssllabs.com/ssltest/) to have them check if you succeeded. diff --git a/doc/Settings.md b/doc/Settings.md index 60fff847a0..ae7d916078 100644 --- a/doc/Settings.md +++ b/doc/Settings.md @@ -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'; diff --git a/doc/Vagrant.md b/doc/Vagrant.md index 1d23ace134..4bc9e6c54d 100644 --- a/doc/Vagrant.md +++ b/doc/Vagrant.md @@ -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. diff --git a/doc/de/Chats.md b/doc/de/Chats.md index a2d06f3c4e..ae239a675b 100644 --- a/doc/de/Chats.md +++ b/doc/de/Chats.md @@ -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 ubuntuusers.de, in Wikipedia oder bei icrhelp.org (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 einfachjabber.de. @@ -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! diff --git a/doc/de/Developers.md b/doc/de/Developers.md index b1d118fd59..2b44e405ff 100644 --- a/doc/de/Developers.md +++ b/doc/de/Developers.md @@ -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 https://git-scm.com/book/de/v1. diff --git a/doc/de/FAQ.md b/doc/de/FAQ.md index d5aa19e6c7..52d56dce8a 100644 --- a/doc/de/FAQ.md +++ b/doc/de/FAQ.md @@ -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.] diff --git a/doc/de/Home.md b/doc/de/Home.md index 561809d6ce..44ebfc0285 100644 --- a/doc/de/Home.md +++ b/doc/de/Home.md @@ -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) diff --git a/doc/de/SSL.md b/doc/de/SSL.md index dd9b42676e..e9deb21b7b 100644 --- a/doc/de/SSL.md +++ b/doc/de/SSL.md @@ -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 - - DocumentRoot /var/www/anywhere - Servername www.anywhere.net - - - DocumentRoot /var/www/anywhere - Servername www.anywhere.net - SSLEngine On - - - - - - DocumentRoot /var/www/somewhere-else - Servername www.somewhere-else.net - - - DocumentRoot /var/www/somewhere-else - Servername www.somewhere-else.net - SSLEngine On - - - - -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. diff --git a/doc/events.md b/doc/events.md index abb4576871..0aca7a902b 100644 --- a/doc/events.md +++ b/doc/events.md @@ -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). \ No newline at end of file diff --git a/doc/htconfig.md b/doc/htconfig.md new file mode 100644 index 0000000000..4764c287c8 --- /dev/null +++ b/doc/htconfig.md @@ -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"; + diff --git a/doc/html/index.php b/doc/html/index.php new file mode 100644 index 0000000000..2e1b4277cf --- /dev/null +++ b/doc/html/index.php @@ -0,0 +1,16 @@ + + + + $Projectname Doxygen API Documentation + + +

$Projectname Doxygen API Documentation not rendered

+ +To get the Doxygen API Documentation you must render it with the program Doxygen (included in most distributions). +
+$ doxygen util/Doxyfile
+
+
+back + + diff --git a/doc/install-ejabberd.md b/doc/install-ejabberd.md new file mode 100644 index 0000000000..c99a845500 --- /dev/null +++ b/doc/install-ejabberd.md @@ -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)" diff --git a/doc/readme.md b/doc/readme.md index a5eeb54511..068d0c9c5c 100644 --- a/doc/readme.md +++ b/doc/readme.md @@ -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) diff --git a/images/icons.png b/images/icons.png index 0ff5c430c5..e255316e6d 100644 Binary files a/images/icons.png and b/images/icons.png differ diff --git a/include/Contact.php b/include/Contact.php index 920ec3c2b4..340b3ec6fa 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -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 .= "
  • $k
  • \n"; - else - $o .= "
  • $k
  • \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; }} diff --git a/include/Photo.php b/include/Photo.php index 785601c7e4..9732801c9a 100644 --- a/include/Photo.php +++ b/include/Photo.php @@ -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; + } diff --git a/include/Scrape.php b/include/Scrape.php index 93d68be22b..6ee3dabfca 100644 --- a/include/Scrape.php +++ b/include/Scrape.php @@ -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 : ''); $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; diff --git a/include/acl_selectors.php b/include/acl_selectors.php index f628b97309..4ef3d05ea3 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -1,6 +1,7 @@ "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 ); } diff --git a/include/api.php b/include/api.php index 2fd7d6d45a..531b66814f 100644 --- a/include/api.php +++ b/include/api.php @@ -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); } diff --git a/include/auth_ejabberd.php b/include/auth_ejabberd.php index 8b18a02c58..9a9d9accad 100755 --- a/include/auth_ejabberd.php +++ b/include/auth_ejabberd.php @@ -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; diff --git a/include/bb2diaspora.php b/include/bb2diaspora.php index fc05e720f4..a8b39f741a 100644 --- a/include/bb2diaspora.php +++ b/include/bb2diaspora.php @@ -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."
    ".$tagline; + } + $Text = $Text." ".$tagline; } } else diff --git a/include/bbcode.php b/include/bbcode.php index 13061958c5..100c3b9306 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -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('%s', - $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('%s
    ', + $url, $title, $title2); + } elseif (($simplehtml != 4) AND ($simplehtml != 0)) $text = sprintf('%s
    ', $url, $title); else { $text = sprintf('', $type); @@ -101,9 +126,9 @@ function bb_attachment($Text, $simplehtml = false, $tryoembed = true) { $text = $oembed; else { if (($image != "") AND !strstr(strtolower($oembed), "
    ', $url, $image, $title); + $text .= sprintf('
    ', $url, proxy_url($image), $title); elseif (($preview != "") AND !strstr(strtolower($oembed), "
    ', $url, $preview, $title); + $text .= sprintf('
    ', $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 . '#$]', '' . t('Image/photo') . '', $newbody); + $newbody = str_replace('[$#saved_image' . $cnt . '#$]', '' . t('Image/photo') . '', $newbody); $cnt++; } @@ -585,7 +610,7 @@ function bb_ShareAttributes($share, $simplehtml) { default: $headline = trim($share[1]).'
    '; if ($avatar != "") - $headline .= ''; + $headline .= ''; $headline .= sprintf(t('%s wrote the following post'.$reldate.':'), $profile, $author, $link); $headline .= "
    "; @@ -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$2', $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$2', $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 "
    " . $t_wrote . "
    $2
    ", $Text); + // [img=widthxheight]image source[/img] - //$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '', $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", '', $Text); $Text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '', $Text); // Images // [img]pathtoimage[/img] + $Text = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", 'bb_PictureCache', $Text); + $Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '' . t('Image/photo') . '', $Text); $Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '' . 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); diff --git a/include/contact_selectors.php b/include/contact_selectors.php index f0ac87a09f..f104866232 100644 --- a/include/contact_selectors.php +++ b/include/contact_selectors.php @@ -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') ); diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 810671a91c..bbbd941b56 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -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'] .= '' . "\r\n"; } else { @@ -970,7 +977,7 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) { . (($click) ? ' fakelink' : '') . '" ' . (($redir) ? ' target="redir" ' : '') . (($url) ? ' href="' . $url . '"' : '') . $click . ' >' . $contact['name']
+			. proxy_url($contact['micro'], false, PROXY_SIZE_THUMB) . '' . "\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( - '<3', - '</3', - '<\\3', - ':-)', - ';-)', - ':-(', - ':-P', - ':-p', - ':-\', - ':-\', - ':-x', - ':-X', - ':-D', - '8-|', - '8-O', - ':-O', - '\\o/', - 'o.O', - 'O.o', - 'o_O', - 'O_o', - ':\'(', - ':-!', - ':-/', - ':-[', - '8-)', - ':beer', - ':homebrew', - ':coffee', - ':facepalm', - ':like', - ':dislike', - '~friendica ~friendica', - 'redredmatrix', - 'redredmatrix' + '<3', + '</3', + '<\\3', + ':-)', + ';-)', + ':-(', + ':-P', + ':-p', + ':-\', + ':-\', + ':-x', + ':-X', + ':-D', + '8-|', + '8-O', + ':-O', + '\\o/', + 'o.O', + 'O.o', + 'o_O', + 'O_o', + ':\'(', + ':-!', + ':-/', + ':-[', + '8-)', + ':beer', + ':homebrew', + ':coffee', + ':facepalm', + ':like', + ':dislike', + '~friendica ~friendica', + 'redredmatrix', + 'redredmatrix' ); $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 .= '<3'; + $t .= '<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('/\
    /','$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 = '
    '.sprintf(t('Click to open/close')).''. - '