1
1
Fork 0

Merge remote-tracking branch 'origin/develop' into install_config

This commit is contained in:
Philipp Holzer 2018-04-21 14:23:49 +02:00
commit 334d392154
90 changed files with 59497 additions and 56448 deletions

4
.travis.yml Normal file
View file

@ -0,0 +1,4 @@
---
language: php
php: 5.6
install: composer install

View file

@ -953,10 +953,12 @@ function public_contact()
*/ */
function remote_user() function remote_user()
{ {
// You cannot be both local and remote // You cannot be both local and remote.
if (local_user()) { // Unncommented by rabuzarus because remote authentication to local
return false; // profiles wasn't possible anymore (2018-04-12).
} // if (local_user()) {
// return false;
// }
if (x($_SESSION, 'authenticated') && x($_SESSION, 'visitor_id')) { if (x($_SESSION, 'authenticated') && x($_SESSION, 'visitor_id')) {
return intval($_SESSION['visitor_id']); return intval($_SESSION['visitor_id']);
} }

View file

@ -25,11 +25,13 @@
"paragonie/random_compat": "^2.0", "paragonie/random_compat": "^2.0",
"pear/Text_LanguageDetect": "1.*", "pear/Text_LanguageDetect": "1.*",
"pear/Text_Highlighter": "dev-master", "pear/Text_Highlighter": "dev-master",
"seld/cli-prompt": "^1.0",
"smarty/smarty": "^3.1", "smarty/smarty": "^3.1",
"fxp/composer-asset-plugin": "~1.3", "fxp/composer-asset-plugin": "~1.3",
"bower-asset/base64": "^1.0", "bower-asset/base64": "^1.0",
"bower-asset/Chart-js": "^2.7", "bower-asset/Chart-js": "^2.7",
"bower-asset/perfect-scrollbar": "^0.6", "bower-asset/perfect-scrollbar": "^0.6",
"bower-asset/vue": "^2.5",
"npm-asset/jquery": "^2.0", "npm-asset/jquery": "^2.0",
"npm-asset/jquery-colorbox": "^1.6", "npm-asset/jquery-colorbox": "^1.6",
"npm-asset/jquery-datetimepicker": "^2.4.0", "npm-asset/jquery-datetimepicker": "^2.4.0",

66
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "12b8df66213734281765cb6e2c5a786e", "content-hash": "f97245142e60a521f048a667bec4e436",
"packages": [ "packages": [
{ {
"name": "asika/simple-console", "name": "asika/simple-console",
@ -133,6 +133,22 @@
"description": "Minimalistic but perfect custom scrollbar plugin", "description": "Minimalistic but perfect custom scrollbar plugin",
"time": "2017-01-10T01:04:09+00:00" "time": "2017-01-10T01:04:09+00:00"
}, },
{
"name": "bower-asset/vue",
"version": "v2.5.16",
"source": {
"type": "git",
"url": "https://github.com/vuejs/vue.git",
"reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vuejs/vue/zipball/25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6",
"reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6",
"shasum": ""
},
"type": "bower-asset-library"
},
{ {
"name": "divineomega/password_exposed", "name": "divineomega/password_exposed",
"version": "v2.5.1", "version": "v2.5.1",
@ -1972,6 +1988,54 @@
"description": "PSR-6 adapter for RW File Cache", "description": "PSR-6 adapter for RW File Cache",
"time": "2018-01-30T19:13:45+00:00" "time": "2018-01-30T19:13:45+00:00"
}, },
{
"name": "seld/cli-prompt",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/cli-prompt.git",
"reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd",
"reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Seld\\CliPrompt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type",
"keywords": [
"cli",
"console",
"hidden",
"input",
"prompt"
],
"time": "2017-03-18T11:32:45+00:00"
},
{ {
"name": "smarty/smarty", "name": "smarty/smarty",
"version": "v3.1.31", "version": "v3.1.31",

View file

@ -21,6 +21,18 @@ $db_user = 'mysqlusername';
$db_pass = 'mysqlpassword'; $db_pass = 'mysqlpassword';
$db_data = 'mysqldatabasename'; $db_data = 'mysqldatabasename';
// Use environment variables for mysql if they are set beforehand
if (!empty(getenv('MYSQL_HOST'))
&& !empty(getenv('MYSQL_PORT'))
&& !empty(getenv('MYSQL_USERNAME'))
&& !empty(getenv('MYSQL_PASSWORD'))
&& !empty(getenv('MYSQL_DATABASE'))) {
$db_host = getenv('MYSQL_HOST') . ':' . getenv('MYSQL_PORT');
$db_user = getenv('MYSQL_USERNAME');
$db_pass = getenv('MYSQL_PASSWORD');
$db_data = getenv('MYSQL_DATABASE');
}
// Set the database connection charset to full Unicode (utf8mb4). // Set the database connection charset to full Unicode (utf8mb4).
// Changing this value will likely corrupt the special characters. // Changing this value will likely corrupt the special characters.
// You have been warned. // You have been warned.

View file

@ -1,81 +1,88 @@
Accesskeys in Friendica Accesskeys reference
======================= =======================
* [Home](help) * [Home](help)
For an overview of the modifier key of the different browsers we suggest this [Wikipedia](https://en.wikipedia.org/wiki/Access_key) article. Access keys are keyboard shortcuts that allow you to easily navigate the user interface.
Access keys are currently not available with the Frio theme.
The specific key combinations depend on how your browser's the modifier key setting.
For an overview of modifier keys in different browsers, have a lookat [Wikipedia](https://en.wikipedia.org/wiki/Access_key) article.
For example, for moving to profile page in Firefox, press these three keys simultaneously.
[Shift] [Alt] [p]
General General
------- -------
* p: profile * p - Profile
* n: network * n - Network
* c: community * c - Community
* s: search * s - Search
* a: admin * a - Admin
* f: notifications * f - Notifications
* u: user menu (in themes "vier" and "quattro") * u - User menu
/community ../community
-------- --------
* l: Local community * l - Local community
* g: Global community * g - Global community
/profile ../profile
-------- --------
* m: Status Messages and Posts * m - Status Messages and Posts
* r: Profile Details * r - Profile Details
* h: Photo Albums * h - Photo Albums
* v: Videos * v - Videos
* e: Events and Calendar * e - Events and Calendar
* t: Personal Notes * t - Personal Notes
* k: View Contacts * k - View Contacts
/contacts (contact list) ../contacts (contact list)
--------- ---------
* g: Suggestions * g - Suggestions
* l: Show all Contacts * l - Show all Contacts
* o: Only show unblocked contacts * o - Only show unblocked contacts
* b: Only show blocked contacts * b - Only show blocked contacts
* i: Only show ignored contacts * i - Only show ignored contacts
* y: Only show archived contacts * y - Only show archived contacts
* h: Only show hidden contacts * h - Only show hidden contacts
/contacts (single contact view) ../contacts (single contact view)
------------------------------- -------------------------------
* m: Status messages * m - Status messages
* o: Profile * o - Profile
* t: Contacts * t - Contacts
* d: Common friends * d - Common friends
* r: Advanced * r - Advanced
/message ../message
-------- --------
* m: New message * m - New message
/network ../network
-------- --------
* e: Sort by Comment Date * e - Sort by Comment Date
* t: Sort by Post Date * t - Sort by Post Date
* r: Conversation (Posts that mention or involve you) * r - Conversation (Posts that mention or involve you)
* w: New posts * w - New posts
* b: Bookmarks * b - Bookmarks
* m: Favourite Posts * m - Favourite Posts
/notifications ../notifications
-------------- --------------
* y: System * y - System
* w: Network * w - Network
* r: Personal * r - Personal
* h: Home * h - Home
* i: Introductions * i - Introductions
/settings ../settings
--------- ---------
* o: Account * o - Account
* t: Additional features * t - Additional features
* w: Social Networks * w - Social Networks
* l: Addons * l - Addons
* d: Delegations * d - Delegations
* b: Connected apps * b - Connected apps
* e: Export personal data * e - Export personal data
* r: Remove account * r - Remove account

View file

@ -7,10 +7,10 @@ Registration
--- ---
Not all Friendica sites allow open registration. Not all Friendica sites allow open registration.
If registration is allowed, you will see a "Register" link immediately below the login prompt on the site home page. If registration is allowed, you will see a "Register" link immediately below the login prompt on the site's home page.
Following this link will take you to the site registration page. Following this link will take you to the site registration page.
The strength of our network is that lots of different sites are all completely compatible with each other. The strength of our network is that lots of different sites are all completely compatible with each other.
If the site you're visting doesn't allow registration, or you think you might prefer another one, you can find a [list of public servers here](https://dir.friendica.social/servers), and find one that meets your needs. If the site you're visting doesn't allow registration, or you think you might prefer another one, there is a [list of public servers here](https://dir.friendica.social/servers) and hopefully you will find one that meets your needs.
If you'd like to have your own server, you can do that too. If you'd like to have your own server, you can do that too.
Visit [the Friendica website](http://friendi.ca/) to download the code with setup instructions. Visit [the Friendica website](http://friendi.ca/) to download the code with setup instructions.
@ -44,12 +44,12 @@ A nickname is used to generate web addresses for many of your personal pages, an
Due to the way that the nickname is used, it has some limitations. Due to the way that the nickname is used, it has some limitations.
It must contain only US-ASCII text characters and numbers, and must also start with a text character. It must contain only US-ASCII text characters and numbers, and must also start with a text character.
It also must be unique on this system. It also must be unique on this system.
This is used in many places to identify your account, and once set - cannot be changed. This is used in many places to identify your account, and once set it cannot be changed.
###Directory Publishing ###Directory Publishing
The registration form also allows you to choose whether or not to list your account in the online directory. The registration form also allows you to choose whether or not to list your account in the online directory of your node.
This is like a "phone book" and you may choose to be unlisted. This is like a "phone book" and you may choose to be unlisted.
We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you. We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you.
If you choose 'No', you will essentially be invisible and have few opportunities for interaction. If you choose 'No', you will essentially be invisible and have few opportunities for interaction.
@ -59,7 +59,7 @@ Whichever you choose, this can be changed any time from your Settings page after
Once you have provided the necessary details, click the 'Register' button. Once you have provided the necessary details, click the 'Register' button.
An email will be sent to you providing your account login details. An email will be sent to you providing your account login details.
Please watch your email (including spam folders) for your registration details and initial password. Please check your email (including spam folders) for your registration details and initial password.
Login Page Login Page
--- ---
@ -67,9 +67,9 @@ Login Page
On the 'Login' page, please enter your login information that was provided during registration. On the 'Login' page, please enter your login information that was provided during registration.
You may use either your nickname or email address as a Login Name. You may use either your nickname or email address as a Login Name.
If you use your account to manage multiple '[Pages](help/Pages)' and these all have the same email address, please enter the nickname for the account you wish to manage. If you use your account to manage other accounts and these all have the same email address, please enter the nickname for the account you wish to manage.
*If* your account has been OpenID enabled, you may use your OpenID address as a login name and leave the password blank. If your account has been OpenID enabled, you may use your OpenID address as a login name and leave the password blank.
You will be redirected to your OpenID provider to complete your authorisation. You will be redirected to your OpenID provider to complete your authorisation.
Otherwise, enter your password. Otherwise, enter your password.
@ -84,7 +84,7 @@ After your first login, please visit the 'Settings' page from the top menu bar a
Getting Started Getting Started
--- ---
A ['Tips for New Members'](newmember) link will show up on your network and home pages for two weeks to provide some important Getting Started information. A link with ['Tips for New Members'](newmember) will show up on your network and home pages for two weeks providing key information for getting started.
Retrieving Personal Data Retrieving Personal Data
--- ---
@ -99,6 +99,8 @@ See Also
* [Profiles](help/Profiles) * [Profiles](help/Profiles)
* [Global Directory](help/Making-Friends#1_1)
* [Groups and Privacy](help/Groups-and-Privacy) * [Groups and Privacy](help/Groups-and-Privacy)
* [Move Account](help/Move-Account) * [Move Account](help/Move-Account)

View file

@ -3,21 +3,23 @@ Making Friends
* [Home](help) * [Home](help)
Friendship in Friendica can take on a great many different meanings. Friendship in Friendica can sometimes take on different meaning.
But let's keep it simple, you want to be friends with somebody. But let's keep it simple; you want to be friends with somebody.
How do you do it? How do you do it?
The Directories The Directories
--- ---
Friendica has two different kinds of "address book": Friendica has two different kinds of "address book".
The directory of the Friendica server you are registered on and the global directory that collects account information across all Friendica instances. The directory of the Friendica server you are registered on and a global directory to which your and other Friendica servers submit account information.
The first thing you can do is look at the **Directory**. The first thing you can do is look at the **Directory**.
The directory is split up into two parts. The directory is split up into two parts.
If you click the directory button, you will be presented with a list of all members (who chose to be listed) on your server. If you click the directory button, you will be presented with a list of all members (who chose to be listed) on your server.
You'll also see a link to the **Global Directory**. You'll also see a link to a **Global Directory**.
If you click through to the global directory, you will be presented with a list of everybody who chose to be listed across all instances of Friendica. There are several global directories across the globe that regularly exchange information with each other.
The specific global directory that you see usually depends on where your server is located.
If you click through to the global directory, you will be presented with a list of everybody who choses to be listed across all instances of Friendica.
You will also see a "Show Community Forums" link, which will direct you to Groups, Forums and Fanpages. You will also see a "Show Community Forums" link, which will direct you to Groups, Forums and Fanpages.
You connect to people, groups and forums in the same way, except groups and forums will automatically accept your introduction request, whereas a human will approve you manually. You connect to people, groups and forums in the same way, except groups and forums will automatically accept your introduction request, whereas a human will approve you manually.
@ -26,21 +28,18 @@ Connect to other Friendica users
Visit their profile. Visit their profile.
Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile). Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile).
Click that 'Connect' button. Click that 'Connect' button and it will take you to a 'Connect' form.
It will take you to a 'Connect' form.
The form is going to ask you for your Identity Address. The form is going to ask you for your Identity Address.
This is necessary so that this person's website can find yours. This is necessary so that this person's website can find yours.
What do you put in the box? If your Friendica site is called "demo.friendica.com" and your username/nickname on that site is "bob", you would enter "bob@demo.friendica.com" in this form.
If your Friendica site is called "demo.friendica.com" and your username/nickname on that site is "bob", you would put in "bob@demo.friendica.com".
Notice this looks just like an email address. Notice this looks just like an email address.
It was meant to be that way. It's meant to be that way.
It's easy for people to remember. It's easy for people to remember.
You *could* also put in the URL of your "home" page, such as "http://demo.friendica.com/profile/bob", but the email-style address is certainly easier. You *could* also put in the URL of your "home" page, such as "http://demo.friendica.com/profile/bob" instead of the email-style address.
When you've submitted the connection page, it will take you back to your own site where you must then login (if necessary) and verify the connection request on *your* site. When you've submitted the connection page, it will take you back to your own site where you must then login (if necessary) and verify the connection request on *your* site.
Once you've done this, the two websites can communicate with each other to complete the process (after your new friend has approved the request). Once you've done this, the two websites can communicate with each other to complete the process (after your new friend has approved the request).
@ -51,31 +50,40 @@ This will take you through a similar process.
Connect to users of alternate networks Connect to users of alternate networks
--- ---
###GNU Social, Twitter, Diaspora ###Across the Federation and Fedivese
You can also use your Identity Address or other people's Identity Addresses to become friends across networks. You can also use your Identity Address or other people's Identity Addresses to become friends across the so-called Federation/Fedivese of open source social media.
The list of possible networks is growing all the time. Currently, Friendica supports connections with people on diaspora*, Red, Hubzilla, GNU Social, StatusNet, Mastodon, Pleroma, socialhome, and ganggo platforms.
If you know (for instance) "bob" on gnusocial.de (a GNU Social site) you could put bob@gnusocial.de into your Contact page and become friends across networks.
(Or you can put in the URL to Bob's gnusocial.de page if you wish).
You can do the same for Twitter accounts and Diaspora accounts. If you know (for instance) "alice" on gnusocial.net (a GNU Social site) you could put alice@gnusocial.net into your Contact page and become friends across networks.
Likwise you can put in the URL to Alice's gnusocial.net page, if you wish.
Note: Some versions of GNU Social software may require the full URL to your profile and may not work with the identity address.
In fact, you can "follow" almost anybody or any website that produces a syndication feed (RSS/Atom,etc.). People on these networks can also initiate contact with you, if they know your contact details.
If we can find an information stream and a name to attach to the contact, we'll try to connect with them.
###Other social media
If you server provides this functionality, you can also connect with people one
Twitter or important feeds from Tumblr, Wordpress, and many more.
To connect, enter their contact details in the "connect" box on your "Contacts" page.
###Email ###Email
If you have supplied your mailbox connection information on your Settings page, you can enter the email address of anybody that has sent you a message recently and have their email messages show up in your social stream. If you have supplied your mailbox connection information on your Settings page, you can enter the email address of anybody that has sent you a message recently and have their email messages show up in your social stream.
You can also reply to them from within Friendica. You can also reply to them from within Friendica.
People can also become friends with you from other networks. Create an email contact with for example Alice on Gmail, enter her email in following format "mailto:alice@gmail.no".
If a friend of yours has an GNU Social account, they can become friends with you by putting your Friendica Identity Address into their GNU Social subscription dialog box. In order to avoid abuse or spam, you must have an email from Alice with the correct email address in your email inbox.
A similar mechanism is available for Diaspora members, by putting your identity address into their search bar.
Note: Some versions of GNU Social software may require the full URL to your profile and may not work with the identity address. Subscribing to mailing lists is done in the same way, but without the use of the "mailto:" prefix.
To subscribe to a mailing list, enter the email in following example format "mailling-list@list-server.net".
###Syndication feeds
You can "follow" almost anybody or any website that produces a syndication feed (RSS/Atom,etc.).
If we can find an information stream and a name to attach to the contact, we'll try to connect with them.
Notification Notification
--- ---
When somebody requests friendship you will receive a notification. When somebody requests friendship you will receive a notification.
You will need to approve this before the friendship is complete. You will usually need to approve this before the friendship is complete.
Approval Approval
--- ---
@ -84,16 +92,16 @@ Friendica does not allow this by default, as it would open a gateway for spam.
Unilateral or bilateral friendships Unilateral or bilateral friendships
--- ---
When you receive a friendship notification from another Friendica member, you will have the option of allowing them as a "fan" or as a "friend". When you receive a friendship notification from another Friendica member, you will have the option of allowing them as a "Follower" or as a "Friend".
If they are a fan, they can see what you have to say, including private communications that you send to them, but not vice versa. If they are a follower, they can see what you have to say, including private communications that you send to them, but not vice versa.
As a friend, you can both communicate with each other. As a friend, you can both communicate with each other.
Diaspora uses a different terminology, and you are given the option of allowing them to "share with you", or being full friends. diaspora* uses a different terminology, and you are given the option of allowing them to "share with you", or being full friends.
Ignoring, blocking and deleting contacts Ignoring, blocking and deleting contacts
--- ---
Once you have become friends, if you find the person constantly sends you spam or worthless information, you can "Ignore" them - without breaking off the friendship or even alerting them to the fact that you aren't interested in anything they are saying. Once you have become friends, if you find the person constantly sends you spam or worthless information, you can "Ignore" them - without breaking off the friendship or even alerting them to the fact that you aren't interested in anything they are saying.
In many ways they are like a "fan" - but they don't know this. In many ways they are like a "follower" - but they don't know this.
They think they are a friend. They think they are a friend.
You can also "block" a person. You can also "block" a person.

View file

@ -25,8 +25,9 @@ Example: To set the automatic database cleanup process add this line to your .ht
* **allowed_link_protocols** (Array) - Allowed protocols in links URLs, add at your own risk. http is always allowed. * **allowed_link_protocols** (Array) - Allowed protocols in links URLs, add at your own risk. http is always allowed.
* **always_show_preview** (Boolean) - Only show small preview picures. Default value is false. * **always_show_preview** (Boolean) - Only show small preview picures. Default value is false.
* **block_local_dir** (Boolean) - Blocks the access to the directory of the local users. * **archival_days** (Integer) - Number of days that we try to deliver content before we archive a contact. Defaults to 32.
* **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7. * **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7.
* **block_local_dir** (Boolean) - Blocks the access to the directory of the local users.
* **config_adapter** (jit|preload) - Allow to switch the configuration adapter to improve performances at the cost of memory consumption. Default value is "jit" * **config_adapter** (jit|preload) - Allow to switch the configuration adapter to improve performances at the cost of memory consumption. Default value is "jit"
* **curl_range_bytes** - Maximum number of bytes that should be fetched. Default is 0, which mean "no limit". * **curl_range_bytes** - Maximum number of bytes that should be fetched. Default is 0, which mean "no limit".
* **db_log** - Name of a logfile to log slow database queries * **db_log** - Name of a logfile to log slow database queries

View file

@ -223,7 +223,7 @@ function api_login(App $a)
$record = $addon_auth['user_record']; $record = $addon_auth['user_record'];
} else { } else {
$user_id = User::authenticate(trim($user), trim($password)); $user_id = User::authenticate(trim($user), trim($password));
if ($user_id) { if ($user_id !== false) {
$record = dba::selectFirst('user', [], ['uid' => $user_id]); $record = dba::selectFirst('user', [], ['uid' => $user_id]);
} }
} }
@ -267,7 +267,7 @@ function api_check_method($method)
* @brief Main API entry point * @brief Main API entry point
* *
* @param object $a App * @param object $a App
* @return string API call result * @return string|array API call result
*/ */
function api_call(App $a) function api_call(App $a)
{ {
@ -387,9 +387,7 @@ function api_call(App $a)
break; break;
case "json": case "json":
header("Content-Type: application/json"); header("Content-Type: application/json");
foreach ($return as $rr) { $json = json_encode(end($return));
$json = json_encode($rr);
}
if (x($_GET, 'callback')) { if (x($_GET, 'callback')) {
$json = $_GET['callback'] . "(" . $json . ")"; $json = $_GET['callback'] . "(" . $json . ")";
} }
@ -421,7 +419,7 @@ function api_call(App $a)
* *
* @param string $type Return type (xml, json, rss, as) * @param string $type Return type (xml, json, rss, as)
* @param object $e HTTPException Error object * @param object $e HTTPException Error object
* @return string error message formatted as $type * @return string|array error message formatted as $type
*/ */
function api_error($type, $e) function api_error($type, $e)
{ {
@ -531,7 +529,7 @@ function api_get_user(App $a, $contact_id = null)
// Searching for contact id with uid = 0 // Searching for contact id with uid = 0
if (!is_null($contact_id) && (intval($contact_id) != 0)) { if (!is_null($contact_id) && (intval($contact_id) != 0)) {
$user = dbesc(api_unique_id_to_nurl($contact_id)); $user = dbesc(api_unique_id_to_nurl(intval($contact_id)));
if ($user == "") { if ($user == "") {
throw new BadRequestException("User not found."); throw new BadRequestException("User not found.");
@ -577,16 +575,14 @@ function api_get_user(App $a, $contact_id = null)
$argid = count($called_api); $argid = count($called_api);
list($user, $null) = explode(".", $a->argv[$argid]); list($user, $null) = explode(".", $a->argv[$argid]);
if (is_numeric($user)) { if (is_numeric($user)) {
$user = dbesc(api_unique_id_to_nurl($user)); $user = dbesc(api_unique_id_to_nurl(intval($user)));
if ($user == "") { if ($user != "") {
return false; $url = $user;
} $extra_query = "AND `contact`.`nurl` = '%s' ";
if (api_user() !== false) {
$url = $user; $extra_query .= "AND `contact`.`uid`=" . intval(api_user());
$extra_query = "AND `contact`.`nurl` = '%s' "; }
if (api_user() !== false) {
$extra_query .= "AND `contact`.`uid`=" . intval(api_user());
} }
} else { } else {
$user = dbesc($user); $user = dbesc($user);
@ -620,7 +616,9 @@ function api_get_user(App $a, $contact_id = null)
); );
// Selecting the id by priority, friendica first // Selecting the id by priority, friendica first
api_best_nickname($uinfo); if (is_array($uinfo)) {
api_best_nickname($uinfo);
}
// if the contact wasn't found, fetch it from the contacts with uid = 0 // if the contact wasn't found, fetch it from the contacts with uid = 0
if (!DBM::is_result($uinfo)) { if (!DBM::is_result($uinfo)) {
@ -981,7 +979,7 @@ function api_create_xml($data, $root_element)
* @param string $type Return type (atom, rss, xml, json) * @param string $type Return type (atom, rss, xml, json)
* @param array $data JSON style array * @param array $data JSON style array
* *
* @return (string|object|array) XML data or JSON data * @return (string|array) XML data or JSON data
*/ */
function api_format_data($root_element, $type, $data) function api_format_data($root_element, $type, $data)
{ {
@ -992,6 +990,7 @@ function api_format_data($root_element, $type, $data)
$ret = api_create_xml($data, $root_element); $ret = api_create_xml($data, $root_element);
break; break;
case "json": case "json":
default:
$ret = $data; $ret = $data;
break; break;
} }
@ -1429,7 +1428,7 @@ function api_status_show($type)
$status_info["entities"] = $converted["entities"]; $status_info["entities"] = $converted["entities"];
} }
if (($lastwall['item_network'] != "") && ($status["source"] == 'web')) { if (($lastwall['item_network'] != "") && ($status_info["source"] == 'web')) {
$status_info["source"] = ContactSelector::networkToName($lastwall['item_network'], $user_info['url']); $status_info["source"] = ContactSelector::networkToName($lastwall['item_network'], $user_info['url']);
} elseif (($lastwall['item_network'] != "") && (ContactSelector::networkToName($lastwall['item_network'], $user_info['url']) != $status_info["source"])) { } elseif (($lastwall['item_network'] != "") && (ContactSelector::networkToName($lastwall['item_network'], $user_info['url']) != $status_info["source"])) {
$status_info["source"] = trim($status_info["source"].' ('.ContactSelector::networkToName($lastwall['item_network'], $user_info['url']).')'); $status_info["source"] = trim($status_info["source"].' ('.ContactSelector::networkToName($lastwall['item_network'], $user_info['url']).')');
@ -1438,15 +1437,15 @@ function api_status_show($type)
// "uid" and "self" are only needed for some internal stuff, so remove it from here // "uid" and "self" are only needed for some internal stuff, so remove it from here
unset($status_info["user"]["uid"]); unset($status_info["user"]["uid"]);
unset($status_info["user"]["self"]); unset($status_info["user"]["self"]);
logger('status_info: '.print_r($status_info, true), LOGGER_DEBUG);
if ($type == "raw") {
return $status_info;
}
return api_format_data("statuses", $type, ['status' => $status_info]);
} }
logger('status_info: '.print_r($status_info, true), LOGGER_DEBUG);
if ($type == "raw") {
return $status_info;
}
return api_format_data("statuses", $type, ['status' => $status_info]);
} }
/** /**
@ -1630,6 +1629,13 @@ api_register_func('api/users/lookup', 'api_users_lookup', true);
*/ */
function api_search($type) function api_search($type)
{ {
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$data = []; $data = [];
$sql_extra = ''; $sql_extra = '';
@ -1668,7 +1674,7 @@ function api_search($type)
$since_id $since_id
); );
$data['status'] = api_format_items(dba::inArray($r), api_get_user(get_app())); $data['status'] = api_format_items(dba::inArray($r), $user_info);
return api_format_data("statuses", $type, $data); return api_format_data("statuses", $type, $data);
} }
@ -1690,8 +1696,9 @@ api_register_func('api/search', 'api_search', true);
function api_statuses_home_timeline($type) function api_statuses_home_timeline($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
@ -1701,7 +1708,6 @@ function api_statuses_home_timeline($type)
unset($_REQUEST["screen_name"]); unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]); unset($_GET["screen_name"]);
$user_info = api_get_user($a);
// get last network messages // get last network messages
// params // params
@ -1792,12 +1798,12 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline',
function api_statuses_public_timeline($type) function api_statuses_public_timeline($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
$user_info = api_get_user($a);
// get last network messages // get last network messages
// params // params
@ -1901,13 +1907,12 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline'
function api_statuses_networkpublic_timeline($type) function api_statuses_networkpublic_timeline($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
$user_info = api_get_user($a);
$since_id = x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0; $since_id = x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0;
$max_id = x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0; $max_id = x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0;
@ -1971,13 +1976,12 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu
function api_statuses_show($type) function api_statuses_show($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
$user_info = api_get_user($a);
// params // params
$id = intval($a->argv[3]); $id = intval($a->argv[3]);
@ -2045,13 +2049,12 @@ api_register_func('api/statuses/show', 'api_statuses_show', true);
function api_conversation_show($type) function api_conversation_show($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
$user_info = api_get_user($a);
// params // params
$id = intval($a->argv[3]); $id = intval($a->argv[3]);
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20); $count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
@ -2258,8 +2261,9 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH
function api_statuses_mentions($type) function api_statuses_mentions($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
@ -2269,10 +2273,8 @@ function api_statuses_mentions($type)
unset($_REQUEST["screen_name"]); unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]); unset($_GET["screen_name"]);
$user_info = api_get_user($a);
// get last network messages // get last network messages
// params // params
$since_id = defaults($_REQUEST, 'since_id', 0); $since_id = defaults($_REQUEST, 'since_id', 0);
$max_id = defaults($_REQUEST, 'max_id' , 0); $max_id = defaults($_REQUEST, 'max_id' , 0);
@ -2350,13 +2352,12 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
function api_statuses_user_timeline($type) function api_statuses_user_timeline($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
$user_info = api_get_user($a);
logger( logger(
"api_statuses_user_timeline: api_user: ". api_user() . "api_statuses_user_timeline: api_user: ". api_user() .
"\nuser_info: ".print_r($user_info, true) . "\nuser_info: ".print_r($user_info, true) .
@ -2520,15 +2521,14 @@ function api_favorites($type)
global $called_api; global $called_api;
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
$called_api = []; $called_api = [];
$user_info = api_get_user($a);
// in friendica starred item are private // in friendica starred item are private
// return favorites only for self // return favorites only for self
logger('api_favorites: self:' . $user_info['self']); logger('api_favorites: self:' . $user_info['self']);
@ -3343,7 +3343,8 @@ function api_lists_statuses($type)
{ {
$a = get_app(); $a = get_app();
if (api_user() === false) { $user_info = api_get_user($a);
if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
@ -3353,7 +3354,6 @@ function api_lists_statuses($type)
unset($_REQUEST["screen_name"]); unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]); unset($_GET["screen_name"]);
$user_info = api_get_user($a);
if (empty($_REQUEST['list_id'])) { if (empty($_REQUEST['list_id'])) {
throw new BadRequestException('list_id not specified'); throw new BadRequestException('list_id not specified');
} }
@ -3817,7 +3817,7 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP
* @brief delete a direct_message from mail table through api * @brief delete a direct_message from mail table through api
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message * @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message
*/ */
function api_direct_messages_destroy($type) function api_direct_messages_destroy($type)
@ -3903,8 +3903,9 @@ api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy',
function api_direct_messages_box($type, $box, $verbose) function api_direct_messages_box($type, $box, $verbose)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
@ -3928,7 +3929,6 @@ function api_direct_messages_box($type, $box, $verbose)
unset($_REQUEST["screen_name"]); unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]); unset($_GET["screen_name"]);
$user_info = api_get_user($a);
$profile_url = $user_info["url"]; $profile_url = $user_info["url"];
// pagination // pagination
@ -3979,7 +3979,9 @@ function api_direct_messages_box($type, $box, $verbose)
$sender = $user_info; $sender = $user_info;
} }
$ret[] = api_format_messages($item, $recipient, $sender); if (isset($recipient) && isset($sender)) {
$ret[] = api_format_messages($item, $recipient, $sender);
}
} }
@ -4097,7 +4099,7 @@ api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
* @brief delete a complete photoalbum with all containing photos from database through api * @brief delete a complete photoalbum with all containing photos from database through api
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_fr_photoalbum_delete($type) function api_fr_photoalbum_delete($type)
{ {
@ -4152,7 +4154,7 @@ function api_fr_photoalbum_delete($type)
* @brief update the name of the album for all photos of an album * @brief update the name of the album for all photos of an album
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_fr_photoalbum_update($type) function api_fr_photoalbum_update($type)
{ {
@ -4201,7 +4203,7 @@ function api_fr_photoalbum_update($type)
* @brief list all photos of the authenticated user * @brief list all photos of the authenticated user
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_fr_photos_list($type) function api_fr_photos_list($type)
{ {
@ -4247,7 +4249,7 @@ function api_fr_photos_list($type)
* @brief upload a new photo or change an existing photo * @brief upload a new photo or change an existing photo
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_fr_photo_create_update($type) function api_fr_photo_create_update($type)
{ {
@ -4395,7 +4397,7 @@ function api_fr_photo_create_update($type)
* @brief delete a single photo from the database through api * @brief delete a single photo from the database through api
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_fr_photo_delete($type) function api_fr_photo_delete($type)
{ {
@ -4478,7 +4480,7 @@ function api_fr_photo_detail($type)
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* *
* @return string * @return string|array
* @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image * @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image
*/ */
function api_account_update_profile_image($type) function api_account_update_profile_image($type)
@ -4530,6 +4532,8 @@ function api_account_update_profile_image($type)
$fileext = "jpg"; $fileext = "jpg";
} elseif ($filetype == "image/png") { } elseif ($filetype == "image/png") {
$fileext = "png"; $fileext = "png";
} else {
throw new InternalServerErrorException('Unsupported filetype');
} }
// change specified profile or all profiles to the new resource-id // change specified profile or all profiles to the new resource-id
if ($is_default_profile) { if ($is_default_profile) {
@ -4810,7 +4814,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
logger("photo upload: new profile image upload ended", LOGGER_DEBUG); logger("photo upload: new profile image upload ended", LOGGER_DEBUG);
} }
if ($r) { if (isset($r) && $r) {
// create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo // create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo
if ($photo_id == null && $mediatype == "photo") { if ($photo_id == null && $mediatype == "photo") {
post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility); post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility);
@ -4886,6 +4890,13 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
*/ */
function prepare_photo_data($type, $scale, $photo_id) function prepare_photo_data($type, $scale, $photo_id)
{ {
$a = get_app();
$user_info = api_get_user($a);
if ($user_info === false) {
throw new ForbiddenException();
}
$scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale))); $scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale)));
$data_sql = ($scale === false ? "" : "data, "); $data_sql = ($scale === false ? "" : "data, ");
@ -4966,7 +4977,7 @@ function prepare_photo_data($type, $scale, $photo_id)
); );
// prepare output of comments // prepare output of comments
$commentData = api_format_items($r, api_get_user(get_app()), false, $type); $commentData = api_format_items($r, $user_info, false, $type);
$comments = []; $comments = [];
if ($type == "xml") { if ($type == "xml") {
$k = 0; $k = 0;
@ -5341,7 +5352,7 @@ function api_clean_attachments($body)
{ {
$data = BBCode::getAttachmentData($body); $data = BBCode::getAttachmentData($body);
if (!$data) { if (empty($data)) {
return $body; return $body;
} }
$body = ""; $body = "";
@ -5467,6 +5478,7 @@ function api_friendica_group_show($type)
} }
// loop through all groups and retrieve all members for adding data in the user array // loop through all groups and retrieve all members for adding data in the user array
$grps = [];
foreach ($r as $rr) { foreach ($r as $rr) {
$members = Contact::getByGroupId($rr['id']); $members = Contact::getByGroupId($rr['id']);
$users = []; $users = [];
@ -5665,7 +5677,7 @@ function group_create($name, $uid, $users = [])
} }
// return success message incl. missing users in array // return success message incl. missing users in array
$status = ($erroraddinguser ? "missing user" : ($reactivate_group ? "reactivated" : "ok")); $status = ($erroraddinguser ? "missing user" : ((isset($reactivate_group) && $reactivate_group) ? "reactivated" : "ok"));
return ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers]; return ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers];
} }
@ -5773,7 +5785,7 @@ function api_friendica_group_update($type)
foreach ($users as $user) { foreach ($users as $user) {
$found = ($user['cid'] == $cid ? true : false); $found = ($user['cid'] == $cid ? true : false);
} }
if (!$found) { if (!isset($found) || !$found) {
Group::removeMemberByName($uid, $name, $cid); Group::removeMemberByName($uid, $name, $cid);
} }
} }
@ -5850,8 +5862,6 @@ function api_lists_update($type)
return api_format_data("lists", $type, ['lists' => $list]); return api_format_data("lists", $type, ['lists' => $list]);
} }
return api_format_data("group_update", $type, ['result' => $success]);
} }
api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST); api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST);
@ -5904,7 +5914,7 @@ api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activit
* @brief Returns notifications * @brief Returns notifications
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_friendica_notification($type) function api_friendica_notification($type)
{ {
@ -5938,13 +5948,14 @@ function api_friendica_notification($type)
* @brief Set notification as seen and returns associated item (if possible) * @brief Set notification as seen and returns associated item (if possible)
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_friendica_notification_seen($type) function api_friendica_notification_seen($type)
{ {
$a = get_app(); $a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) { if (api_user() === false || $user_info === false) {
throw new ForbiddenException(); throw new ForbiddenException();
} }
if ($a->argc!==4) { if ($a->argc!==4) {
@ -5969,7 +5980,6 @@ function api_friendica_notification_seen($type)
); );
if ($r!==false) { if ($r!==false) {
// we found the item, return it to the user // we found the item, return it to the user
$user_info = api_get_user($a);
$ret = api_format_items($r, $user_info, false, $type); $ret = api_format_items($r, $user_info, false, $type);
$data = ['status' => $ret]; $data = ['status' => $ret];
return api_format_data("status", $type, $data); return api_format_data("status", $type, $data);
@ -5987,7 +5997,7 @@ api_register_func('api/friendica/notification', 'api_friendica_notification', tr
* @brief update a direct_message to seen state * @brief update a direct_message to seen state
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string (success result=ok, error result=error with error message) * @return string|array (success result=ok, error result=error with error message)
*/ */
function api_friendica_direct_messages_setseen($type) function api_friendica_direct_messages_setseen($type)
{ {
@ -6045,7 +6055,7 @@ api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @param string $box * @param string $box
* @return string (success: success=true if found and search_result contains found messages, * @return string|array (success: success=true if found and search_result contains found messages,
* success=false if nothing was found, search_result='nothing found', * success=false if nothing was found, search_result='nothing found',
* error: result=error with error message) * error: result=error with error message)
*/ */
@ -6093,7 +6103,9 @@ function api_friendica_direct_messages_search($type, $box = "")
$sender = $user_info; $sender = $user_info;
} }
$ret[] = api_format_messages($item, $recipient, $sender); if (isset($recipient) && isset($sender)) {
$ret[] = api_format_messages($item, $recipient, $sender);
}
} }
$success = ['success' => true, 'search_results' => $ret]; $success = ['success' => true, 'search_results' => $ret];
} }
@ -6108,7 +6120,7 @@ api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_
* @brief return data of all the profiles a user has to the client * @brief return data of all the profiles a user has to the client
* *
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string * @return string|array
*/ */
function api_friendica_profile_show($type) function api_friendica_profile_show($type)
{ {
@ -6145,19 +6157,20 @@ function api_friendica_profile_show($type)
} }
// loop through all returned profiles and retrieve data and users // loop through all returned profiles and retrieve data and users
$k = 0; $k = 0;
$profiles = [];
foreach ($r as $rr) { foreach ($r as $rr) {
$profile = api_format_items_profiles($rr); $profile = api_format_items_profiles($rr);
// select all users from contact table, loop and prepare standard return for user data // select all users from contact table, loop and prepare standard return for user data
$users = []; $users = [];
$r = q( $nurls = q(
"SELECT `id`, `nurl` FROM `contact` WHERE `uid`= %d AND `profile-id` = %d", "SELECT `id`, `nurl` FROM `contact` WHERE `uid`= %d AND `profile-id` = %d",
intval(api_user()), intval(api_user()),
intval($rr['profile_id']) intval($rr['profile_id'])
); );
foreach ($r as $rr) { foreach ($nurls as $nurl) {
$user = api_get_user($a, $rr['nurl']); $user = api_get_user($a, $nurl['nurl']);
($type == "xml") ? $users[$k++ . ":user"] = $user : $users[] = $user; ($type == "xml") ? $users[$k++ . ":user"] = $user : $users[] = $user;
} }
$profile['users'] = $users; $profile['users'] = $users;

View file

@ -668,33 +668,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
$profile_name = $item['author-link']; $profile_name = $item['author-link'];
} }
$tags = []; $tags = \Friendica\Model\Term::populateTagsFromItem($item);
$hashtags = [];
$mentions = [];
$searchpath = System::baseUrl()."/search?tag=";
$taglist = dba::select('term', ['type', 'term', 'url'],
["`otype` = ? AND `oid` = ? AND `type` IN (?, ?)", TERM_OBJ_POST, $item['id'], TERM_HASHTAG, TERM_MENTION],
['order' => ['tid']]);
while ($tag = dba::fetch($taglist)) {
if ($tag["url"] == "") {
$tag["url"] = $searchpath . strtolower($tag["term"]);
}
$tag["url"] = best_link_url($item, $sp, $tag["url"]);
if ($tag["type"] == TERM_HASHTAG) {
$hashtags[] = "#<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "#";
} elseif ($tag["type"] == TERM_MENTION) {
$mentions[] = "@<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "@";
}
$tags[] = $prefix."<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
}
dba::close($taglist);
$sp = false; $sp = false;
$profile_link = best_link_url($item, $sp); $profile_link = best_link_url($item, $sp);
@ -764,9 +738,9 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
} }
$body_e = $body; $body_e = $body;
$tags_e = $tags; $tags_e = $tags['tags'];
$hashtags_e = $hashtags; $hashtags_e = $tags['hashtags'];
$mentions_e = $mentions; $mentions_e = $tags['mentions'];
$location_e = $location; $location_e = $location;
$owner_name_e = $owner_name; $owner_name_e = $owner_name;

View file

@ -52,8 +52,9 @@ class dba {
} }
if ($install) { if ($install) {
if (strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) { // server has to be a non-empty string that is not 'localhost' and not an IP
if (! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) { if (strlen($server) && ($server !== 'localhost') && filter_var($server, FILTER_VALIDATE_IP) === false) {
if (! dns_get_record($server, DNS_A + DNS_CNAME)) {
self::$error = L10n::t('Cannot locate DNS info for database server \'%s\'', $server); self::$error = L10n::t('Cannot locate DNS info for database server \'%s\'', $server);
return false; return false;
} }

View file

@ -357,7 +357,7 @@ function notification($params)
if ($params['type'] == NOTIFY_SYSTEM) { if ($params['type'] == NOTIFY_SYSTEM) {
switch($params['event']) { switch($params['event']) {
case "SYSTEM_REGISTER_REQUEST": case "SYSTEM_REGISTER_REQUEST":
$subject = L10n::t('[Friendica System:Notify] registration request'); $subject = L10n::t('[Friendica System Notify]') . ' ' . L10n::t('registration request');
$preamble = L10n::t('You\'ve received a registration request from \'%1$s\' at %2$s', $params['source_name'], $sitename); $preamble = L10n::t('You\'ve received a registration request from \'%1$s\' at %2$s', $params['source_name'], $sitename);
$epreamble = L10n::t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.', $epreamble = L10n::t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.',

View file

@ -405,12 +405,21 @@ function get_form_security_token($typename = '')
function check_form_security_token($typename = '', $formname = 'form_security_token') function check_form_security_token($typename = '', $formname = 'form_security_token')
{ {
if (!x($_REQUEST, $formname)) { $hash = null;
return false;
if (!empty($_REQUEST[$formname])) {
/// @TODO Careful, not secured!
$hash = $_REQUEST[$formname];
} }
/// @TODO Careful, not secured! if (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) {
$hash = $_REQUEST[$formname]; /// @TODO Careful, not secured!
$hash = $_SERVER['HTTP_X_CSRF_TOKEN'];
}
if (empty($hash)) {
return false;
}
$max_livetime = 10800; // 3 hours $max_livetime = 10800; // 3 hours

View file

@ -1234,12 +1234,6 @@ function prepare_body(array &$item, $attach = false, $is_preview = false)
$a = get_app(); $a = get_app();
Addon::callHooks('prepare_body_init', $item); Addon::callHooks('prepare_body_init', $item);
$searchpath = System::baseUrl() . "/search?tag=";
$tags = [];
$hashtags = [];
$mentions = [];
// In order to provide theme developers more possibilities, event items // In order to provide theme developers more possibilities, event items
// are treated differently. // are treated differently.
if ($item['object-type'] === ACTIVITY_OBJ_EVENT && isset($item['event-id'])) { if ($item['object-type'] === ACTIVITY_OBJ_EVENT && isset($item['event-id'])) {
@ -1247,37 +1241,11 @@ function prepare_body(array &$item, $attach = false, $is_preview = false)
return $ev; return $ev;
} }
$taglist = dba::p("SELECT `type`, `term`, `url` FROM `term` WHERE `otype` = ? AND `oid` = ? AND `type` IN (?, ?) ORDER BY `tid`", $tags = \Friendica\Model\Term::populateTagsFromItem($item);
intval(TERM_OBJ_POST), intval($item['id']), intval(TERM_HASHTAG), intval(TERM_MENTION));
while ($tag = dba::fetch($taglist)) { $item['tags'] = $tags['tags'];
if ($tag["url"] == "") { $item['hashtags'] = $tags['hashtags'];
$tag["url"] = $searchpath . strtolower($tag["term"]); $item['mentions'] = $tags['mentions'];
}
$orig_tag = $tag["url"];
$tag["url"] = best_link_url($item, $sp, $tag["url"]);
if ($tag["type"] == TERM_HASHTAG) {
if ($orig_tag != $tag["url"]) {
$item['body'] = str_replace($orig_tag, $tag["url"], $item['body']);
}
$hashtags[] = "#<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "#";
} elseif ($tag["type"] == TERM_MENTION) {
$mentions[] = "@<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "@";
}
$tags[] = $prefix . "<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
}
dba::close($taglist);
$item['tags'] = $tags;
$item['hashtags'] = $hashtags;
$item['mentions'] = $mentions;
// Compile eventual content filter reasons // Compile eventual content filter reasons
$filter_reasons = []; $filter_reasons = [];

View file

@ -228,8 +228,36 @@ if (strlen($a->module)) {
*/ */
// Compatibility with the Android Diaspora client // Compatibility with the Android Diaspora client
if ($a->module == "stream") { if ($a->module == 'stream') {
$a->module = "network"; goaway('network?f=&order=post');
}
if ($a->module == 'conversations') {
goaway('message');
}
if ($a->module == 'commented') {
goaway('network?f=&order=comment');
}
if ($a->module == 'liked') {
goaway('network?f=&order=comment');
}
if ($a->module == 'activity') {
goaway('network/?f=&conv=1');
}
if (($a->module == 'status_messages') && ($a->cmd == 'status_messages/new')) {
goaway('bookmarklet');
}
if (($a->module == 'user') && ($a->cmd == 'user/edit')) {
goaway('settings');
}
if (($a->module == 'tag_followings') && ($a->cmd == 'tag_followings/manage')) {
goaway('search');
} }
// Compatibility with the Firefox App // Compatibility with the Firefox App

View file

@ -46,8 +46,10 @@ function wk_social_relay()
$server_tags = Config::get('system', 'relay_server_tags'); $server_tags = Config::get('system', 'relay_server_tags');
$tagitems = explode(",", $server_tags); $tagitems = explode(",", $server_tags);
/// @todo Check if it was better to use "strtolower" on the tags
foreach ($tagitems AS $tag) { foreach ($tagitems AS $tag) {
$tags[trim($tag, "# ")] = trim($tag, "# "); $tag = trim($tag, "# ");
$tags[$tag] = $tag;
} }
if (Config::get('system', 'relay_user_tags')) { if (Config::get('system', 'relay_user_tags')) {
@ -62,7 +64,9 @@ function wk_social_relay()
$taglist = []; $taglist = [];
foreach ($tags AS $tag) { foreach ($tags AS $tag) {
$taglist[] = $tag; if (!empty($tag)) {
$taglist[] = $tag;
}
} }
$relay = [ $relay = [

View file

@ -1384,7 +1384,7 @@ function admin_page_site(App $a)
'$allowed_oembed' => ['allowed_oembed', L10n::t("Allowed OEmbed domains"), Config::get('system','allowed_oembed'), L10n::t("Comma separated list of domains which oembed content is allowed to be displayed. Wildcards are accepted.")], '$allowed_oembed' => ['allowed_oembed', L10n::t("Allowed OEmbed domains"), Config::get('system','allowed_oembed'), L10n::t("Comma separated list of domains which oembed content is allowed to be displayed. Wildcards are accepted.")],
'$block_public' => ['block_public', L10n::t("Block public"), Config::get('system','block_public'), L10n::t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")], '$block_public' => ['block_public', L10n::t("Block public"), Config::get('system','block_public'), L10n::t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")],
'$force_publish' => ['publish_all', L10n::t("Force publish"), Config::get('system','publish_all'), L10n::t("Check to force all profiles on this site to be listed in the site directory.")], '$force_publish' => ['publish_all', L10n::t("Force publish"), Config::get('system','publish_all'), L10n::t("Check to force all profiles on this site to be listed in the site directory.")],
'$global_directory' => ['directory', L10n::t("Global directory URL"), Config::get('system','directory'), L10n::t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")], '$global_directory' => ['directory', L10n::t("Global directory URL"), Config::get('system', 'directory', 'https://dir.friendica.social'), L10n::t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")],
'$newuser_private' => ['newuser_private', L10n::t("Private posts by default for new users"), Config::get('system','newuser_private'), L10n::t("Set default post permissions for all new members to the default privacy group rather than public.")], '$newuser_private' => ['newuser_private', L10n::t("Private posts by default for new users"), Config::get('system','newuser_private'), L10n::t("Set default post permissions for all new members to the default privacy group rather than public.")],
'$enotify_no_content' => ['enotify_no_content', L10n::t("Don't include post content in email notifications"), Config::get('system','enotify_no_content'), L10n::t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")], '$enotify_no_content' => ['enotify_no_content', L10n::t("Don't include post content in email notifications"), Config::get('system','enotify_no_content'), L10n::t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")],
'$private_addons' => ['private_addons', L10n::t("Disallow public access to addons listed in the apps menu."), Config::get('config','private_addons'), L10n::t("Checking this box will restrict addons listed in the apps menu to members only.")], '$private_addons' => ['private_addons', L10n::t("Disallow public access to addons listed in the apps menu."), Config::get('config','private_addons'), L10n::t("Checking this box will restrict addons listed in the apps menu to members only.")],
@ -1400,17 +1400,17 @@ function admin_page_site(App $a)
'$ostatus_not_able' => L10n::t("OStatus support can only be enabled if threading is enabled."), '$ostatus_not_able' => L10n::t("OStatus support can only be enabled if threading is enabled."),
'$diaspora_able' => $diaspora_able, '$diaspora_able' => $diaspora_able,
'$diaspora_not_able' => L10n::t("Diaspora support can't be enabled because Friendica was installed into a sub directory."), '$diaspora_not_able' => L10n::t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),
'$diaspora_enabled' => ['diaspora_enabled', L10n::t("Enable Diaspora support"), Config::get('system','diaspora_enabled'), L10n::t("Provide built-in Diaspora network compatibility.")], '$diaspora_enabled' => ['diaspora_enabled', L10n::t("Enable Diaspora support"), Config::get('system', 'diaspora_enabled', $diaspora_able), L10n::t("Provide built-in Diaspora network compatibility.")],
'$dfrn_only' => ['dfrn_only', L10n::t('Only allow Friendica contacts'), Config::get('system','dfrn_only'), L10n::t("All contacts must use Friendica protocols. All other built-in communication protocols disabled.")], '$dfrn_only' => ['dfrn_only', L10n::t('Only allow Friendica contacts'), Config::get('system','dfrn_only'), L10n::t("All contacts must use Friendica protocols. All other built-in communication protocols disabled.")],
'$verifyssl' => ['verifyssl', L10n::t("Verify SSL"), Config::get('system','verifyssl'), L10n::t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect \x28at all\x29 to self-signed SSL sites.")], '$verifyssl' => ['verifyssl', L10n::t("Verify SSL"), Config::get('system','verifyssl'), L10n::t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect \x28at all\x29 to self-signed SSL sites.")],
'$proxyuser' => ['proxyuser', L10n::t("Proxy user"), Config::get('system','proxyuser'), ""], '$proxyuser' => ['proxyuser', L10n::t("Proxy user"), Config::get('system','proxyuser'), ""],
'$proxy' => ['proxy', L10n::t("Proxy URL"), Config::get('system','proxy'), ""], '$proxy' => ['proxy', L10n::t("Proxy URL"), Config::get('system','proxy'), ""],
'$timeout' => ['timeout', L10n::t("Network timeout"), (x(Config::get('system','curl_timeout'))?Config::get('system','curl_timeout'):60), L10n::t("Value is in seconds. Set to 0 for unlimited \x28not recommended\x29.")], '$timeout' => ['timeout', L10n::t("Network timeout"), Config::get('system', 'curl_timeout', 60), L10n::t("Value is in seconds. Set to 0 for unlimited \x28not recommended\x29.")],
'$maxloadavg' => ['maxloadavg', L10n::t("Maximum Load Average"), ((intval(Config::get('system','maxloadavg')) > 0)?Config::get('system','maxloadavg'):50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")], '$maxloadavg' => ['maxloadavg', L10n::t("Maximum Load Average"), Config::get('system', 'maxloadavg', 50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")],
'$maxloadavg_frontend' => ['maxloadavg_frontend', L10n::t("Maximum Load Average \x28Frontend\x29"), ((intval(Config::get('system','maxloadavg_frontend')) > 0)?Config::get('system','maxloadavg_frontend'):50), L10n::t("Maximum system load before the frontend quits service - default 50.")], '$maxloadavg_frontend' => ['maxloadavg_frontend', L10n::t("Maximum Load Average \x28Frontend\x29"), Config::get('system', 'maxloadavg_frontend', 50), L10n::t("Maximum system load before the frontend quits service - default 50.")],
'$min_memory' => ['min_memory', L10n::t("Minimal Memory"), ((intval(Config::get('system','min_memory')) > 0)?Config::get('system','min_memory'):0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 \x28deactivated\x29.")], '$min_memory' => ['min_memory', L10n::t("Minimal Memory"), Config::get('system', 'min_memory', 0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 \x28deactivated\x29.")],
'$optimize_max_tablesize'=> ['optimize_max_tablesize', L10n::t("Maximum table size for optimization"), $optimize_max_tablesize, L10n::t("Maximum table size \x28in MB\x29 for the automatic optimization - default 100 MB. Enter -1 to disable it.")], '$optimize_max_tablesize'=> ['optimize_max_tablesize', L10n::t("Maximum table size for optimization"), $optimize_max_tablesize, L10n::t("Maximum table size \x28in MB\x29 for the automatic optimization - default 100 MB. Enter -1 to disable it.")],
'$optimize_fragmentation'=> ['optimize_fragmentation', L10n::t("Minimum level of fragmentation"), ((intval(Config::get('system','optimize_fragmentation')) > 0)?Config::get('system','optimize_fragmentation'):30), L10n::t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")], '$optimize_fragmentation'=> ['optimize_fragmentation', L10n::t("Minimum level of fragmentation"), Config::get('system', 'optimize_fragmentation', 30), L10n::t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")],
'$poco_completion' => ['poco_completion', L10n::t("Periodical check of global contacts"), Config::get('system','poco_completion'), L10n::t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")], '$poco_completion' => ['poco_completion', L10n::t("Periodical check of global contacts"), Config::get('system','poco_completion'), L10n::t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")],
'$poco_requery_days' => ['poco_requery_days', L10n::t("Days between requery"), Config::get('system','poco_requery_days'), L10n::t("Number of days after which a server is requeried for his contacts.")], '$poco_requery_days' => ['poco_requery_days', L10n::t("Days between requery"), Config::get('system','poco_requery_days'), L10n::t("Number of days after which a server is requeried for his contacts.")],
@ -1440,11 +1440,11 @@ function admin_page_site(App $a)
'$worker_frontend' => ['worker_frontend', L10n::t('Enable frontend worker'), Config::get('system','frontend_worker'), L10n::t('When enabled the Worker process is triggered when backend access is performed \x28e.g. messages being delivered\x29. On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', System::baseUrl())], '$worker_frontend' => ['worker_frontend', L10n::t('Enable frontend worker'), Config::get('system','frontend_worker'), L10n::t('When enabled the Worker process is triggered when backend access is performed \x28e.g. messages being delivered\x29. On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', System::baseUrl())],
'$relay_subscribe' => ['relay_subscribe', L10n::t("Subscribe to relay"), Config::get('system','relay_subscribe'), L10n::t("Enables the receiving of public posts from the relay. They will be included in the search, subscribed tags and on the global community page.")], '$relay_subscribe' => ['relay_subscribe', L10n::t("Subscribe to relay"), Config::get('system','relay_subscribe'), L10n::t("Enables the receiving of public posts from the relay. They will be included in the search, subscribed tags and on the global community page.")],
'$relay_server' => ['relay_server', L10n::t("Relay server"), Config::get('system','relay_server'), L10n::t("Address of the relay server where public posts should be send to. For example https://relay.diasp.org")], '$relay_server' => ['relay_server', L10n::t("Relay server"), Config::get('system', 'relay_server', 'https://relay.diasp.org'), L10n::t("Address of the relay server where public posts should be send to. For example https://relay.diasp.org")],
'$relay_directly' => ['relay_directly', L10n::t("Direct relay transfer"), Config::get('system','relay_directly'), L10n::t("Enables the direct transfer to other servers without using the relay servers")], '$relay_directly' => ['relay_directly', L10n::t("Direct relay transfer"), Config::get('system','relay_directly'), L10n::t("Enables the direct transfer to other servers without using the relay servers")],
'$relay_scope' => ['relay_scope', L10n::t("Relay scope"), Config::get('system','relay_scope'), L10n::t("Can be 'all' or 'tags'. 'all' means that every public post should be received. 'tags' means that only posts with selected tags should be received."), ['' => L10n::t('Disabled'), 'all' => L10n::t('all'), 'tags' => L10n::t('tags')]], '$relay_scope' => ['relay_scope', L10n::t("Relay scope"), Config::get('system','relay_scope'), L10n::t("Can be 'all' or 'tags'. 'all' means that every public post should be received. 'tags' means that only posts with selected tags should be received."), ['' => L10n::t('Disabled'), 'all' => L10n::t('all'), 'tags' => L10n::t('tags')]],
'$relay_server_tags' => ['relay_server_tags', L10n::t("Server tags"), Config::get('system','relay_server_tags'), L10n::t("Comma separated list of tags for the 'tags' subscription.")], '$relay_server_tags' => ['relay_server_tags', L10n::t("Server tags"), Config::get('system','relay_server_tags'), L10n::t("Comma separated list of tags for the 'tags' subscription.")],
'$relay_user_tags' => ['relay_user_tags', L10n::t("Allow user tags"), Config::get('system','relay_user_tags'), L10n::t("If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'.")], '$relay_user_tags' => ['relay_user_tags', L10n::t("Allow user tags"), Config::get('system', 'relay_user_tags', true), L10n::t("If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'.")],
'$form_security_token' => get_form_security_token("admin_site") '$form_security_token' => get_form_security_token("admin_site")
]); ]);
@ -1735,13 +1735,28 @@ function admin_page_users(App $a)
$adminlist = explode(",", str_replace(" ", "", $a->config['admin_email'])); $adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
$_setup_users = function ($e) use ($adminlist) { $_setup_users = function ($e) use ($adminlist) {
$accounts = [ $page_types = [
L10n::t('Normal Account'), PAGE_NORMAL => L10n::t('Normal Account Page'),
L10n::t('Automatic Follower Account'), PAGE_SOAPBOX => L10n::t('Soapbox Page'),
L10n::t('Public Forum Account'), PAGE_COMMUNITY => L10n::t('Public Forum'),
L10n::t('Automatic Friend Account') PAGE_FREELOVE => L10n::t('Automatic Friend Page'),
PAGE_PRVGROUP => L10n::t('Private Forum')
]; ];
$e['page-flags'] = $accounts[$e['page-flags']]; $account_types = [
ACCOUNT_TYPE_PERSON => L10n::t('Personal Page'),
ACCOUNT_TYPE_ORGANISATION => L10n::t('Organisation Page'),
ACCOUNT_TYPE_NEWS => L10n::t('News Page'),
ACCOUNT_TYPE_COMMUNITY => L10n::t('Community Forum')
];
$e['page-flags-raw'] = $e['page-flags'];
$e['page-flags'] = $page_types[$e['page-flags']];
$e['account-type-raw'] = ($e['page_flags_raw']==0) ? $e['account-type'] : -1;
$e['account-type'] = ($e['page_flags_raw']==0) ? $account_types[$e['account-type']] : "";
$e['register_date'] = Temporal::getRelativeDate($e['register_date']); $e['register_date'] = Temporal::getRelativeDate($e['register_date']);
$e['login_date'] = Temporal::getRelativeDate($e['login_date']); $e['login_date'] = Temporal::getRelativeDate($e['login_date']);
$e['lastitem_date'] = Temporal::getRelativeDate($e['lastitem_date']); $e['lastitem_date'] = Temporal::getRelativeDate($e['lastitem_date']);
@ -1778,8 +1793,7 @@ function admin_page_users(App $a)
array_push($users, array_pop($tmp_users)); array_push($users, array_pop($tmp_users));
} }
$th_users = array_map(null, [L10n::t('Name'), L10n::t('Email'), L10n::t('Register date'), L10n::t('Last login'), L10n::t('Last item'), L10n::t('Account')], $valid_orders $th_users = array_map(null, [L10n::t('Name'), L10n::t('Email'), L10n::t('Register date'), L10n::t('Last login'), L10n::t('Last item'), L10n::t('Type')], $valid_orders);
);
$t = get_markup_template('admin/users.tpl'); $t = get_markup_template('admin/users.tpl');
$o = replace_macros($t, [ $o = replace_macros($t, [

View file

@ -223,7 +223,7 @@ function dirfind_content(App $a, $prefix = "") {
$entry = [ $entry = [
'alt_text' => $alt_text, 'alt_text' => $alt_text,
'url' => Profile::zrl($jj->url), 'url' => Profile::magicLink($jj->url),
'itemurl' => $itemurl, 'itemurl' => $itemurl,
'name' => htmlentities($jj->name), 'name' => htmlentities($jj->name),
'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB), 'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB),

View file

@ -86,7 +86,7 @@ function friendica_content(App $a)
$o .= L10n::t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">'.L10n::t('the bugtracker at github').'</a>'; $o .= L10n::t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">'.L10n::t('the bugtracker at github').'</a>';
$o .= '</p>' . PHP_EOL; $o .= '</p>' . PHP_EOL;
$o .= '<p>'; $o .= '<p>';
$o .= L10n::t('Suggestions, praise, donations, etc. - please email "Info" at Friendica - dot com'); $o .= L10n::t('Suggestions, praise, etc. - please email "info" at "friendi - dot - ca');
$o .= '</p>' . PHP_EOL; $o .= '</p>' . PHP_EOL;
$visible_addons = []; $visible_addons = [];
@ -112,7 +112,7 @@ function friendica_content(App $a)
$s .= $p; $s .= $p;
} }
} }
$o .= '<div style="margin-left: 25px; margin-right: 25px;">' . $s . '</div>' . PHP_EOL; $o .= '<div style="margin-left: 25px; margin-right: 25px; margin-bottom: 25px;">' . $s . '</div>' . PHP_EOL;
} else { } else {
$o .= '<p>' . L10n::t('No installed addons/apps') . '</p>' . PHP_EOL; $o .= '<p>' . L10n::t('No installed addons/apps') . '</p>' . PHP_EOL;
} }

View file

@ -771,10 +771,15 @@ function networkThreadedView(App $a, $update, $parent)
FROM `item` $sql_post_table FROM `item` $sql_post_table
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND (NOT `contact`.`blocked` OR `contact`.`pending`) AND (NOT `contact`.`blocked` OR `contact`.`pending`)
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`)
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
AND NOT `item`.`moderated` AND $sql_extra4 AND NOT `item`.`moderated` AND $sql_extra4
$sql_extra3 $sql_extra $sql_range $sql_nets $sql_extra3 $sql_extra $sql_range $sql_nets
ORDER BY `order_date` DESC LIMIT 100", ORDER BY `order_date` DESC LIMIT 100",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
intval(local_user()) intval(local_user())
); );
} else { } else {
@ -783,10 +788,15 @@ function networkThreadedView(App $a, $update, $parent)
STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
AND (NOT `contact`.`blocked` OR `contact`.`pending`) AND (NOT `contact`.`blocked` OR `contact`.`pending`)
STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid` STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`)
WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted` WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated` AND NOT `thread`.`moderated`
$sql_extra2 $sql_extra3 $sql_range $sql_extra $sql_nets $sql_extra2 $sql_extra3 $sql_range $sql_extra $sql_nets
ORDER BY `order_date` DESC $pager_sql", ORDER BY `order_date` DESC $pager_sql",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
intval(local_user()) intval(local_user())
); );
} }
@ -827,9 +837,14 @@ function networkThreadedView(App $a, $update, $parent)
(SELECT SUBSTR(`term`, 2) FROM `search` WHERE `uid` = ? AND `term` LIKE '#%') AND `otype` = ? AND `type` = ? AND `uid` = 0) AS `term` (SELECT SUBSTR(`term`, 2) FROM `search` WHERE `uid` = ? AND `term` LIKE '#%') AND `otype` = ? AND `type` = ? AND `uid` = 0) AS `term`
ON `item`.`id` = `term`.`oid` ON `item`.`id` = `term`.`oid`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`author-id` STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`author-id`
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (?, ?) AND NOT `contact`.`readonly`)
WHERE `item`.`uid` = 0 AND `item`.$ordering < ? AND `item`.$ordering > ? WHERE `item`.`uid` = 0 AND `item`.$ordering < ? AND `item`.$ordering > ?
AND NOT `contact`.`hidden` AND NOT `contact`.`blocked`" . $sql_tag_nets, AND NOT `contact`.`hidden` AND NOT `contact`.`blocked`" . $sql_tag_nets,
local_user(), TERM_OBJ_POST, TERM_HASHTAG, $top_limit, $bottom_limit); local_user(), TERM_OBJ_POST, TERM_HASHTAG,
CONTACT_IS_SHARING, CONTACT_IS_FRIEND,
$top_limit, $bottom_limit);
$data = dba::inArray($items); $data = dba::inArray($items);

View file

@ -7,6 +7,8 @@ use Friendica\Core\L10n;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Model\User; use Friendica\Model\User;
require_once 'include/enotify.php';
function removeme_post(App $a) function removeme_post(App $a)
{ {
if (!local_user()) { if (!local_user()) {
@ -29,6 +31,25 @@ function removeme_post(App $a)
return; return;
} }
// send notification to admins so that they can clean um the backups
// send email to admins
$admin_mail_list = "'" . implode("','", array_map(dbesc, explode(",", str_replace(" ", "", $a->config['admin_email'])))) . "'";
$adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)",
$admin_mail_list
);
foreach ($adminlist as $admin) {
notification([
'type' => SYSTEM_EMAIL,
'subject' => L10n::t('[Friendica System Notify]') . ' ' . L10n::t('User deleted their account'),
'preamble' => L10n::t('On your Friendica node an user deleted their account. Please ensure that their data is removed from the backups.'),
'body' => L10n::t('The user id is %d', local_user()),
'to_email' => $admin['email'],
'uid' => $admin['uid'],
'language' => $admin['language'] ? $admin['language'] : 'en',
'show_in_notification_page' => false
]);
}
if (User::authenticate($a->user, trim($_POST['qxz_password']))) { if (User::authenticate($a->user, trim($_POST['qxz_password']))) {
User::remove($a->user['uid']); User::remove($a->user['uid']);
// NOTREACHED // NOTREACHED

21
mods/home.css Normal file
View file

@ -0,0 +1,21 @@
.homeinfocontainer {
display: grid;
grid-template-columns: 33% 33% 33%;
grid-column-gap: 15px;
padding: 10px;
}
.homeinfobox p {
text-align: justify;
}
#c1 {
grid-column-start: 1;
grid-column-end: 2;
}
#c2 {
grid-column-start: 2;
grid-column-end: 3;
}
#c3 {
grid-column-start: 3;
grid-column-end: 4;
}

23
mods/home.html Normal file
View file

@ -0,0 +1,23 @@
<!-- styling for this page is done in the home.css file //-->
<!-- Some node specifiv welcome message //-->
<p>Welcome to this <a href="https://friendi.ca">Friendica</a> node!</p>
<!-- Some general notes about Friendica, the other networks and difficulty to run //-->
<div class="homeinfocontainer">
<div id="c1" class="homeinfobox">
<h4>What is Friendica?</h4>
<p>Friendica is a decentral social network platform everybody can use to setup their own social networking node. It interacts with many other FLOSS microblogging and social networking platforms as well as some walled gardens.</p>
<p><a href="https://friendi.ca">Learn more at friendi.ca</a><br /><a href="https://dir.friendica.social/servers">Find an open Friendica node to join</a></p>
</div>
<div id="c2" class="homeinfobox">
<h4>What other networks does it interact with?</h4>
<p>Every network that speaks either the DFRN2, OStatus or diaspora* protocol. Currently this list includes: diaspora*, friendica, ganggo, GNU social, Hubzilla, Mastodon, Pleroma, postActivi and Socialhome.</p>
<p><a href="http://fediverse.party/">Learn more at fediverse.party</a></p>
</div>
<div id="c3" class="homeinfobox">
<h4>Is it hard to run Friendica?</h4>
<p>No, not at all! You need a LAMP server, most shared hosting services that offer MySQL, PHP and the ability to run cron jobs will do just fine. If you have your own (virtual) server, for a small Friendica server something like a Raspberry2B is sufficenent from the specs.</p>
<p><a href="https://github.com/friendica/friendica">Get the source</a></p>
</div>
</div>

View file

@ -19,3 +19,13 @@ sample-systemd.service
issue in Github (https://github.com/friendica/friendica/issues). issue in Github (https://github.com/friendica/friendica/issues).
This is for usage of systemd instead of cron to start the worker.php This is for usage of systemd instead of cron to start the worker.php
periodically, the solution is work-in-progress and can surely be improved. periodically, the solution is work-in-progress and can surely be improved.
home.css
home.html
Example files to customize the landing page of your Friendica node.
The home.html file contains the text of the page, the home.css file
the style information. The login box will be added according to the
other system settings.
Both files have to be placed in the base directory of your Friendica
installation to be used for the landing page.

View file

@ -4,6 +4,7 @@ Description=Run Friendica Poller every n minutes
[Timer] [Timer]
OnBootSec=120 OnBootSec=120
OnUnitActiveSec=120 OnUnitActiveSec=120
RemainAfterElapse=False
[Install] [Install]
WantedBy=timers.target WantedBy=timers.target

8
phpunit.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<phpunit bootstrap="boot.php">
<testsuites>
<testsuite>
<directory>tests/</directory>
</testsuite>
</testsuites>
</phpunit>

View file

@ -1062,7 +1062,7 @@ class App
$hostname = substr($hostname, 0, strpos($hostname, ':')); $hostname = substr($hostname, 0, strpos($hostname, ':'));
} }
$sender_email = L10n::t('noreply') . '@' . $hostname; $sender_email = 'noreply@' . $hostname;
} }
return $sender_email; return $sender_email;

View file

@ -1583,7 +1583,7 @@ class BBCode extends BaseObject
$text = preg_replace("(\[u\](.*?)\[\/u\])ism", '<u>$1</u>', $text); $text = preg_replace("(\[u\](.*?)\[\/u\])ism", '<u>$1</u>', $text);
// Check for strike-through text // Check for strike-through text
$text = preg_replace("(\[s\](.*?)\[\/s\])ism", '<strike>$1</strike>', $text); $text = preg_replace("(\[s\](.*?)\[\/s\])ism", '<s>$1</s>', $text);
// Check for over-line text // Check for over-line text
$text = preg_replace("(\[o\](.*?)\[\/o\])ism", '<span class="overline">$1</span>', $text); $text = preg_replace("(\[o\](.*?)\[\/o\])ism", '<span class="overline">$1</span>', $text);

View file

@ -221,6 +221,9 @@ class HTML
self::tagToBBCode($doc, 'b', [], '[b]', '[/b]'); self::tagToBBCode($doc, 'b', [], '[b]', '[/b]');
self::tagToBBCode($doc, 'i', [], '[i]', '[/i]'); self::tagToBBCode($doc, 'i', [], '[i]', '[/i]');
self::tagToBBCode($doc, 'u', [], '[u]', '[/u]'); self::tagToBBCode($doc, 'u', [], '[u]', '[/u]');
self::tagToBBCode($doc, 's', [], '[s]', '[/s]');
self::tagToBBCode($doc, 'del', [], '[s]', '[/s]');
self::tagToBBCode($doc, 'strike', [], '[s]', '[/s]');
self::tagToBBCode($doc, 'big', [], "[size=large]", "[/size]"); self::tagToBBCode($doc, 'big', [], "[size=large]", "[/size]");
self::tagToBBCode($doc, 'small', [], "[size=small]", "[/size]"); self::tagToBBCode($doc, 'small', [], "[size=small]", "[/size]");

View file

@ -50,7 +50,7 @@ class MemcachedCacheDriver extends BaseObject implements ICacheDriver
{ {
// We store with the hostname as key to avoid problems with other applications // We store with the hostname as key to avoid problems with other applications
return $this->memcached->set( return $this->memcached->set(
self::getApp()->get_hostname() . ":" . $key, self::getApp()->get_hostname() . ':' . $key,
$value, $value,
time() + $duration time() + $duration
); );
@ -58,7 +58,9 @@ class MemcachedCacheDriver extends BaseObject implements ICacheDriver
public function delete($key) public function delete($key)
{ {
return $this->memcached->delete($key); $return = $this->memcached->delete(self::getApp()->get_hostname() . ':' . $key);
return $return;
} }
public function clear() public function clear()

View file

@ -32,6 +32,10 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter
return; return;
} }
if (empty($uid)) {
return;
}
$pconfigs = dba::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); $pconfigs = dba::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);
while ($pconfig = dba::fetch($pconfigs)) { while ($pconfig = dba::fetch($pconfigs)) {
self::getApp()->setPConfigValue($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']); self::getApp()->setPConfigValue($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']);
@ -43,6 +47,10 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter
public function get($uid, $cat, $k, $default_value = null, $refresh = false) public function get($uid, $cat, $k, $default_value = null, $refresh = false)
{ {
if (!$this->config_loaded) {
$this->load($uid, $cat);
}
if ($refresh) { if ($refresh) {
$config = dba::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); $config = dba::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
if (DBM::is_result($config)) { if (DBM::is_result($config)) {
@ -59,6 +67,9 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter
public function set($uid, $cat, $k, $value) public function set($uid, $cat, $k, $value)
{ {
if (!$this->config_loaded) {
$this->load($uid, $cat);
}
// We store our setting values as strings. // We store our setting values as strings.
// So we have to do the conversion here so that the compare below works. // So we have to do the conversion here so that the compare below works.
// The exception are array values. // The exception are array values.
@ -83,6 +94,10 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter
public function delete($uid, $cat, $k) public function delete($uid, $cat, $k)
{ {
if (!$this->config_loaded) {
$this->load($uid, $cat);
}
self::getApp()->deletePConfigValue($uid, $cat, $k); self::getApp()->deletePConfigValue($uid, $cat, $k);
$result = dba::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); $result = dba::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]);

View file

@ -21,6 +21,7 @@ class Console extends \Asika\SimpleConsole\Console
'extract' => __NAMESPACE__ . '\Console\Extract', 'extract' => __NAMESPACE__ . '\Console\Extract',
'globalcommunityblock' => __NAMESPACE__ . '\Console\GlobalCommunityBlock', 'globalcommunityblock' => __NAMESPACE__ . '\Console\GlobalCommunityBlock',
'globalcommunitysilence' => __NAMESPACE__ . '\Console\GlobalCommunitySilence', 'globalcommunitysilence' => __NAMESPACE__ . '\Console\GlobalCommunitySilence',
'autoinstall' => __NAMESPACE__ . '\Console\AutomaticInstallation',
'maintenance' => __NAMESPACE__ . '\Console\Maintenance', 'maintenance' => __NAMESPACE__ . '\Console\Maintenance',
'newpassword' => __NAMESPACE__ . '\Console\NewPassword', 'newpassword' => __NAMESPACE__ . '\Console\NewPassword',
'php2po' => __NAMESPACE__ . '\Console\PhpToPo', 'php2po' => __NAMESPACE__ . '\Console\PhpToPo',
@ -42,6 +43,7 @@ Commands:
globalcommunityblock Block remote profile from interacting with this node globalcommunityblock Block remote profile from interacting with this node
globalcommunitysilence Silence remote profile from global community page globalcommunitysilence Silence remote profile from global community page
help Show help about a command, e.g (bin/console help config) help Show help about a command, e.g (bin/console help config)
autoinstall Starts automatic installation of friendica based on values from htconfig.php
maintenance Set maintenance mode for this node maintenance Set maintenance mode for this node
newpassword Set a new password for a given user newpassword Set a new password for a given user
php2po Generate a messages.po file from a strings.php file php2po Generate a messages.po file from a strings.php file

View file

@ -0,0 +1,164 @@
<?php
namespace Friendica\Core\Console;
use Asika\SimpleConsole\Console;
use dba;
use Friendica\App;
require_once 'mod/install.php';
require_once 'include/dba.php';
class AutomaticInstallation extends Console
{
protected function getHelp()
{
return <<<HELP
Installation - Install Friendica automatically
Synopsis
bin/console autoinstall [-h|--help|-?] [-v] [-a]
Description
Installs Friendica with data based on the htconfig.php file
Notes:
Not checking .htaccess/URL-Rewrite during CLI installation.
Options
-h|--help|-? Show help information
-v Show more debug information.
-a All setup checks are required (except .htaccess)
HELP;
}
protected function doExecute()
{
// Initialise the app
$this->out("Initializing setup...\n");
$a = get_app();
$db_host = '';
$db_user = '';
$db_pass = '';
$db_data = '';
require_once 'htconfig.php';
$this->out(" Complete!\n\n");
// Check basic setup
$this->out("Checking basic setup...\n");
$checkResults = [];
$checkResults['basic'] = $this->runBasicChecks($a);
$errorMessage = $this->extractErrors($checkResults['basic']);
if ($errorMessage !== '') {
throw new \RuntimeException($errorMessage);
}
$this->out(" Complete!\n\n");
// Check database connection
$this->out("Checking database...\n");
$checkResults['db'] = array();
$checkResults['db'][] = $this->runDatabaseCheck($db_host, $db_user, $db_pass, $db_data);
$errorMessage = $this->extractErrors($checkResults['db']);
if ($errorMessage !== '') {
throw new \RuntimeException($errorMessage);
}
$this->out(" Complete!\n\n");
// Install database
$this->out("Inserting data into database...\n");
$checkResults['data'] = load_database();
if ($checkResults['data'] !== '') {
throw new \RuntimeException("ERROR: DB Database creation error. Is the DB empty?\n");
}
$this->out(" Complete!\n\n");
// Copy config file
$this->out("Saving config file...\n");
if (!copy('htconfig.php', '.htconfig.php')) {
throw new \RuntimeException("ERROR: Saving config file failed. Please copy .htautoinstall.php to .htconfig.php manually.\n");
}
$this->out(" Complete!\n\n");
$this->out("\nInstallation is finished\n");
return 0;
}
/**
* @param App $app
* @return array
*/
private function runBasicChecks($app)
{
$checks = [];
check_funcs($checks);
check_imagik($checks);
check_htconfig($checks);
check_smarty3($checks);
check_keys($checks);
if (!empty($app->config['php_path'])) {
check_php($app->config['php_path'], $checks);
} else {
throw new \RuntimeException(" ERROR: The php_path is not set in the config. Please check the file .htconfig.php.\n");
}
$this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n");
return $checks;
}
/**
* @param $db_host
* @param $db_user
* @param $db_pass
* @param $db_data
* @return array
*/
private function runDatabaseCheck($db_host, $db_user, $db_pass, $db_data)
{
$result = array(
'title' => 'MySQL Connection',
'required' => true,
'status' => true,
'help' => '',
);
if (!dba::connect($db_host, $db_user, $db_pass, $db_data, true)) {
$result['status'] = false;
$result['help'] = 'Failed, please check your MySQL settings and credentials.';
}
return $result;
}
/**
* @param array $results
* @return string
*/
private function extractErrors($results)
{
$errorMessage = '';
$allChecksRequired = $this->getOption('a') !== null;
foreach ($results as $result) {
if (($allChecksRequired || $result['required'] === true) && $result['status'] === false) {
$errorMessage .= "--------\n";
$errorMessage .= $result['title'] . ': ' . $result['help'] . "\n";
}
}
return $errorMessage;
}
}

View file

@ -27,7 +27,7 @@ class NewPassword extends \Asika\SimpleConsole\Console
$help = <<<HELP $help = <<<HELP
console newpassword - Creates a new password for a given user console newpassword - Creates a new password for a given user
Usage Usage
bin/console newpassword <nickname> <password> [-h|--help|-?] [-v] bin/console newpassword <nickname> [<password>] [-h|--help|-?] [-v]
Description Description
Creates a new password for a user without using the "forgot password" functionality. Creates a new password for a user without using the "forgot password" functionality.
@ -67,13 +67,22 @@ HELP;
} }
$nick = $this->getArgument(0); $nick = $this->getArgument(0);
$password = $this->getArgument(1);
$user = dba::selectFirst('user', ['uid'], ['nickname' => $nick]); $user = dba::selectFirst('user', ['uid'], ['nickname' => $nick]);
if (!DBM::is_result($user)) { if (!DBM::is_result($user)) {
throw new \RuntimeException(L10n::t('User not found')); throw new \RuntimeException(L10n::t('User not found'));
} }
$password = $this->getArgument(1);
if (is_null($password)) {
$this->out(L10n::t('Enter new password: '), false);
$password = \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
}
if (!$password) {
throw new \RuntimeException(L10n::t('Password can\'t be empty'));
}
if (!Config::get('system', 'disable_password_exposed', false) && User::isPasswordExposed($password)) { if (!Config::get('system', 'disable_password_exposed', false) && User::isPasswordExposed($password)) {
throw new \RuntimeException(L10n::t('The new password has been exposed in a public data dump, please choose another.')); throw new \RuntimeException(L10n::t('The new password has been exposed in a public data dump, please choose another.'));
} }

View file

@ -24,7 +24,7 @@ class CacheSessionHandler extends BaseObject implements SessionHandlerInterface
public function read($session_id) public function read($session_id)
{ {
if (!x($session_id)) { if (empty($session_id)) {
return ''; return '';
} }
@ -58,9 +58,9 @@ class CacheSessionHandler extends BaseObject implements SessionHandlerInterface
return true; return true;
} }
Cache::set('session:' . $session_id, $session_data, Session::$expire); $return = Cache::set('session:' . $session_id, $session_data, Session::$expire);
return true; return $return;
} }
public function close() public function close()
@ -70,8 +70,9 @@ class CacheSessionHandler extends BaseObject implements SessionHandlerInterface
public function destroy($id) public function destroy($id)
{ {
Cache::delete('session:' . $id); $return = Cache::delete('session:' . $id);
return true;
return $return;
} }
public function gc($maxlifetime) public function gc($maxlifetime)

View file

@ -60,12 +60,12 @@ class System extends BaseObject
$previous = ['class' => '', 'function' => '']; $previous = ['class' => '', 'function' => ''];
// The ignore list contains all functions that are only wrapper functions // The ignore list contains all functions that are only wrapper functions
$ignore = ['fetchUrl']; $ignore = ['fetchUrl', 'call_user_func_array'];
while ($func = array_pop($trace)) { while ($func = array_pop($trace)) {
if (!empty($func['class'])) { if (!empty($func['class'])) {
// Don't show multiple calls from the same function (mostly used for "dba" class) // Don't show multiple calls from the "dba" class to show the essential parts of the callstack
if (($previous['class'] != $func['class']) && ($previous['function'] != 'q')) { if ((($previous['class'] != $func['class']) || ($func['class'] != 'dba')) && ($previous['function'] != 'q')) {
$classparts = explode("\\", $func['class']); $classparts = explode("\\", $func['class']);
$callstack[] = array_pop($classparts).'::'.$func['function']; $callstack[] = array_pop($classparts).'::'.$func['function'];
$previous = $func; $previous = $func;

View file

@ -1803,6 +1803,8 @@ class DBStructure
] ]
]; ];
\Friendica\Core\Addon::callHooks('dbstructure_definition', $database);
return $database; return $database;
} }
} }

View file

@ -220,6 +220,11 @@ class Contact extends BaseObject
// Update the public contact as well // Update the public contact as well
dba::update('contact', $fields, ['uid' => 0, 'nurl' => $self['nurl']]); dba::update('contact', $fields, ['uid' => 0, 'nurl' => $self['nurl']]);
// Update the profile
$fields = ['photo' => System::baseUrl() . '/photo/profile/' .$uid . '.jpg',
'thumb' => System::baseUrl() . '/photo/avatar/' . $uid .'.jpg'];
dba::update('profile', $fields, ['uid' => $uid, 'is-default' => true]);
} }
} }
@ -306,7 +311,9 @@ class Contact extends BaseObject
*/ */
/// @todo Check for contact vitality via probing /// @todo Check for contact vitality via probing
$expiry = $contact['term-date'] . ' + 32 days '; $archival_days = Config::get('system', 'archival_days', 32);
$expiry = $contact['term-date'] . ' + ' . $archival_days . ' days ';
if (DateTimeFormat::utcNow() > DateTimeFormat::utc($expiry)) { if (DateTimeFormat::utcNow() > DateTimeFormat::utc($expiry)) {
/* Relationship is really truly dead. archive them rather than /* Relationship is really truly dead. archive them rather than
* delete, though if the owner tries to unarchive them we'll start * delete, though if the owner tries to unarchive them we'll start
@ -343,9 +350,14 @@ class Contact extends BaseObject
$fields = ['term-date' => NULL_DATE, 'archive' => false]; $fields = ['term-date' => NULL_DATE, 'archive' => false];
dba::update('contact', $fields, ['id' => $contact['id']]); dba::update('contact', $fields, ['id' => $contact['id']]);
if ($contact['url'] != '') { if (!empty($contact['url'])) {
dba::update('contact', $fields, ['nurl' => normalise_link($contact['url'])]); dba::update('contact', $fields, ['nurl' => normalise_link($contact['url'])]);
} }
if (!empty($contact['batch'])) {
$condition = ['batch' => $contact['batch'], 'contact-type' => ACCOUNT_TYPE_RELAY];
dba::update('contact', $fields, $condition);
}
} }
/** /**
@ -1470,6 +1482,11 @@ class Contact extends BaseObject
} }
// send email notification to owner? // send email notification to owner?
} else { } else {
if (dba::exists('contact', ['nurl' => normalise_link($url), 'uid' => $importer['uid'], 'pending' => true])) {
logger('ignoring duplicated connection request from pending contact ' . $url);
return;
}
// create contact record // create contact record
q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`, q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `name`, `nick`, `photo`, `network`, `rel`,
`blocked`, `readonly`, `pending`, `writable`) `blocked`, `readonly`, `pending`, `writable`)

View file

@ -500,6 +500,8 @@ class Profile
$p['photo'] = proxy_url($p['photo'], false, PROXY_SIZE_SMALL); $p['photo'] = proxy_url($p['photo'], false, PROXY_SIZE_SMALL);
} }
$p['url'] = self::magicLink($p['url']);
$tpl = get_markup_template('profile_vcard.tpl'); $tpl = get_markup_template('profile_vcard.tpl');
$o .= replace_macros($tpl, [ $o .= replace_macros($tpl, [
'$profile' => $p, '$profile' => $p,
@ -1005,6 +1007,29 @@ class Profile
} }
} }
/**
* @brief Returns a magic link to authenticate remote visitors
*
* @param string $contact_url The address of the contact profile
* @param integer $uid The user id, "local_user" is the default
*
* @return string with "redir" link
*/
public static function magicLink($contact_url, $uid = -1)
{
if ($uid == -1) {
$uid = local_user();
}
$condition = ['pending' => false, 'uid' => $uid,
'nurl' => normalise_link($contact_url),
'network' => NETWORK_DFRN, 'self' => false];
$contact = dba::selectFirst('contact', ['id'], $condition);
if (DBM::is_result($contact)) {
return System::baseUrl() . '/redir/' . $contact['id'];
}
return self::zrl($contact_url);
}
public static function zrl($s, $force = false) public static function zrl($s, $force = false)
{ {
if (!strlen($s)) { if (!strlen($s)) {

View file

@ -9,6 +9,7 @@ use Friendica\Database\DBM;
use dba; use dba;
require_once 'boot.php'; require_once 'boot.php';
require_once 'include/conversation.php';
require_once 'include/dba.php'; require_once 'include/dba.php';
class Term class Term
@ -168,4 +169,56 @@ class Term
} }
} }
} }
/**
* Sorts an item's tags into mentions, hashtags and other tags. Generate personalized URLs by user and modify the
* provided item's body with them.
*
* @param array $item
* @return array
*/
public static function populateTagsFromItem(&$item)
{
$return = [
'tags' => [],
'hashtags' => [],
'mentions' => [],
];
$searchpath = System::baseUrl() . "/search?tag=";
$taglist = dba::select(
'term',
['type', 'term', 'url'],
["`otype` = ? AND `oid` = ? AND `type` IN (?, ?)", TERM_OBJ_POST, $item['id'], TERM_HASHTAG, TERM_MENTION],
['order' => ['tid']]
);
while ($tag = dba::fetch($taglist)) {
if ($tag["url"] == "") {
$tag["url"] = $searchpath . strtolower($tag["term"]);
}
$orig_tag = $tag["url"];
$tag["url"] = best_link_url($item, $sp, $tag["url"]);
if ($tag["type"] == TERM_HASHTAG) {
if ($orig_tag != $tag["url"]) {
$item['body'] = str_replace($orig_tag, $tag["url"], $item['body']);
}
$return['hashtags'][] = "#<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "#";
} elseif ($tag["type"] == TERM_MENTION) {
$return['mentions'][] = "@<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "@";
}
$return['tags'][] = $prefix . "<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
}
dba::close($taglist);
return $return;
}
} }

View file

@ -127,13 +127,23 @@ class User
{ {
$user = self::getAuthenticationInfo($user_info); $user = self::getAuthenticationInfo($user_info);
if ($user['legacy_password']) { if (strpos($user['password'], '$') === false) {
//Legacy hash that has not been replaced by a new hash yet
if (self::hashPasswordLegacy($password) === $user['password']) {
self::updatePassword($user['uid'], $password);
return $user['uid'];
}
} elseif (!empty($user['legacy_password'])) {
//Legacy hash that has been double-hashed and not replaced by a new hash yet
//Warning: `legacy_password` is not necessary in sync with the content of `password`
if (password_verify(self::hashPasswordLegacy($password), $user['password'])) { if (password_verify(self::hashPasswordLegacy($password), $user['password'])) {
self::updatePassword($user['uid'], $password); self::updatePassword($user['uid'], $password);
return $user['uid']; return $user['uid'];
} }
} elseif (password_verify($password, $user['password'])) { } elseif (password_verify($password, $user['password'])) {
//New password hash
if (password_needs_rehash($user['password'], PASSWORD_DEFAULT)) { if (password_needs_rehash($user['password'], PASSWORD_DEFAULT)) {
self::updatePassword($user['uid'], $password); self::updatePassword($user['uid'], $password);
} }
@ -248,6 +258,10 @@ class User
*/ */
public static function hashPassword($password) public static function hashPassword($password)
{ {
if (!trim($password)) {
throw new Exception(L10n::t('Password can\'t be empty'));
}
return password_hash($password, PASSWORD_DEFAULT); return password_hash($password, PASSWORD_DEFAULT);
} }

View file

@ -50,6 +50,7 @@ class Tos extends BaseModule
'$displayprivstatement' => Config::get('system', 'tosprivstatement'), '$displayprivstatement' => Config::get('system', 'tosprivstatement'),
'$privstatementtitle' => L10n::t("Privacy Statement"), '$privstatementtitle' => L10n::t("Privacy Statement"),
'$privoperate' => L10n::t('At the time of registration, and for providing communications between the user account and their contacts, the user has to provide a display name (pen name), an username (nickname) and a working email address. The names will be accessible on the profile page of the account by any visitor of the page, even if other profile details are not displayed. The email address will only be used to send the user notifications about interactions, but wont be visibly displayed. The listing of an account in the node\'s user directory or the global user directory is optional and can be controlled in the user settings, it is not necessary for communication.'), '$privoperate' => L10n::t('At the time of registration, and for providing communications between the user account and their contacts, the user has to provide a display name (pen name), an username (nickname) and a working email address. The names will be accessible on the profile page of the account by any visitor of the page, even if other profile details are not displayed. The email address will only be used to send the user notifications about interactions, but wont be visibly displayed. The listing of an account in the node\'s user directory or the global user directory is optional and can be controlled in the user settings, it is not necessary for communication.'),
'$privdistribute' => L10n::t('This data is required for communication and is passed on to the nodes of the communication partners. Users can enter additional private data that may be transmitted to the communication partners accounts.'),
'$privdelete' => L10n::t('At any point in time a logged in user can export their account data from the <a href="%1$s/settings/uexport">account settings</a>. If the user wants to delete their account they can do so at <a href="%1$s/removeme">%1$s/removeme</a>. The deletion of the account will be permanent.', System::baseurl()) '$privdelete' => L10n::t('At any point in time a logged in user can export their account data from the <a href="%1$s/settings/uexport">account settings</a>. If the user wants to delete their account they can do so at <a href="%1$s/removeme">%1$s/removeme</a>. The deletion of the account will be permanent.', System::baseurl())
]); ]);
} else { } else {

View file

@ -49,10 +49,12 @@ class Diaspora
* *
* The list contains not only the official relays but also servers that we serve directly * The list contains not only the official relays but also servers that we serve directly
* *
* @param integer $item_id The id of the item that is sent * @param integer $item_id The id of the item that is sent
* @param array $contacts The previously fetched contacts
*
* @return array of relay servers * @return array of relay servers
*/ */
public static function relayList($item_id) public static function relayList($item_id, $contacts = [])
{ {
$serverlist = []; $serverlist = [];
@ -99,15 +101,26 @@ class Diaspora
} }
// Now we are collecting all relay contacts // Now we are collecting all relay contacts
$contacts = [];
foreach ($serverlist as $server_url) { foreach ($serverlist as $server_url) {
// We don't send messages to ourselves // We don't send messages to ourselves
if (!link_compare($server_url, System::baseUrl())) { if (link_compare($server_url, System::baseUrl())) {
$cid = self::getRelayContactId($server_url); continue;
if (!is_bool($cid)) { }
$contacts[] = $cid; $contact = self::getRelayContact($server_url);
if (is_bool($contact)) {
continue;
}
$exists = false;
foreach ($contacts as $entry) {
if ($entry['batch'] == $contact['batch']) {
$exists = true;
} }
} }
if (!$exists) {
$contacts[] = $contact;
}
} }
return $contacts; return $contacts;
@ -119,34 +132,34 @@ class Diaspora
* @param string $server_url The url of the server * @param string $server_url The url of the server
* @return array with the contact * @return array with the contact
*/ */
private static function getRelayContactId($server_url) private static function getRelayContact($server_url)
{ {
$batch = $server_url . '/receive/public'; $batch = $server_url . '/receive/public';
$fields = ['batch', 'id', 'name', 'network', 'nick', $fields = ['batch', 'id', 'name', 'network', 'archive', 'blocked'];
'url', 'archive', 'blocked', 'contact-type'];
// Fetch the first unarchived, unblocked account // Fetch the relay contact
$condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch, $condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch,
'archive' => false, 'blocked' => false]; 'contact-type' => ACCOUNT_TYPE_RELAY];
$contact = dba::selectFirst('contact', $fields, $condition); $contact = dba::selectFirst('contact', $fields, $condition);
// If there is nothing found, we check if there is already a relay account // If there is nothing found, we check if there is some unmarked relay
// This code segment can be removed before the release 2018-05
if (!DBM::is_result($contact)) { if (!DBM::is_result($contact)) {
$condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch, $condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch,
'contact-type' => ACCOUNT_TYPE_RELAY]; 'name' => 'relay', 'nick' => 'relay', 'url' => $server_url];
$contact = dba::selectFirst('contact', $fields, $condition); $contact = dba::selectFirst('contact', $fields, $condition);
if (DBM::is_result($contact)) {
// Mark the relay account as a relay account
$fields = ['contact-type' => ACCOUNT_TYPE_RELAY];
dba::update('contact', $fields, ['id' => $contact['id']]);
}
} }
if (DBM::is_result($contact)) { if (DBM::is_result($contact)) {
if ($contact['archive'] || $contact['blocked']) { if ($contact['archive'] || $contact['blocked']) {
return false; return false;
} }
// Mark relay accounts as a relay, if this hadn't been the case before
if (($contact['url'] == $server_url) && ($contact['nick'] == 'relay') &&
($contact['name'] == 'relay') && ($contact['contact-type'] != ACCOUNT_TYPE_RELAY)) {
$fields = ['contact-type' => ACCOUNT_TYPE_RELAY];
dba::update('contact', $fields, ['id' => $contact['id']]);
}
return $contact; return $contact;
} else { } else {
$fields = ['uid' => 0, 'created' => DateTimeFormat::utcNow(), $fields = ['uid' => 0, 'created' => DateTimeFormat::utcNow(),
@ -1160,7 +1173,7 @@ class Diaspora
// Yes, then it is fine. // Yes, then it is fine.
return true; return true;
// Is it a post to a community? // Is it a post to a community?
} elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && ($importer["page-flags"] == PAGE_COMMUNITY)) { } elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && in_array($importer["page-flags"], [PAGE_COMMUNITY, PAGE_PRVGROUP])) {
// That's good // That's good
return true; return true;
// Is the message a global user or a comment? // Is the message a global user or a comment?
@ -1515,36 +1528,29 @@ class Diaspora
*/ */
private static function plink($addr, $guid, $parent_guid = '') private static function plink($addr, $guid, $parent_guid = '')
{ {
$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr)); $contact = Contact::getDetailsByAddr($addr);
// Fallback // Fallback
if (!DBM::is_result($r)) { if (!$contact) {
if ($parent_guid != '') { if ($parent_guid != '') {
return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid; return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid;
} else { } else {
return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid; return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid;
} }
} }
// Friendica contacts are often detected as Diaspora contacts in the "fcontact" table if ($contact["network"] == NETWORK_DFRN) {
// So we try another way as well. return str_replace("/profile/" . $contact["nick"] . "/", "/display/" . $guid, $contact["url"] . "/");
$s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
if (DBM::is_result($s)) {
$r[0]["network"] = $s[0]["network"];
} }
if ($r[0]["network"] == NETWORK_DFRN) { if (self::isRedmatrix($contact["url"])) {
return str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"); return $contact["url"] . "/?f=&mid=" . $guid;
}
if (self::isRedmatrix($r[0]["url"])) {
return $r[0]["url"]."/?f=&mid=".$guid;
} }
if ($parent_guid != '') { if ($parent_guid != '') {
return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid; return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $parent_guid . "#" . $guid;
} else { } else {
return "https://".substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid; return "https://" . substr($addr, strpos($addr, "@") + 1) . "/posts/" . $guid;
} }
} }
@ -2659,7 +2665,7 @@ class Diaspora
Contact::updateAvatar($ret["photo"], $importer['uid'], $contact_record["id"], true); Contact::updateAvatar($ret["photo"], $importer['uid'], $contact_record["id"], true);
if ($importer["page-flags"] == PAGE_NORMAL) { if (in_array($importer["page-flags"], [PAGE_NORMAL, PAGE_PRVGROUP])) {
logger("Sending intra message for author ".$author.".", LOGGER_DEBUG); logger("Sending intra message for author ".$author.".", LOGGER_DEBUG);
$hash = random_string().(string)time(); // Generate a confirm_key $hash = random_string().(string)time(); // Generate a confirm_key
@ -2731,35 +2737,33 @@ class Diaspora
* *
* @return array The fetched item * @return array The fetched item
*/ */
private static function originalItem($guid, $orig_author, $author) public static function originalItem($guid, $orig_author)
{ {
// Do we already have this item? // Do we already have this item?
$r = q( $fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
"SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`, 'author-name', 'author-link', 'author-avatar'];
`author-name`, `author-link`, `author-avatar` $condition = ['guid' => $guid, 'visible' => true, 'deleted' => false];
FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", $item = dba::selectfirst('item', $fields, $condition);
dbesc($guid)
);
if (DBM::is_result($r)) { if (DBM::is_result($item)) {
logger("reshared message ".$guid." already exists on system."); logger("reshared message ".$guid." already exists on system.");
// Maybe it is already a reshared item? // Maybe it is already a reshared item?
// Then refetch the content, if it is a reshare from a reshare. // Then refetch the content, if it is a reshare from a reshare.
// If it is a reshared post from another network then reformat to avoid display problems with two share elements // If it is a reshared post from another network then reformat to avoid display problems with two share elements
if (self::isReshare($r[0]["body"], true)) { if (self::isReshare($item["body"], true)) {
$r = []; $r = [];
} elseif (self::isReshare($r[0]["body"], false) || strstr($r[0]["body"], "[share")) { } elseif (self::isReshare($item["body"], false) || strstr($item["body"], "[share")) {
$r[0]["body"] = Markdown::toBBCode(BBCode::toMarkdown($r[0]["body"])); $item["body"] = Markdown::toBBCode(BBCode::toMarkdown($item["body"]));
$r[0]["body"] = self::replacePeopleGuid($r[0]["body"], $r[0]["author-link"]); $item["body"] = self::replacePeopleGuid($item["body"], $item["author-link"]);
// Add OEmbed and other information to the body // Add OEmbed and other information to the body
$r[0]["body"] = add_page_info_to_body($r[0]["body"], false, true); $item["body"] = add_page_info_to_body($item["body"], false, true);
return $r[0]; return $item;
} else { } else {
return $r[0]; return $item;
} }
} }
@ -2775,21 +2779,19 @@ class Diaspora
} }
if ($item_id) { if ($item_id) {
$r = q( $fields = ['body', 'tag', 'app', 'created', 'object-type', 'uri', 'guid',
"SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`, 'author-name', 'author-link', 'author-avatar'];
`author-name`, `author-link`, `author-avatar` $condition = ['id' => $item_id, 'visible' => true, 'deleted' => false];
FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", $item = dba::selectfirst('item', $fields, $condition);
intval($item_id)
);
if (DBM::is_result($r)) { if (DBM::is_result($item)) {
// If it is a reshared post from another network then reformat to avoid display problems with two share elements // If it is a reshared post from another network then reformat to avoid display problems with two share elements
if (self::isReshare($r[0]["body"], false)) { if (self::isReshare($item["body"], false)) {
$r[0]["body"] = Markdown::toBBCode(BBCode::toMarkdown($r[0]["body"])); $item["body"] = Markdown::toBBCode(BBCode::toMarkdown($item["body"]));
$r[0]["body"] = self::replacePeopleGuid($r[0]["body"], $r[0]["author-link"]); $item["body"] = self::replacePeopleGuid($item["body"], $item["author-link"]);
} }
return $r[0]; return $item;
} }
} }
} }
@ -2825,7 +2827,7 @@ class Diaspora
return true; return true;
} }
$original_item = self::originalItem($root_guid, $root_author, $author); $original_item = self::originalItem($root_guid, $root_author);
if (!$original_item) { if (!$original_item) {
return false; return false;
} }
@ -3319,7 +3321,7 @@ class Diaspora
} }
} }
logger("transmit: ".$logid."-".$guid." returns: ".$return_code); logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code);
if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) { if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
if (!$no_queue && ($contact['contact-type'] != ACCOUNT_TYPE_RELAY)) { if (!$no_queue && ($contact['contact-type'] != ACCOUNT_TYPE_RELAY)) {
@ -3543,24 +3545,21 @@ class Diaspora
// Skip if it isn't a pure repeated messages // Skip if it isn't a pure repeated messages
// Does it start with a share? // Does it start with a share?
if ((strpos($body, "[share") > 0) && $complete) { if ((strpos($body, "[share") > 0) && $complete) {
return(false); return false;
} }
// Does it end with a share? // Does it end with a share?
if (strlen($body) > (strrpos($body, "[/share]") + 8)) { if (strlen($body) > (strrpos($body, "[/share]") + 8)) {
return(false); return false;
} }
$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body); $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism", "$1", $body);
// Skip if there is no shared message in there // Skip if there is no shared message in there
if ($body == $attributes) { if ($body == $attributes) {
return(false); return false;
} }
// If we don't do the complete check we quit here // If we don't do the complete check we quit here
if (!$complete) {
return true;
}
$guid = ""; $guid = "";
preg_match("/guid='(.*?)'/ism", $attributes, $matches); preg_match("/guid='(.*?)'/ism", $attributes, $matches);
@ -3573,18 +3572,14 @@ class Diaspora
$guid = $matches[1]; $guid = $matches[1];
} }
if ($guid != "") { if (($guid != "") && $complete) {
$r = q( $condition = ['guid' => $guid, 'network' => [NETWORK_DFRN, NETWORK_DIASPORA]];
"SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1", $item = dba::selectFirst('item', ['contact-id'], $condition);
dbesc($guid), if (DBM::is_result($item)) {
NETWORK_DFRN,
NETWORK_DIASPORA
);
if ($r) {
$ret= []; $ret= [];
$ret["root_handle"] = self::handleFromContact($r[0]["contact-id"]); $ret["root_handle"] = self::handleFromContact($item["contact-id"]);
$ret["root_guid"] = $guid; $ret["root_guid"] = $guid;
return($ret); return $ret;
} }
} }
@ -3601,28 +3596,22 @@ class Diaspora
$ret= []; $ret= [];
$ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); if ($profile != "") {
if (($ret["root_handle"] == $profile) || ($ret["root_handle"] == "")) { if (Contact::getIdForURL($profile)) {
return(false); $author = Contact::getDetailsByURL($profile);
$ret["root_handle"] = $author['addr'];
}
} }
$link = ""; if (!empty($guid)) {
preg_match("/link='(.*?)'/ism", $attributes, $matches); $ret["root_guid"] = $guid;
if ($matches[1] != "") {
$link = $matches[1];
} }
preg_match('/link="(.*?)"/ism', $attributes, $matches); if (empty($ret) && !$complete) {
if ($matches[1] != "") { return true;
$link = $matches[1];
} }
$ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); return $ret;
if (($ret["root_guid"] == $link) || (trim($ret["root_guid"]) == "")) {
return(false);
}
return($ret);
} }
/** /**
@ -3747,6 +3736,12 @@ class Diaspora
$title = $item["title"]; $title = $item["title"];
$body = $item["body"]; $body = $item["body"];
if ($item['author-link'] != $item['owner-link']) {
require_once 'mod/share.php';
$body = share_header($item['author-name'], $item['author-link'], $item['author-avatar'],
"", $item['created'], $item['plink']) . $body . '[/share]';
}
// convert to markdown // convert to markdown
$body = html_entity_decode(BBCode::toMarkdown($body)); $body = html_entity_decode(BBCode::toMarkdown($body));

View file

@ -1418,7 +1418,14 @@ class PortableContact
dba::delete('gserver-tag', ['gserver-id' => $gserver['id']]); dba::delete('gserver-tag', ['gserver-id' => $gserver['id']]);
if ($data->scope == 'tags') { if ($data->scope == 'tags') {
// Avoid duplicates
$tags = [];
foreach ($data->tags as $tag) { foreach ($data->tags as $tag) {
$tag = mb_strtolower($tag);
$tags[$tag] = $tag;
}
foreach ($tags as $tag) {
dba::insert('gserver-tag', ['gserver-id' => $gserver['id'], 'tag' => $tag]); dba::insert('gserver-tag', ['gserver-id' => $gserver['id'], 'tag' => $tag]);
} }
} }

View file

@ -446,7 +446,7 @@ class Network
/// @TODO Really suppress function outcomes? Why not find them + debug them? /// @TODO Really suppress function outcomes? Why not find them + debug them?
$h = @parse_url($url); $h = @parse_url($url);
if ((is_array($h)) && (@dns_get_record($h['host'], DNS_A + DNS_CNAME + DNS_PTR) || filter_var($h['host'], FILTER_VALIDATE_IP) )) { if ((is_array($h)) && (@dns_get_record($h['host'], DNS_A + DNS_CNAME) || filter_var($h['host'], FILTER_VALIDATE_IP) )) {
return $url; return $url;
} }
@ -471,7 +471,7 @@ class Network
$h = substr($addr, strpos($addr, '@') + 1); $h = substr($addr, strpos($addr, '@') + 1);
if (($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_PTR + DNS_MX) || filter_var($h, FILTER_VALIDATE_IP) )) { if (($h) && (dns_get_record($h, DNS_A + DNS_CNAME + DNS_MX) || filter_var($h, FILTER_VALIDATE_IP) )) {
return true; return true;
} }
return false; return false;

View file

@ -208,7 +208,7 @@ class Delivery {
$atom = DFRN::mail($item, $owner); $atom = DFRN::mail($item, $owner);
} elseif ($fsuggest) { } elseif ($fsuggest) {
$atom = DFRN::fsuggest($item, $owner); $atom = DFRN::fsuggest($item, $owner);
q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id'])); dba::delete('fsuggest', ['id' => $item['id']]);
} elseif ($relocate) { } elseif ($relocate) {
$atom = DFRN::relocate($owner, $uid); $atom = DFRN::relocate($owner, $uid);
} elseif ($followup) { } elseif ($followup) {
@ -290,9 +290,7 @@ class Delivery {
if ($x && count($x)) { if ($x && count($x)) {
$write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false); $write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false);
if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) { if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) {
q("UPDATE `contact` SET `writable` = 1 WHERE `id` = %d", dba::update('contact', ['writable' => true], ['id' => $x[0]['id']]);
intval($x[0]['id'])
);
$x[0]['writable'] = 1; $x[0]['writable'] = 1;
} }
@ -401,7 +399,7 @@ class Delivery {
$headers = 'From: '.Email::encodeHeader($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n"; $headers = 'From: '.Email::encodeHeader($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n";
} }
} else { } else {
$headers = 'From: '. Email::encodeHeader($local_user[0]['username'],'UTF-8') .' <'. L10n::t('noreply') .'@'.$a->get_hostname() .'>'. "\n"; $headers = 'From: '. Email::encodeHeader($local_user[0]['username'], 'UTF-8') . ' <noreply@' . $a->get_hostname() . '>' . "\n";
} }
//if ($reply_to) //if ($reply_to)

View file

@ -13,6 +13,7 @@ use Friendica\Network\Probe;
use Friendica\Protocol\PortableContact; use Friendica\Protocol\PortableContact;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network; use Friendica\Util\Network;
use dba;
class DiscoverPoCo { class DiscoverPoCo {
/// @todo Clean up this mess of a parameter hell and split it in several classes /// @todo Clean up this mess of a parameter hell and split it in several classes
@ -158,8 +159,8 @@ class DiscoverPoCo {
$urlparts = parse_url($user["url"]); $urlparts = parse_url($user["url"]);
if (!isset($urlparts["scheme"])) { if (!isset($urlparts["scheme"])) {
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'", dba::update('gcontact', ['network' => NETWORK_PHANTOM],
dbesc(NETWORK_PHANTOM), dbesc(normalise_link($user["url"]))); ['nurl' => normalise_link($user["url"])]);
continue; continue;
} }
@ -171,8 +172,8 @@ class DiscoverPoCo {
"identi.ca" => NETWORK_PUMPIO, "identi.ca" => NETWORK_PUMPIO,
"alpha.app.net" => NETWORK_APPNET]; "alpha.app.net" => NETWORK_APPNET];
q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'", dba::update('gcontact', ['network' => $networks[$urlparts["host"]]],
dbesc($networks[$urlparts["host"]]), dbesc(normalise_link($user["url"]))); ['nurl' => normalise_link($user["url"])]);
continue; continue;
} }
@ -194,8 +195,8 @@ class DiscoverPoCo {
return; return;
} }
} else { } else {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'", dba::update('gcontact', ['last_failure' => DateTimeFormat::utcNow()],
dbesc(DateTimeFormat::utcNow()), dbesc(normalise_link($user["url"]))); ['nurl' => normalise_link($user["url"])]);
} }
// Quit the loop after 3 minutes // Quit the loop after 3 minutes

View file

@ -479,15 +479,9 @@ class Notifier {
if ($public_message) { if ($public_message) {
$r0 = [];
$r1 = []; $r1 = [];
if ($diaspora_delivery) { if ($diaspora_delivery) {
if (!$followup) {
$r0 = Diaspora::relayList($item_id);
}
$r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network` $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network`
FROM `contact` WHERE `network` = '%s' AND `batch` != '' FROM `contact` WHERE `network` = '%s' AND `batch` != ''
AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`", AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`",
@ -500,17 +494,17 @@ class Notifier {
// The function will ensure that there are no duplicates // The function will ensure that there are no duplicates
$r1 = Diaspora::participantsForThread($item_id, $r1); $r1 = Diaspora::participantsForThread($item_id, $r1);
// Add the relay to the list, avoid duplicates
if (!$followup) {
$r1 = Diaspora::relayList($item_id, $r1);
}
} }
$r2 = q("SELECT `id`, `name`,`network` FROM `contact` $condition = ['network' => NETWORK_DFRN, 'uid' => $owner['uid'], 'blocked' => false,
WHERE `network` in ('%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `rel` != %d", 'pending' => false, 'archive' => false, 'rel' => [CONTACT_IS_FOLLOWER, CONTACT_IS_FRIEND]];
dbesc(NETWORK_DFRN), $r2 = dba::inArray(dba::select('contact', ['id', 'name', 'network'], $condition));
intval($owner['uid']),
intval(CONTACT_IS_SHARING)
);
$r = array_merge($r2, $r1);
$r = array_merge($r2, $r1, $r0);
if (DBM::is_result($r)) { if (DBM::is_result($r)) {
logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG); logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG);
@ -541,8 +535,8 @@ class Notifier {
if ($push_notify) { if ($push_notify) {
// Set push flag for PuSH subscribers to this topic, // Set push flag for PuSH subscribers to this topic,
// they will be notified in queue.php // they will be notified in queue.php
q("UPDATE `push_subscriber` SET `push` = 1 ". $condition = ['push' => false, 'nickname' => $owner['nickname']];
"WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname'])); dba::update('push_subscriber', ['push' => true], $condition);
logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG); logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG);

View file

@ -12,6 +12,7 @@ use Friendica\Core\Worker;
use Friendica\Database\DBM; use Friendica\Database\DBM;
use Friendica\Protocol\OStatus; use Friendica\Protocol\OStatus;
use Friendica\Util\Network; use Friendica\Util\Network;
use dba;
require_once 'include/items.php'; require_once 'include/items.php';
@ -76,9 +77,8 @@ class PubSubPublish {
logger('successfully pushed to '.$rr['callback_url']); logger('successfully pushed to '.$rr['callback_url']);
// set last_update to the "created" date of the last item, and reset push=0 // set last_update to the "created" date of the last item, and reset push=0
q("UPDATE `push_subscriber` SET `push` = 0, last_update = '%s' WHERE id = %d", $fields = ['push' => 0, 'last_update' => $last_update];
dbesc($last_update), dba::update('push_subscriber', $fields, ['id' => $rr['id']]);
intval($rr['id']));
} else { } else {
logger('error when pushing to '.$rr['callback_url'].' HTTP: '.$ret); logger('error when pushing to '.$rr['callback_url'].' HTTP: '.$ret);
@ -90,9 +90,7 @@ class PubSubPublish {
if ($new_push > 30) // OK, let's give up if ($new_push > 30) // OK, let's give up
$new_push = 0; $new_push = 0;
q("UPDATE `push_subscriber` SET `push` = %d WHERE id = %d", dba::update('push_subscriber', ['push' => $new_push], ['id' => $rr['id']]);
$new_push,
intval($rr['id']));
} }
} }
} }

View file

@ -36,7 +36,7 @@ class Queue
// Handling the pubsubhubbub requests // Handling the pubsubhubbub requests
Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], 'PubSubPublish'); Worker::add(['priority' => PRIORITY_HIGH, 'dont_fork' => true], 'PubSubPublish');
$r = dba::inArray(dba::p("SELECT `id` FROM `queue` WHERE `next` < UTC_TIMESTAMP()")); $r = dba::inArray(dba::p("SELECT `id` FROM `queue` WHERE `next` < UTC_TIMESTAMP() ORDER BY `batch`, `cid`"));
Addon::callHooks('queue_predeliver', $r); Addon::callHooks('queue_predeliver', $r);
@ -86,7 +86,7 @@ class Queue
logger("Check server " . $server . " (" . $contact["network"] . ")"); logger("Check server " . $server . " (" . $contact["network"] . ")");
$vital = PortableContact::checkServer($server, $contact["network"], true); $vital = PortableContact::checkServer($server, $contact["network"], true);
Cache::set($cachekey_server . $server, $vital, CACHE_QUARTER_HOUR); Cache::set($cachekey_server . $server, $vital, CACHE_MINUTE);
} }
if (!is_null($vital) && !$vital) { if (!is_null($vital) && !$vital) {
@ -118,7 +118,7 @@ class Queue
QueueModel::removeItem($q_item['id']); QueueModel::removeItem($q_item['id']);
} else { } else {
QueueModel::updateTime($q_item['id']); QueueModel::updateTime($q_item['id']);
Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_QUARTER_HOUR); Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_MINUTE);
} }
break; break;
case NETWORK_OSTATUS: case NETWORK_OSTATUS:
@ -127,7 +127,7 @@ class Queue
if ($deliver_status == -1) { if ($deliver_status == -1) {
QueueModel::updateTime($q_item['id']); QueueModel::updateTime($q_item['id']);
Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_QUARTER_HOUR); Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_MINUTE);
} else { } else {
QueueModel::removeItem($q_item['id']); QueueModel::removeItem($q_item['id']);
} }
@ -141,7 +141,7 @@ class Queue
QueueModel::removeItem($q_item['id']); QueueModel::removeItem($q_item['id']);
} else { } else {
QueueModel::updateTime($q_item['id']); QueueModel::updateTime($q_item['id']);
Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_QUARTER_HOUR); Cache::set($cachekey_deadguy . $contact['notify'], true, CACHE_MINUTE);
} }
break; break;

View file

@ -2,6 +2,8 @@
namespace Friendica\Worker; namespace Friendica\Worker;
use dba;
class TagUpdate class TagUpdate
{ {
public static function execute() public static function execute()
@ -13,18 +15,14 @@ class TagUpdate
if ($message['uid'] == 0) { if ($message['uid'] == 0) {
$global = true; $global = true;
q("UPDATE `term` SET `global` = 1 WHERE `otype` = %d AND `guid` = '%s'", dba::update('term', ['global' => true], ['otype' => TERM_OBJ_POST, 'guid' => $message['guid']]);
intval(TERM_OBJ_POST), dbesc($message['guid']));
} else { } else {
$isglobal = q("SELECT `global` FROM `term` WHERE `uid` = 0 AND `otype` = %d AND `guid` = '%s'", $global = (dba::count('term', ['uid' => 0, 'otype' => TERM_OBJ_POST, 'guid' => $message['guid']]) > 0);
intval(TERM_OBJ_POST), dbesc($message['guid']));
$global = (count($isglobal) > 0);
} }
q("UPDATE `term` SET `guid` = '%s', `created` = '%s', `received` = '%s', `global` = %d WHERE `otype` = %d AND `oid` = %d", $fields = ['guid' => $message['guid'], 'created' => $message['created'],
dbesc($message['guid']), dbesc($message['created']), dbesc($message['received']), 'received' => $message['received'], 'global' => $global];
intval($global), intval(TERM_OBJ_POST), intval($message['oid'])); dba::update('term', $fields, ['otype' => TERM_OBJ_POST, 'oid' => $message['oid']]);
} }
dba::close($messages); dba::close($messages);
@ -33,7 +31,7 @@ class TagUpdate
logger('fetched messages: ' . dba::num_rows($messages)); logger('fetched messages: ' . dba::num_rows($messages));
while ($message = dba::fetch(messages)) { while ($message = dba::fetch(messages)) {
q("UPDATE `item` SET `global` = 1 WHERE `guid` = '%s'", dbesc($message['guid'])); dba::update('item', ['global' => true], ['guid' => $message['guid']]);
} }
dba::close($messages); dba::close($messages);

45
tests/BaseObjectTest.php Normal file
View file

@ -0,0 +1,45 @@
<?php
/**
* BaseObjectTest class.
*/
namespace Friendica\Test;
use Friendica\App;
use Friendica\BaseObject;
use PHPUnit_Framework_TestCase;
/**
* Tests for the BaseObject class.
*/
class BaseObjectTest extends PHPUnit_Framework_TestCase
{
/**
* Create variables used in tests.
*/
protected function setUp()
{
$this->baseObject = new BaseObject();
}
/**
* Test the getApp() function.
* @return void
*/
public function testGetApp()
{
$this->assertInstanceOf(App::class, $this->baseObject->getApp());
}
/**
* Test the setApp() function.
* @return void
*/
public function testSetApp()
{
$app = new App(__DIR__.'/../');
$this->assertNull($this->baseObject->setApp($app));
$this->assertEquals($app, $this->baseObject->getApp());
}
}

301
tests/TextTest.php Normal file
View file

@ -0,0 +1,301 @@
<?php
/**
* TextTest class.
*/
namespace Friendica\Test;
use PHPUnit_Framework_TestCase;
/**
* Tests for text functions.
*/
class TextTest extends PHPUnit_Framework_TestCase
{
/**
*autonames should be random, even length
*/
public function testAutonameEven()
{
$autoname1=autoname(10);
$autoname2=autoname(10);
$this->assertNotEquals($autoname1, $autoname2);
}
/**
*autonames should be random, odd length
*/
public function testAutonameOdd()
{
$autoname1=autoname(9);
$autoname2=autoname(9);
$this->assertNotEquals($autoname1, $autoname2);
}
/**
* try to fail autonames
*/
public function testAutonameNoLength()
{
$autoname1=autoname(0);
$this->assertEquals(0, strlen($autoname1));
}
/**
* try to fail it with invalid input
*
* @todo What's corect behaviour here? An exception?
*/
public function testAutonameNegativeLength()
{
$autoname1=autoname(-23);
$this->assertEquals(0, strlen($autoname1));
}
/**
* test with a length, that may be too short
*/
public function testAutonameLength1()
{
$autoname1=autoname(1);
$this->assertEquals(1, count($autoname1));
$autoname2=autoname(1);
$this->assertEquals(1, count($autoname2));
}
/**
* test attribute contains
*/
public function testAttributeContains1()
{
$testAttr="class1 notclass2 class3";
$this->assertTrue(attribute_contains($testAttr, "class3"));
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test attribute contains
*/
public function testAttributeContains2()
{
$testAttr="class1 not-class2 class3";
$this->assertTrue(attribute_contains($testAttr, "class3"));
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test with empty input
*/
public function testAttributeContainsEmpty()
{
$testAttr="";
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test input with special chars
*/
public function testAttributeContainsSpecialChars()
{
$testAttr="--... %\$ä() /(=?}";
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test expand_acl, perfect input
*/
public function testExpandAclNormal()
{
$text='<1><2><3>';
$this->assertEquals(array(1, 2, 3), expand_acl($text));
}
/**
* test with a big number
*/
public function testExpandAclBigNumber()
{
$text='<1><'.PHP_INT_MAX.'><15>';
$this->assertEquals(array(1, PHP_INT_MAX, 15), expand_acl($text));
}
/**
* test with a string in it.
*
* @todo is this valid input? Otherwise: should there be an exception?
*/
public function testExpandAclString()
{
$text="<1><279012><tt>";
$this->assertEquals(array(1, 279012), expand_acl($text));
}
/**
* test with a ' ' in it.
*
* @todo is this valid input? Otherwise: should there be an exception?
*/
public function testExpandAclSpace()
{
$text="<1><279 012><32>";
$this->assertEquals(array(1, "279", "32"), expand_acl($text));
}
/**
* test empty input
*/
public function testExpandAclEmpty()
{
$text="";
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, no < at all
*
* @todo should there be an exception?
*/
public function testExpandAclNoBrackets()
{
$text="According to documentation, that's invalid. "; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just open <
*
* @todo should there be an exception?
*/
public function testExpandAclJustOneBracket1()
{
$text="<Another invalid string"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just close >
*
* @todo should there be an exception?
*/
public function testExpandAclJustOneBracket2()
{
$text="Another invalid> string"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just close >
*
* @todo should there be an exception?
*/
public function testExpandAclCloseOnly()
{
$text="Another> invalid> string>"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just open <
*
* @todo should there be an exception?
*/
public function testExpandAclOpenOnly()
{
$text="<Another< invalid string<"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, open and close do not match
*
* @todo should there be an exception?
*/
public function testExpandAclNoMatching1()
{
$text="<Another<> invalid <string>"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, empty <>
*
* @todo should there be an exception? Or array(1, 3)
* (This should be array(1,3) - mike)
*/
public function testExpandAclEmptyMatch()
{
$text="<1><><3>";
$this->assertEquals(array(1,3), expand_acl($text));
}
/**
* test, that tags are escaped
*/
public function testEscapeTags()
{
$invalidstring='<submit type="button" onclick="alert(\'failed!\');" />';
$validstring=notags($invalidstring);
$escapedString=escape_tags($invalidstring);
$this->assertEquals('[submit type="button" onclick="alert(\'failed!\');" /]', $validstring);
$this->assertEquals(
"&lt;submit type=&quot;button&quot; onclick=&quot;alert('failed!');&quot; /&gt;",
$escapedString
);
}
/**
*xmlify and unxmlify
*/
public function testXmlify()
{
$text="<tag>I want to break\n this!11!<?hard?></tag>";
$xml=xmlify($text);
$retext=unxmlify($text);
$this->assertEquals($text, $retext);
}
/**
* xmlify and put in a document
*/
public function testXmlifyDocument()
{
$tag="<tag>I want to break</tag>";
$xml=xmlify($tag);
$text='<text>'.$xml.'</text>';
$xml_parser=xml_parser_create();
//should be possible to parse it
$values=array();
$index=array();
$this->assertEquals(1, xml_parse_into_struct($xml_parser, $text, $values, $index));
$this->assertEquals(
array('TEXT'=>array(0)),
$index
);
$this->assertEquals(
array(array('tag'=>'TEXT', 'type'=>'complete', 'level'=>1, 'value'=>$tag)),
$values
);
xml_parser_free($xml_parser);
}
/**
* test hex2bin and reverse
*/
public function testHex2Bin()
{
$this->assertEquals(-3, hex2bin(bin2hex(-3)));
$this->assertEquals(0, hex2bin(bin2hex(0)));
$this->assertEquals(12, hex2bin(bin2hex(12)));
$this->assertEquals(PHP_INT_MAX, hex2bin(bin2hex(PHP_INT_MAX)));
}
}

View file

@ -1,76 +0,0 @@
<?php
/**
* this file contains tests for the autoname function
*
* @package test.util
*/
/** required, it is the file under test */
require_once('include/text.php');
/**
* TestCase for the autoname function
*
* @author Alexander Kampmann
* @package test.util
*/
class AutonameTest extends PHPUnit_Framework_TestCase {
/**
*autonames should be random, even length
*/
public function testAutonameEven() {
$autoname1=autoname(10);
$autoname2=autoname(10);
$this->assertNotEquals($autoname1, $autoname2);
}
/**
*autonames should be random, odd length
*/
public function testAutonameOdd() {
$autoname1=autoname(9);
$autoname2=autoname(9);
$this->assertNotEquals($autoname1, $autoname2);
}
/**
* try to fail autonames
*/
public function testAutonameNoLength() {
$autoname1=autoname(0);
$this->assertEquals(0, strlen($autoname1));
}
/**
* try to fail it with invalid input
*
* TODO: What's corect behaviour here? An exception?
*/
public function testAutonameNegativeLength() {
$autoname1=autoname(-23);
$this->assertEquals(0, strlen($autoname1));
}
// public function testAutonameMaxLength() {
// $autoname2=autoname(PHP_INT_MAX);
// $this->assertEquals(PHP_INT_MAX, count($autoname2));
// }
/**
* test with a length, that may be too short
*/
public function testAutonameLength1() {
$autoname1=autoname(1);
$this->assertEquals(1, count($autoname1));
$autoname2=autoname(1);
$this->assertEquals(1, count($autoname2));
// The following test is problematic, with only 26 possibilities
// generating the same thing twice happens often aka
// birthday paradox
// $this->assertFalse($autoname1==$autoname2);
}
}

View file

@ -1,51 +0,0 @@
<?php
/**
* this test tests the contains_attribute function
*
* @package test.util
*/
/** required, it is the file under test */
require_once('include/text.php');
/**
* TestCase for the contains_attribute function
*
* @author Alexander Kampmann
* @package test.util
*/
class ContainsAttributeTest extends PHPUnit_Framework_TestCase {
/**
* test attribute contains
*/
public function testAttributeContains1() {
$testAttr="class1 notclass2 class3";
$this->assertTrue(attribute_contains($testAttr, "class3"));
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test attribute contains
*/
public function testAttributeContains2() {
$testAttr="class1 not-class2 class3";
$this->assertTrue(attribute_contains($testAttr, "class3"));
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test with empty input
*/
public function testAttributeContainsEmpty() {
$testAttr="";
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
/**
* test input with special chars
*/
public function testAttributeContainsSpecialChars() {
$testAttr="--... %\$ä() /(=?}";
$this->assertFalse(attribute_contains($testAttr, "class2"));
}
}

View file

@ -1,148 +0,0 @@
<?php
/**
* this test tests the expand_acl function
*
* @package test.util
*/
/** required, it is the file under test */
require_once('include/text.php');
/**
* TestCase for the expand_acl function
*
* @author Alexander Kampmann
* @package test.util
*/
class ExpandAclTest extends PHPUnit_Framework_TestCase {
/**
* test expand_acl, perfect input
*/
public function testExpandAclNormal() {
$text='<1><2><3>';
$this->assertEquals(array(1, 2, 3), expand_acl($text));
}
/**
* test with a big number
*/
public function testExpandAclBigNumber() {
$text='<1><'.PHP_INT_MAX.'><15>';
$this->assertEquals(array(1, PHP_INT_MAX, 15), expand_acl($text));
}
/**
* test with a string in it.
*
* TODO: is this valid input? Otherwise: should there be an exception?
*/
public function testExpandAclString() {
$text="<1><279012><tt>";
$this->assertEquals(array(1, 279012), expand_acl($text));
}
/**
* test with a ' ' in it.
*
* TODO: is this valid input? Otherwise: should there be an exception?
*/
public function testExpandAclSpace() {
$text="<1><279 012><32>";
$this->assertEquals(array(1, "279", "32"), expand_acl($text));
}
/**
* test empty input
*/
public function testExpandAclEmpty() {
$text="";
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, no < at all
*
* TODO: should there be an exception?
*/
public function testExpandAclNoBrackets() {
$text="According to documentation, that's invalid. "; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just open <
*
* TODO: should there be an exception?
*/
public function testExpandAclJustOneBracket1() {
$text="<Another invalid string"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just close >
*
* TODO: should there be an exception?
*/
public function testExpandAclJustOneBracket2() {
$text="Another invalid> string"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just close >
*
* TODO: should there be an exception?
*/
public function testExpandAclCloseOnly() {
$text="Another> invalid> string>"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, just open <
*
* TODO: should there be an exception?
*/
public function testExpandAclOpenOnly() {
$text="<Another< invalid string<"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, open and close do not match
*
* TODO: should there be an exception?
*/
public function testExpandAclNoMatching1() {
$text="<Another<> invalid <string>"; //should be invalid
$this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, open and close do not match
*
* TODO: should there be an exception?
*/
public function testExpandAclNoMatching2() {
$text="<1>2><3>";
// The angles are delimiters which aren't important
// the important thing is the numeric content, this returns array(1,2,3) currently
// we may wish to eliminate 2 from the results, though it isn't harmful
// It would be a better test to figure out if there is any ACL input which can
// produce this $text and fix that instead.
// $this->assertEquals(array(), expand_acl($text));
}
/**
* test invalid input, empty <>
*
* TODO: should there be an exception? Or array(1, 3)
* (This should be array(1,3) - mike)
*/
public function testExpandAclEmptyMatch() {
$text="<1><><3>";
$this->assertEquals(array(1,3), expand_acl($text));
}
}

View file

@ -1,326 +0,0 @@
<?php
/**
* This file contains the tests for get_tags and the tag handling in item.php
*
* @package test.util
*/
/**
* required, because it contains the get_tags() function
*/
require_once 'include/text.php';
/**
* required, because it contains the tag handling
*/
require_once 'mod/item.php';
/**
* A class which can be used as replacement for an app if
* only get_baseurl is used.
*
* @author Alexander Kampmann
* @package test.util
*/
class MockApp {
function get_baseurl() {
return "baseurl";
}
};
/**
* the test should not rely on a database,
* so this is a replacement for the database access method q.
*
* It simulates the user with uid 11 has one contact, named Mike Lastname.
*
* @param string $sql
*/
function q($sql) {
$result=array(array('id'=>15,
'attag'=>'', 'network'=>'dfrn',
'name'=>'Mike Lastname', 'alias'=>'Mike',
'nick'=>'Mike', 'url'=>"http://justatest.de"));
$args=func_get_args();
//last parameter is always (in this test) uid, so, it should be 11
if($args[count($args)-1]!=11) {
return;
}
if(3==count($args)) {
//first call in handle_body, id only
if($result[0]['id']==$args[1]) {
return $result;
}
//second call in handle_body, name
if($result[0]['name']===$args[1]) {
return $result;
}
}
//third call in handle_body, nick or attag
if($result[0]['nick']===$args[2] || $result[0]['attag']===$args[1]) {
return $result;
}
}
/**
* replacement for dbesc.
* I don't want to test dbesc here, so
* I just return the input. It won't be a problem, because
* the test does not use a real database.
*
* DON'T USE HAT FUNCTION OUTSIDE A TEST!
*
* @param string $str
* @return input
*/
function dbesc($str) {
return $str;
}
/**
* TestCase for tag handling.
*
* @author alexander
* @package test.util
*/
class GetTagsTest extends PHPUnit_Framework_TestCase {
/** the mock to use as app */
private $a;
/**
* initialize the test. That's a phpUnit function,
* don't change its name.
*/
public function setUp() {
$this->a=new MockApp();
}
/**
* test with one Person tag
*/
public function testGetTagsShortPerson() {
$text="hi @Mike";
$tags=get_tags($text);
$inform='';
$str_tags='';
foreach($tags as $tag) {
handle_tag($this->a, $text, $inform, $str_tags, 11, $tag);
}
//correct tags found?
$this->assertEquals(1, count($tags));
$this->assertTrue(in_array("@Mike", $tags));
//correct output from handle_tag?
$this->assertEquals("cid:15", $inform);
$this->assertEquals("@[url=http://justatest.de]Mike Lastname[/url]", $str_tags);
$this->assertEquals("hi @[url=http://justatest.de]Mike Lastname[/url]", $text);
}
/**
* test with one Person tag.
* There's a minor spelling mistake...
*/
public function testGetTagsShortPersonSpelling() {
$text="hi @Mike.because";
$tags=get_tags($text);
//correct tags found?
$this->assertEquals(1, count($tags));
$this->assertTrue(in_array("@Mike.because", $tags));
$inform='';
$str_tags='';
handle_tag($this->a, $text, $inform, $str_tags, 11, $tags[0]);
// (mike) - This is a tricky case.
// we support mentions as in @mike@example.com - which contains a period.
// This shouldn't match anything unless you have a contact named "Mike.because".
// We may need another test for "@Mike. because" - which should return the contact
// as we ignore trailing periods in tags.
// $this->assertEquals("cid:15", $inform);
// $this->assertEquals("@[url=http://justatest.de]Mike Lastname[/url]", $str_tags);
// $this->assertEquals("hi @[url=http://justatest.de]Mike Lastname[/url].because", $text);
$this->assertEquals("", $inform);
$this->assertEquals("", $str_tags);
}
/**
* test with two Person tags.
* There's a minor spelling mistake...
*/
public function testGetTagsPerson2Spelling() {
$text="hi @Mike@campino@friendica.eu";
$tags=get_tags($text);
// This construct is not supported. Results are indeterminate
// $this->assertEquals(2, count($tags));
// $this->assertTrue(in_array("@Mike", $tags));
// $this->assertTrue(in_array("@campino@friendica.eu", $tags));
}
/**
* Test with one hash tag.
*/
public function testGetTagsShortTag() {
$text="This is a #test_case";
$tags=get_tags($text);
$this->assertEquals(1, count($tags));
$this->assertTrue(in_array("#test_case", $tags));
}
/**
* test with a person and a hash tag
*/
public function testGetTagsShortTagAndPerson() {
$text="hi @Mike This is a #test_case";
$tags=get_tags($text);
$this->assertEquals(3, count($tags));
$this->assertTrue(in_array("@Mike", $tags));
$this->assertTrue(in_array("@Mike This", $tags));
$this->assertTrue(in_array("#test_case", $tags));
$inform='';
$str_tags='';
foreach($tags as $tag) {
handle_tag($this->a, $text, $inform, $str_tags, 11, $tag);
}
$this->assertEquals("cid:15", $inform);
$this->assertEquals("@[url=http://justatest.de]Mike Lastname[/url],#[url=baseurl/search?tag=test%20case]test case[/url]", $str_tags);
$this->assertEquals("hi @[url=http://justatest.de]Mike Lastname[/url] This is a #[url=baseurl/search?tag=test%20case]test case[/url]", $text);
}
/**
* test with a person, a hash tag and some special chars.
*/
public function testGetTagsShortTagAndPersonSpecialChars() {
$text="hi @Mike, This is a #test_case.";
$tags=get_tags($text);
$this->assertEquals(2, count($tags));
$this->assertTrue(in_array("@Mike", $tags));
$this->assertTrue(in_array("#test_case", $tags));
}
/**
* Test with a person tag and text behind it.
*/
public function testGetTagsPersonOnly() {
$text="@Test I saw the Theme Dev group was created.";
$tags=get_tags($text);
$this->assertEquals(2, count($tags));
$this->assertTrue(in_array("@Test I", $tags));
$this->assertTrue(in_array("@Test", $tags));
}
/**
* this test demonstrates strange behaviour by intval.
* It makes the next test fail.
*/
public function testIntval() {
$this->assertEquals(15, intval("15 it"));
}
/**
* test a tag with an id in it
*/
public function testIdTag() {
$text="Test with @mike+15 id tag";
$tags=get_tags($text);
$this->assertEquals(2, count($tags));
$this->assertTrue(in_array("@mike+15", $tags));
//happens right now, but it shouldn't be necessary
$this->assertTrue(in_array("@mike+15 id", $tags));
$inform='';
$str_tags='';
foreach($tags as $tag) {
handle_tag($this->a, $text, $inform, $str_tags, 11, $tag);
}
$this->assertEquals("Test with @[url=http://justatest.de]Mike Lastname[/url] id tag", $text);
$this->assertEquals("@[url=http://justatest.de]Mike Lastname[/url]", $str_tags);
// this test may produce two cid:15 entries - which is OK because duplicates are pruned before delivery
$this->assertContains("cid:15",$inform);
}
/**
* test with two persons and one special tag.
*/
public function testGetTags2Persons1TagSpecialChars() {
$text="hi @Mike, I'm just writing #test_cases, so"
." so @somebody@friendica.com may change #things.";
$tags=get_tags($text);
$this->assertEquals(5, count($tags));
$this->assertTrue(in_array("@Mike", $tags));
$this->assertTrue(in_array("#test_cases", $tags));
$this->assertTrue(in_array("@somebody@friendica.com", $tags));
$this->assertTrue(in_array("@somebody@friendica.com may", $tags));
$this->assertTrue(in_array("#things", $tags));
}
/**
* test with a long text.
*/
public function testGetTags() {
$text="hi @Mike, I'm just writing #test_cases, "
." so @somebody@friendica.com may change #things. Of course I "
."look for a lot of #pitfalls, like #tags at the end of a sentence "
."@comment. I hope noone forgets about @fullstops.because that might"
." break #things. @Mike@campino@friendica.eu is also #nice, isn't it? "
."Now, add a @first_last tag. ";
$tags=get_tags($text);
$this->assertTrue(in_array("@Mike", $tags));
$this->assertTrue(in_array("#test_cases", $tags));
$this->assertTrue(in_array("@somebody@friendica.com", $tags));
$this->assertTrue(in_array("#things", $tags));
$this->assertTrue(in_array("#pitfalls", $tags));
$this->assertTrue(in_array("#tags", $tags));
$this->assertTrue(in_array("@comment", $tags));
$this->assertTrue(in_array("@fullstops.because", $tags));
$this->assertTrue(in_array("#things", $tags));
$this->assertTrue(in_array("@Mike", $tags));
$this->assertTrue(in_array("#nice", $tags));
$this->assertTrue(in_array("@first_last", $tags));
//right now, none of the is matched (unsupported)
// $this->assertFalse(in_array("@Mike@campino@friendica.eu", $tags));
// $this->assertTrue(in_array("@campino@friendica.eu", $tags));
// $this->assertTrue(in_array("@campino@friendica.eu is", $tags));
}
/**
* test with an empty string
*/
public function testGetTagsEmpty() {
$tags=get_tags("");
$this->assertEquals(0, count($tags));
}
}

View file

@ -1,224 +0,0 @@
<?php
/**
* this file contains tests for the template engine
*
* @package test.util
*/
/** required, it is the file under test */
require_once('include/template_processor.php');
require_once('include/text.php');
class TemplateMockApp {
public $theme_info=array();
}
if(!function_exists('current_theme')) {
function current_theme() {
return 'clean';
}
}
if(!function_exists('x')) {
function x($s,$k = NULL) {
return false;
}
}
if(!function_exists('get_app')) {
function get_app() {
return new TemplateMockApp();
}
}
/**
* TestCase for the template engine
*
* @author Alexander Kampmann
* @package test.util
*/
class TemplateTest extends PHPUnit_Framework_TestCase {
public function setUp() {
global $t;
$t=new Template;
}
public function testListToShort() {
@list($first, $second)=array('first');
$this->assertTrue(is_null($second));
}
public function testSimpleVariableString() {
$tpl='Hello $name!';
$text=replace_macros($tpl, array('$name'=>'Anna'));
$this->assertEquals('Hello Anna!', $text);
}
public function testSimpleVariableInt() {
$tpl='There are $num new messages!';
$text=replace_macros($tpl, array('$num'=>172));
$this->assertEquals('There are 172 new messages!', $text);
}
public function testConditionalElse() {
$tpl='There{{ if $num!=1 }} are $num new messages{{ else }} is 1 new message{{ endif }}!';
$text1=replace_macros($tpl, array('$num'=>1));
$text22=replace_macros($tpl, array('$num'=>22));
$this->assertEquals('There is 1 new message!', $text1);
$this->assertEquals('There are 22 new messages!', $text22);
}
public function testConditionalNoElse() {
$tpl='{{ if $num!=0 }}There are $num new messages!{{ endif }}';
$text0=replace_macros($tpl, array('$num'=>0));
$text22=replace_macros($tpl, array('$num'=>22));
$this->assertEquals('', $text0);
$this->assertEquals('There are 22 new messages!', $text22);
}
public function testConditionalFail() {
$tpl='There {{ if $num!=1 }} are $num new messages{{ else }} is 1 new message{{ endif }}!';
$text1=replace_macros($tpl, array());
//$this->assertEquals('There is 1 new message!', $text1);
}
public function testSimpleFor() {
$tpl='{{ for $messages as $message }} $message {{ endfor }}';
$text=replace_macros($tpl, array('$messages'=>array('message 1', 'message 2')));
$this->assertEquals(' message 1 message 2 ', $text);
}
public function testFor() {
$tpl='{{ for $messages as $message }} from: $message.from to $message.to {{ endfor }}';
$text=replace_macros($tpl, array('$messages'=>array(array('from'=>'Mike', 'to'=>'Alex'), array('from'=>'Alex', 'to'=>'Mike'))));
$this->assertEquals(' from: Mike to Alex from: Alex to Mike ', $text);
}
public function testKeyedFor() {
$tpl='{{ for $messages as $from=>$to }} from: $from to $to {{ endfor }}';
$text=replace_macros($tpl, array('$messages'=>array('Mike'=>'Alex', 'Sven'=>'Mike')));
$this->assertEquals(' from: Mike to Alex from: Sven to Mike ', $text);
}
public function testForEmpty() {
$tpl='messages: {{for $messages as $message}} from: $message.from to $message.to {{ endfor }}';
$text=replace_macros($tpl, array('$messages'=>array()));
$this->assertEquals('messages: ', $text);
}
public function testForWrongType() {
$tpl='messages: {{for $messages as $message}} from: $message.from to $message.to {{ endfor }}';
$text=replace_macros($tpl, array('$messages'=>11));
$this->assertEquals('messages: ', $text);
}
public function testForConditional() {
$tpl='new messages: {{for $messages as $message}}{{ if $message.new }} $message.text{{endif}}{{ endfor }}';
$text=replace_macros($tpl, array('$messages'=>array(
array('new'=>true, 'text'=>'new message'),
array('new'=>false, 'text'=>'old message'))));
$this->assertEquals('new messages: new message', $text);
}
public function testConditionalFor() {
$tpl='{{ if $enabled }}new messages:{{for $messages as $message}} $message.text{{ endfor }}{{endif}}';
$text=replace_macros($tpl, array('$enabled'=>true,
'$messages'=>array(
array('new'=>true, 'text'=>'new message'),
array('new'=>false, 'text'=>'old message'))));
$this->assertEquals('new messages: new message old message', $text);
}
public function testFantasy() {
$tpl='Fantasy: {{fantasy $messages}}';
$text=replace_macros($tpl, array('$messages'=>'no no'));
$this->assertEquals('Fantasy: {{fantasy no no}}', $text);
}
public function testInc() {
$tpl='{{inc field_input.tpl with $field=$myvar}}{{ endinc }}';
$text=replace_macros($tpl, array('$myvar'=>array('myfield', 'label', 'value', 'help')));
$this->assertEquals(" \n"
." <div class='field input'>\n"
." <label for='id_myfield'>label</label>\n"
." <input name='myfield' id='id_myfield' value=\"value\">\n"
." <span class='field_help'>help</span>\n"
." </div>\n", $text);
}
public function testIncNoVar() {
$tpl='{{inc field_input.tpl }}{{ endinc }}';
$text=replace_macros($tpl, array('$field'=>array('myfield', 'label', 'value', 'help')));
$this->assertEquals(" \n <div class='field input'>\n <label for='id_myfield'>label</label>\n"
." <input name='myfield' id='id_myfield' value=\"value\">\n"
." <span class='field_help'>help</span>\n"
." </div>\n", $text);
}
public function testDoubleUse() {
$tpl='Hello $name! {{ if $enabled }} I love you! {{ endif }}';
$text=replace_macros($tpl, array('$name'=>'Anna', '$enabled'=>false));
$this->assertEquals('Hello Anna! ', $text);
$tpl='Hey $name! {{ if $enabled }} I hate you! {{ endif }}';
$text=replace_macros($tpl, array('$name'=>'Max', '$enabled'=>true));
$this->assertEquals('Hey Max! I hate you! ', $text);
}
public function testIncDouble() {
$tpl='{{inc field_input.tpl with $field=$var1}}{{ endinc }}'
.'{{inc field_input.tpl with $field=$var2}}{{ endinc }}';
$text=replace_macros($tpl, array('$var1'=>array('myfield', 'label', 'value', 'help'),
'$var2'=>array('myfield2', 'label2', 'value2', 'help2')));
$this->assertEquals(" \n"
." <div class='field input'>\n"
." <label for='id_myfield'>label</label>\n"
." <input name='myfield' id='id_myfield' value=\"value\">\n"
." <span class='field_help'>help</span>\n"
." </div>\n"
." \n"
." <div class='field input'>\n"
." <label for='id_myfield2'>label2</label>\n"
." <input name='myfield2' id='id_myfield2' value=\"value2\">\n"
." <span class='field_help'>help2</span>\n"
." </div>\n", $text);
}
}

View file

@ -1,70 +0,0 @@
<?php
/**
* tests several functions which are used to prevent xss attacks
*
* @package test.util
*/
require_once('include/text.php');
class AntiXSSTest extends PHPUnit_Framework_TestCase {
/**
* test, that tags are escaped
*/
public function testEscapeTags() {
$invalidstring='<submit type="button" onclick="alert(\'failed!\');" />';
$validstring=notags($invalidstring);
$escapedString=escape_tags($invalidstring);
$this->assertEquals('[submit type="button" onclick="alert(\'failed!\');" /]', $validstring);
$this->assertEquals("&lt;submit type=&quot;button&quot; onclick=&quot;alert('failed!');&quot; /&gt;", $escapedString);
}
/**
*xmlify and unxmlify
*/
public function testXmlify() {
$text="<tag>I want to break\n this!11!<?hard?></tag>";
$xml=xmlify($text);
$retext=unxmlify($text);
$this->assertEquals($text, $retext);
}
/**
* xmlify and put in a document
*/
public function testXmlifyDocument() {
$tag="<tag>I want to break</tag>";
$xml=xmlify($tag);
$text='<text>'.$xml.'</text>';
$xml_parser=xml_parser_create();
//should be possible to parse it
$values=array(); $index=array();
$this->assertEquals(1, xml_parse_into_struct($xml_parser, $text, $values, $index));
$this->assertEquals(array('TEXT'=>array(0)),
$index);
$this->assertEquals(array(array('tag'=>'TEXT', 'type'=>'complete', 'level'=>1, 'value'=>$tag)),
$values);
xml_parser_free($xml_parser);
}
/**
* test hex2bin and reverse
*/
public function testHex2Bin() {
$this->assertEquals(-3, hex2bin(bin2hex(-3)));
$this->assertEquals(0, hex2bin(bin2hex(0)));
$this->assertEquals(12, hex2bin(bin2hex(12)));
$this->assertEquals(PHP_INT_MAX, hex2bin(bin2hex(PHP_INT_MAX)));
}
//function qp, quick and dirty??
//get_mentions
//get_contact_block, bis Zeile 538
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,72 @@ $a->strings["Weekly posting limit of %d post reached. The post was rejected."] =
]; ];
$a->strings["Monthly posting limit of %d post reached. The post was rejected."] = "De maandelijkse limiet van %d berichten is bereikt. Dit bericht werd niet aanvaard."; $a->strings["Monthly posting limit of %d post reached. The post was rejected."] = "De maandelijkse limiet van %d berichten is bereikt. Dit bericht werd niet aanvaard.";
$a->strings["Profile Photos"] = "Profielfoto's"; $a->strings["Profile Photos"] = "Profielfoto's";
$a->strings["Friendica Notification"] = "Friendica Notificatie";
$a->strings["Thank You,"] = "Bedankt";
$a->strings["%s Administrator"] = "%s Beheerder";
$a->strings["%1\$s, %2\$s Administrator"] = "%1\$s, %2\$s Beheerder";
$a->strings["noreply"] = "geen reactie";
$a->strings["[Friendica:Notify] New mail received at %s"] = "[Friendica:Notificatie] Nieuw bericht ontvangen op %s";
$a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$s sent you a new private message at %2\$s.";
$a->strings["a private message"] = "een prive bericht";
$a->strings["%1\$s sent you %2\$s."] = "%1\$s stuurde jou %2\$s.";
$a->strings["Please visit %s to view and/or reply to your private messages."] = "Bezoek %s om je privé-berichten te bekijken en/of te beantwoorden.";
$a->strings["%1\$s commented on [url=%2\$s]a %3\$s[/url]"] = "%1\$s gaf een reactie op [url=%2\$s]a %3\$s[/url]";
$a->strings["%1\$s commented on [url=%2\$s]%3\$s's %4\$s[/url]"] = "%1\$s gaf een reactie op [url=%2\$s]%3\$s's %4\$s[/url]";
$a->strings["%1\$s commented on [url=%2\$s]your %3\$s[/url]"] = "%1\$s gaf een reactie op [url=%2\$s]jouw %3\$s[/url]";
$a->strings["[Friendica:Notify] Comment to conversation #%1\$d by %2\$s"] = "[Friendica:Notificatie] Reactie op gesprek #%1\$d door %2\$s";
$a->strings["%s commented on an item/conversation you have been following."] = "%s gaf een reactie op een bericht/gesprek die jij volgt.";
$a->strings["Please visit %s to view and/or reply to the conversation."] = "Bezoek %s om het gesprek te bekijken en/of te beantwoorden.";
$a->strings["[Friendica:Notify] %s posted to your profile wall"] = "[Friendica:Melding] %s plaatste een bericht op je tijdlijn";
$a->strings["%1\$s posted to your profile wall at %2\$s"] = "%1\$splaatste een bericht op je tijdlijn op %2\$s";
$a->strings["%1\$s posted to [url=%2\$s]your wall[/url]"] = "%1\$s schreef op [url=%2\$s]jouw tijdlijn[/url]";
$a->strings["[Friendica:Notify] %s tagged you"] = "[Friendica:Notificatie] %s heeft jou genoemd";
$a->strings["%1\$s tagged you at %2\$s"] = "%1\$s heeft jou in %2\$s genoemd";
$a->strings["%1\$s [url=%2\$s]tagged you[/url]."] = "%1\$s [url=%2\$s]heeft jou genoemd[/url].";
$a->strings["[Friendica:Notify] %s shared a new post"] = "[Friendica:Melding] %s deelde een nieuw bericht";
$a->strings["%1\$s shared a new post at %2\$s"] = "%1\$s deelde een nieuw bericht op %2\$s";
$a->strings["%1\$s [url=%2\$s]shared a post[/url]."] = "%1\$s [url=%2\$s]deelde een bericht[/url].";
$a->strings["[Friendica:Notify] %1\$s poked you"] = "[Friendica:Melding] %1\$s heeft jou gepord";
$a->strings["%1\$s poked you at %2\$s"] = "%1\$s heeft jou gepord op %2\$s";
$a->strings["%1\$s [url=%2\$s]poked you[/url]."] = "%1\$s [url=%2\$s]porde jou[/url]";
$a->strings["[Friendica:Notify] %s tagged your post"] = "[Friendica:Notificatie] %s heeft jouw bericht gelabeld";
$a->strings["%1\$s tagged your post at %2\$s"] = "%1\$s heeft jouw bericht gelabeld in %2\$s";
$a->strings["%1\$s tagged [url=%2\$s]your post[/url]"] = "%1\$s labelde [url=%2\$s]jouw bericht[/url]";
$a->strings["[Friendica:Notify] Introduction received"] = "[Friendica:Notificatie] Vriendschaps-/connectieverzoek ontvangen";
$a->strings["You've received an introduction from '%1\$s' at %2\$s"] = "Je hebt een vriendschaps- of connectieverzoek ontvangen van '%1\$s' om %2\$s";
$a->strings["You've received [url=%1\$s]an introduction[/url] from %2\$s."] = "Je ontving [url=%1\$s]een vriendschaps- of connectieverzoek[/url] van %2\$s.";
$a->strings["You may visit their profile at %s"] = "U kunt hun profiel bezoeken op %s";
$a->strings["Please visit %s to approve or reject the introduction."] = "Bezoek %s om het verzoek goed of af te keuren.";
$a->strings["[Friendica:Notify] A new person is sharing with you"] = "[Friendica:Melding] Iemand nieuw deelt met jou.";
$a->strings["%1\$s is sharing with you at %2\$s"] = "%1\$s deelt met jouw in %2\$s";
$a->strings["[Friendica:Notify] You have a new follower"] = "[Friendica:Melding] Je hebt een nieuwe volger";
$a->strings["You have a new follower at %2\$s : %1\$s"] = "Je hebt een nieuwe volger op %2\$s: %1\$s";
$a->strings["[Friendica:Notify] Friend suggestion received"] = "[Friendica:Melding] Vriendschapsvoorstel ontvangen";
$a->strings["You've received a friend suggestion from '%1\$s' at %2\$s"] = "Je kreeg een vriendschapssuggestie van '%1\$s' op %2\$s";
$a->strings["You've received [url=%1\$s]a friend suggestion[/url] for %2\$s from %3\$s."] = "Je kreeg een [url=%1\$s]vriendschapssuggestie[/url] voor %2\$s op %3\$s.";
$a->strings["Name:"] = "Naam:";
$a->strings["Photo:"] = "Foto: ";
$a->strings["Please visit %s to approve or reject the suggestion."] = "Bezoek %s om de suggestie goed of af te keuren.";
$a->strings["[Friendica:Notify] Connection accepted"] = "[Friendica:Melding] Verbinding aanvaard";
$a->strings["'%1\$s' has accepted your connection request at %2\$s"] = "'%1\$s' aanvaarde je contactaanvraag op %2\$s";
$a->strings["%2\$s has accepted your [url=%1\$s]connection request[/url]."] = "%2\$saanvaarde jouw [url=%1\$s]contactaanvraag[/url].";
$a->strings["You are now mutual friends and may exchange status updates, photos, and email without restriction."] = "Jullie zijn nu in contact met elkaar en kunnen statusberichten, foto's en email delen zonder beperkingen.";
$a->strings["Please visit %s if you wish to make any changes to this relationship."] = "Bezoek alstublieft %s als je deze relatie wil wijzigen.";
$a->strings["'%1\$s' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically."] = "'%1\$s' koos om je te accepteren als fan, wat sommige communicatievormen beperkt - zoals privéberichten en sommige profielfuncties. Als dit een beroemdheid- of groepspagina is, werd dit automatisch toegepast.";
$a->strings["'%1\$s' may choose to extend this into a two-way or more permissive relationship in the future."] = "'%1\$s' kan er later voor kiezen om deze beperkingen aan te passen.";
$a->strings["Please visit %s if you wish to make any changes to this relationship."] = "Bezoek %s wanneer je deze relatie wil wijzigen.";
$a->strings["[Friendica System:Notify] registration request"] = "[Friendica System:Melding] Registratieaanvraag";
$a->strings["You've received a registration request from '%1\$s' at %2\$s"] = "Je kreeg een registratieaanvraag van '%1\$s' op %2\$s";
$a->strings["You've received a [url=%1\$s]registration request[/url] from %2\$s."] = "Je kreeg een [url=%1\$s]registratieaanvraag[/url] van %2\$s.";
$a->strings["Full Name:\t%1\$s\\nSite Location:\t%2\$s\\nLogin Name:\t%3\$s (%4\$s)"] = "Volledige naam:\t%1\$s\\nAdres van de site\t%2\$s\\nLoginnaam:\t%3\$s (%4\$s)";
$a->strings["Please visit %s to approve or reject the request."] = "Bezoek %s om de aanvraag goed of af te keuren.";
$a->strings["Item not found."] = "Item niet gevonden.";
$a->strings["Do you really want to delete this item?"] = "Wil je echt dit item verwijderen?";
$a->strings["Yes"] = "Ja";
$a->strings["Cancel"] = "Annuleren";
$a->strings["Permission denied."] = "Toegang geweigerd";
$a->strings["Archives"] = "Archieven";
$a->strings["show more"] = "toon meer";
$a->strings["event"] = "gebeurtenis"; $a->strings["event"] = "gebeurtenis";
$a->strings["status"] = "status"; $a->strings["status"] = "status";
$a->strings["photo"] = "foto"; $a->strings["photo"] = "foto";
@ -85,6 +151,7 @@ $a->strings["Tag term:"] = "Label:";
$a->strings["Save to Folder:"] = "Bewaren in map:"; $a->strings["Save to Folder:"] = "Bewaren in map:";
$a->strings["Where are you right now?"] = "Waar ben je nu?"; $a->strings["Where are you right now?"] = "Waar ben je nu?";
$a->strings["Delete item(s)?"] = "Item(s) verwijderen?"; $a->strings["Delete item(s)?"] = "Item(s) verwijderen?";
$a->strings["New Post"] = "Nieuw bericht";
$a->strings["Share"] = "Delen"; $a->strings["Share"] = "Delen";
$a->strings["Upload photo"] = "Foto uploaden"; $a->strings["Upload photo"] = "Foto uploaden";
$a->strings["upload photo"] = "Foto uploaden"; $a->strings["upload photo"] = "Foto uploaden";
@ -106,7 +173,6 @@ $a->strings["Permission settings"] = "Instellingen van rechten";
$a->strings["permissions"] = "rechten"; $a->strings["permissions"] = "rechten";
$a->strings["Public post"] = "Openbare post"; $a->strings["Public post"] = "Openbare post";
$a->strings["Preview"] = "Voorvertoning"; $a->strings["Preview"] = "Voorvertoning";
$a->strings["Cancel"] = "Annuleren";
$a->strings["Post to Groups"] = "Verzenden naar Groepen"; $a->strings["Post to Groups"] = "Verzenden naar Groepen";
$a->strings["Post to Contacts"] = "Verzenden naar Contacten"; $a->strings["Post to Contacts"] = "Verzenden naar Contacten";
$a->strings["Private post"] = "Privé verzending"; $a->strings["Private post"] = "Privé verzending";
@ -129,78 +195,13 @@ $a->strings["Undecided"] = [
0 => "Onbeslist", 0 => "Onbeslist",
1 => "Onbeslist", 1 => "Onbeslist",
]; ];
$a->strings["Friendica Notification"] = "Friendica Notificatie";
$a->strings["Thank You,"] = "Bedankt";
$a->strings["%s Administrator"] = "%s Beheerder";
$a->strings["%1\$s, %2\$s Administrator"] = "%1\$s, %2\$s Beheerder";
$a->strings["noreply"] = "geen reactie";
$a->strings["[Friendica:Notify] New mail received at %s"] = "[Friendica:Notificatie] Nieuw bericht ontvangen op %s";
$a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$s sent you a new private message at %2\$s.";
$a->strings["a private message"] = "een prive bericht";
$a->strings["%1\$s sent you %2\$s."] = "%1\$s stuurde jou %2\$s.";
$a->strings["Please visit %s to view and/or reply to your private messages."] = "Bezoek %s om je privé-berichten te bekijken en/of te beantwoorden.";
$a->strings["%1\$s commented on [url=%2\$s]a %3\$s[/url]"] = "%1\$s gaf een reactie op [url=%2\$s]a %3\$s[/url]";
$a->strings["%1\$s commented on [url=%2\$s]%3\$s's %4\$s[/url]"] = "%1\$s gaf een reactie op [url=%2\$s]%3\$s's %4\$s[/url]";
$a->strings["%1\$s commented on [url=%2\$s]your %3\$s[/url]"] = "%1\$s gaf een reactie op [url=%2\$s]jouw %3\$s[/url]";
$a->strings["[Friendica:Notify] Comment to conversation #%1\$d by %2\$s"] = "[Friendica:Notificatie] Reactie op gesprek #%1\$d door %2\$s";
$a->strings["%s commented on an item/conversation you have been following."] = "%s gaf een reactie op een bericht/gesprek die jij volgt.";
$a->strings["Please visit %s to view and/or reply to the conversation."] = "Bezoek %s om het gesprek te bekijken en/of te beantwoorden.";
$a->strings["[Friendica:Notify] %s posted to your profile wall"] = "[Friendica:Melding] %s plaatste een bericht op je tijdlijn";
$a->strings["%1\$s posted to your profile wall at %2\$s"] = "%1\$splaatste een bericht op je tijdlijn op %2\$s";
$a->strings["%1\$s posted to [url=%2\$s]your wall[/url]"] = "%1\$s schreef op [url=%2\$s]jouw tijdlijn[/url]";
$a->strings["[Friendica:Notify] %s tagged you"] = "[Friendica:Notificatie] %s heeft jou genoemd";
$a->strings["%1\$s tagged you at %2\$s"] = "%1\$s heeft jou in %2\$s genoemd";
$a->strings["%1\$s [url=%2\$s]tagged you[/url]."] = "%1\$s [url=%2\$s]heeft jou genoemd[/url].";
$a->strings["[Friendica:Notify] %s shared a new post"] = "[Friendica:Melding] %s deelde een nieuw bericht";
$a->strings["%1\$s shared a new post at %2\$s"] = "%1\$s deelde een nieuw bericht op %2\$s";
$a->strings["%1\$s [url=%2\$s]shared a post[/url]."] = "%1\$s [url=%2\$s]deelde een bericht[/url].";
$a->strings["[Friendica:Notify] %1\$s poked you"] = "[Friendica:Melding] %1\$s heeft jou gepord";
$a->strings["%1\$s poked you at %2\$s"] = "%1\$s heeft jou gepord op %2\$s";
$a->strings["%1\$s [url=%2\$s]poked you[/url]."] = "%1\$s [url=%2\$s]porde jou[/url]";
$a->strings["[Friendica:Notify] %s tagged your post"] = "[Friendica:Notificatie] %s heeft jouw bericht gelabeld";
$a->strings["%1\$s tagged your post at %2\$s"] = "%1\$s heeft jouw bericht gelabeld in %2\$s";
$a->strings["%1\$s tagged [url=%2\$s]your post[/url]"] = "%1\$s labelde [url=%2\$s]jouw bericht[/url]";
$a->strings["[Friendica:Notify] Introduction received"] = "[Friendica:Notificatie] Vriendschaps-/connectieverzoek ontvangen";
$a->strings["You've received an introduction from '%1\$s' at %2\$s"] = "Je hebt een vriendschaps- of connectieverzoek ontvangen van '%1\$s' om %2\$s";
$a->strings["You've received [url=%1\$s]an introduction[/url] from %2\$s."] = "Je ontving [url=%1\$s]een vriendschaps- of connectieverzoek[/url] van %2\$s.";
$a->strings["You may visit their profile at %s"] = "U kunt hun profiel bezoeken op %s";
$a->strings["Please visit %s to approve or reject the introduction."] = "Bezoek %s om het verzoek goed of af te keuren.";
$a->strings["[Friendica:Notify] A new person is sharing with you"] = "[Friendica:Melding] Iemand nieuw deelt met jou.";
$a->strings["%1\$s is sharing with you at %2\$s"] = "%1\$s deelt met jouw in %2\$s";
$a->strings["[Friendica:Notify] You have a new follower"] = "[Friendica:Melding] Je hebt een nieuwe volger";
$a->strings["You have a new follower at %2\$s : %1\$s"] = "Je hebt een nieuwe volger op %2\$s: %1\$s";
$a->strings["[Friendica:Notify] Friend suggestion received"] = "[Friendica:Melding] Vriendschapsvoorstel ontvangen";
$a->strings["You've received a friend suggestion from '%1\$s' at %2\$s"] = "Je kreeg een vriendschapssuggestie van '%1\$s' op %2\$s";
$a->strings["You've received [url=%1\$s]a friend suggestion[/url] for %2\$s from %3\$s."] = "Je kreeg een [url=%1\$s]vriendschapssuggestie[/url] voor %2\$s op %3\$s.";
$a->strings["Name:"] = "Naam:";
$a->strings["Photo:"] = "Foto: ";
$a->strings["Please visit %s to approve or reject the suggestion."] = "Bezoek %s om de suggestie goed of af te keuren.";
$a->strings["[Friendica:Notify] Connection accepted"] = "[Friendica:Melding] Verbinding aanvaard";
$a->strings["'%1\$s' has accepted your connection request at %2\$s"] = "'%1\$s' aanvaarde je contactaanvraag op %2\$s";
$a->strings["%2\$s has accepted your [url=%1\$s]connection request[/url]."] = "%2\$saanvaarde jouw [url=%1\$s]contactaanvraag[/url].";
$a->strings["You are now mutual friends and may exchange status updates, photos, and email without restriction."] = "Jullie zijn nu in contact met elkaar en kunnen statusberichten, foto's en email delen zonder beperkingen.";
$a->strings["Please visit %s if you wish to make any changes to this relationship."] = "Bezoek alstublieft %s als je deze relatie wil wijzigen.";
$a->strings["'%1\$s' has chosen to accept you a fan, which restricts some forms of communication - such as private messaging and some profile interactions. If this is a celebrity or community page, these settings were applied automatically."] = "'%1\$s' koos om je te accepteren als fan, wat sommige communicatievormen beperkt - zoals privéberichten en sommige profielfuncties. Als dit een beroemdheid- of groepspagina is, werd dit automatisch toegepast.";
$a->strings["'%1\$s' may choose to extend this into a two-way or more permissive relationship in the future."] = "'%1\$s' kan er later voor kiezen om deze beperkingen aan te passen.";
$a->strings["Please visit %s if you wish to make any changes to this relationship."] = "Bezoek %s wanneer je deze relatie wil wijzigen.";
$a->strings["[Friendica System:Notify] registration request"] = "[Friendica System:Melding] Registratieaanvraag";
$a->strings["You've received a registration request from '%1\$s' at %2\$s"] = "Je kreeg een registratieaanvraag van '%1\$s' op %2\$s";
$a->strings["You've received a [url=%1\$s]registration request[/url] from %2\$s."] = "Je kreeg een [url=%1\$s]registratieaanvraag[/url] van %2\$s.";
$a->strings["Full Name:\t%1\$s\\nSite Location:\t%2\$s\\nLogin Name:\t%3\$s (%4\$s)"] = "Volledige naam:\t%1\$s\\nAdres van de site\t%2\$s\\nLoginnaam:\t%3\$s (%4\$s)";
$a->strings["Please visit %s to approve or reject the request."] = "Bezoek %s om de aanvraag goed of af te keuren.";
$a->strings["Item not found."] = "Item niet gevonden.";
$a->strings["Do you really want to delete this item?"] = "Wil je echt dit item verwijderen?";
$a->strings["Yes"] = "Ja";
$a->strings["Permission denied."] = "Toegang geweigerd";
$a->strings["Archives"] = "Archieven";
$a->strings["show more"] = "toon meer";
$a->strings["newer"] = "nieuwere berichten"; $a->strings["newer"] = "nieuwere berichten";
$a->strings["older"] = "oudere berichten"; $a->strings["older"] = "oudere berichten";
$a->strings["first"] = "eerste"; $a->strings["first"] = "eerste";
$a->strings["prev"] = "vorige"; $a->strings["prev"] = "vorige";
$a->strings["next"] = "volgende"; $a->strings["next"] = "volgende";
$a->strings["last"] = "laatste"; $a->strings["last"] = "laatste";
$a->strings["Loading more entries..."] = ""; $a->strings["Loading more entries..."] = "Meer berichten aan het laden...";
$a->strings["The end"] = "Het einde"; $a->strings["The end"] = "Het einde";
$a->strings["No contacts"] = "Geen contacten"; $a->strings["No contacts"] = "Geen contacten";
$a->strings["%d Contact"] = [ $a->strings["%d Contact"] = [
@ -264,6 +265,7 @@ $a->strings["Sep"] = "Sep";
$a->strings["Oct"] = "Okt"; $a->strings["Oct"] = "Okt";
$a->strings["Nov"] = "Nov"; $a->strings["Nov"] = "Nov";
$a->strings["Dec"] = "Dec"; $a->strings["Dec"] = "Dec";
$a->strings["Content warning: %s"] = "Waarschuwing inhoud: %s";
$a->strings["View Video"] = "Bekijk Video"; $a->strings["View Video"] = "Bekijk Video";
$a->strings["bytes"] = "bytes"; $a->strings["bytes"] = "bytes";
$a->strings["Click to open/close"] = "klik om te openen/sluiten"; $a->strings["Click to open/close"] = "klik om te openen/sluiten";
@ -291,12 +293,12 @@ $a->strings["Item not available."] = "Item niet beschikbaar";
$a->strings["Item was not found."] = "Item niet gevonden"; $a->strings["Item was not found."] = "Item niet gevonden";
$a->strings["No contacts in common."] = "Geen gedeelde contacten."; $a->strings["No contacts in common."] = "Geen gedeelde contacten.";
$a->strings["Common Friends"] = "Gedeelde Vrienden"; $a->strings["Common Friends"] = "Gedeelde Vrienden";
$a->strings["Credits"] = ""; $a->strings["Credits"] = "Credits";
$a->strings["Friendica is a community project, that would not be possible without the help of many people. Here is a list of those who have contributed to the code or the translation of Friendica. Thank you all!"] = ""; $a->strings["Friendica is a community project, that would not be possible without the help of many people. Here is a list of those who have contributed to the code or the translation of Friendica. Thank you all!"] = "Friendica is een gemeenschapsproject dat niet mogelijk zou zijn zonder de hulp van vele mensen. Hier is een lijst van alle mensen die aan de code of vertalingen van Friendica hebben meegewerkt. Allen van harte bedankt!";
$a->strings["Contact settings applied."] = "Contactinstellingen toegepast."; $a->strings["Contact settings applied."] = "Contactinstellingen toegepast.";
$a->strings["Contact update failed."] = "Aanpassen van contact mislukt."; $a->strings["Contact update failed."] = "Aanpassen van contact mislukt.";
$a->strings["Contact not found."] = "Contact niet gevonden"; $a->strings["Contact not found."] = "Contact niet gevonden";
$a->strings["<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working."] = ""; $a->strings["<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working."] = "<strong>WAARSCHUWING: Dit is zeer geavanceerd</strong> en als je verkeerde informatie invult, zal je mogelijk niet meer kunnen communiceren met deze contactpersoon.";
$a->strings["Please use your browser 'Back' button <strong>now</strong> if you are uncertain what to do on this page."] = "Gebruik <strong>nu</strong> de \"terug\"-knop in je webbrowser wanneer je niet weet wat je op deze pagina moet doen."; $a->strings["Please use your browser 'Back' button <strong>now</strong> if you are uncertain what to do on this page."] = "Gebruik <strong>nu</strong> de \"terug\"-knop in je webbrowser wanneer je niet weet wat je op deze pagina moet doen.";
$a->strings["No mirroring"] = ""; $a->strings["No mirroring"] = "";
$a->strings["Mirror as forwarded posting"] = ""; $a->strings["Mirror as forwarded posting"] = "";
@ -368,7 +370,7 @@ $a->strings["Edit contact"] = "Contact bewerken";
$a->strings["Contacts who are not members of a group"] = "Contacten die geen leden zijn van een groep"; $a->strings["Contacts who are not members of a group"] = "Contacten die geen leden zijn van een groep";
$a->strings["Not Extended"] = ""; $a->strings["Not Extended"] = "";
$a->strings["Resubscribing to OStatus contacts"] = ""; $a->strings["Resubscribing to OStatus contacts"] = "";
$a->strings["Error"] = ""; $a->strings["Error"] = "Fout";
$a->strings["Done"] = "Klaar"; $a->strings["Done"] = "Klaar";
$a->strings["Keep this window open until done."] = "Houd dit scherm open tot het klaar is"; $a->strings["Keep this window open until done."] = "Houd dit scherm open tot het klaar is";
$a->strings["Do you really want to delete this suggestion?"] = "Wil je echt dit voorstel verwijderen?"; $a->strings["Do you really want to delete this suggestion?"] = "Wil je echt dit voorstel verwijderen?";
@ -777,7 +779,7 @@ $a->strings["Set the default language for your Friendica installation interface
$a->strings["Could not find a command line version of PHP in the web server PATH."] = "Kan geen command-line-versie van PHP vinden in het PATH van de webserver."; $a->strings["Could not find a command line version of PHP in the web server PATH."] = "Kan geen command-line-versie van PHP vinden in het PATH van de webserver.";
$a->strings["If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>"] = ""; $a->strings["If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>"] = "";
$a->strings["PHP executable path"] = "PATH van het PHP commando"; $a->strings["PHP executable path"] = "PATH van het PHP commando";
$a->strings["Enter full path to php executable. You can leave this blank to continue the installation."] = "Vul het volledige path in naar het php programma. Je kunt dit blanco laten om de installatie verder te zetten."; $a->strings["Enter full path to php executable. You can leave this blank to continue the installation."] = "Vul het volledige pad in naar het php programma. Je kunt dit leeg laten om de installatie verder te zetten.";
$a->strings["Command line PHP"] = "PHP-opdrachtregel"; $a->strings["Command line PHP"] = "PHP-opdrachtregel";
$a->strings["PHP executable is not the php cli binary (could be cgi-fgci version)"] = ""; $a->strings["PHP executable is not the php cli binary (could be cgi-fgci version)"] = "";
$a->strings["Found PHP version: "] = "Gevonden PHP versie:"; $a->strings["Found PHP version: "] = "Gevonden PHP versie:";
@ -881,209 +883,6 @@ $a->strings["Crop Image"] = "Afbeelding bijsnijden";
$a->strings["Please adjust the image cropping for optimum viewing."] = "Pas het afsnijden van de afbeelding aan voor het beste resultaat."; $a->strings["Please adjust the image cropping for optimum viewing."] = "Pas het afsnijden van de afbeelding aan voor het beste resultaat.";
$a->strings["Done Editing"] = "Wijzigingen compleet"; $a->strings["Done Editing"] = "Wijzigingen compleet";
$a->strings["Image uploaded successfully."] = "Uploaden van afbeelding gelukt."; $a->strings["Image uploaded successfully."] = "Uploaden van afbeelding gelukt.";
$a->strings["Account"] = "Account";
$a->strings["Additional features"] = "Extra functies";
$a->strings["Display"] = "Weergave";
$a->strings["Social Networks"] = "Sociale netwerken";
$a->strings["Addons"] = "";
$a->strings["Delegations"] = "";
$a->strings["Connected apps"] = "Verbonden applicaties";
$a->strings["Remove account"] = "Account verwijderen";
$a->strings["Missing some important data!"] = "Een belangrijk gegeven ontbreekt!";
$a->strings["Update"] = "Wijzigen";
$a->strings["Failed to connect with email account using the settings provided."] = "Ik kon geen verbinding maken met het e-mail account met de gegeven instellingen.";
$a->strings["Email settings updated."] = "E-mail instellingen bijgewerkt..";
$a->strings["Features updated"] = "Functies bijgewerkt";
$a->strings["Relocate message has been send to your contacts"] = "";
$a->strings["Passwords do not match. Password unchanged."] = "Wachtwoorden komen niet overeen. Wachtwoord niet gewijzigd.";
$a->strings["Empty passwords are not allowed. Password unchanged."] = "Lege wachtwoorden zijn niet toegelaten. Wachtwoord niet gewijzigd.";
$a->strings["The new password has been exposed in a public data dump, please choose another."] = "";
$a->strings["Wrong password."] = "Verkeerd wachtwoord.";
$a->strings["Password changed."] = "Wachtwoord gewijzigd.";
$a->strings["Password update failed. Please try again."] = "Wachtwoord-)wijziging mislukt. Probeer opnieuw.";
$a->strings[" Please use a shorter name."] = "Gebruik een kortere naam.";
$a->strings[" Name too short."] = "Naam te kort.";
$a->strings["Wrong Password"] = "Verkeerd wachtwoord";
$a->strings["Invalid email."] = "";
$a->strings["Cannot change to that email."] = "";
$a->strings["Private forum has no privacy permissions. Using default privacy group."] = "Privéforum/-groep heeft geen privacyrechten. De standaard privacygroep wordt gebruikt.";
$a->strings["Private forum has no privacy permissions and no default privacy group."] = "Privéforum/-groep heeft geen privacyrechten en geen standaard privacygroep.";
$a->strings["Settings updated."] = "Instellingen bijgewerkt.";
$a->strings["Add application"] = "Toepassing toevoegen";
$a->strings["Consumer Key"] = "Gebruikerssleutel";
$a->strings["Consumer Secret"] = "Gebruikersgeheim";
$a->strings["Redirect"] = "Doorverwijzing";
$a->strings["Icon url"] = "URL pictogram";
$a->strings["You can't edit this application."] = "Je kunt deze toepassing niet wijzigen.";
$a->strings["Connected Apps"] = "Verbonden applicaties";
$a->strings["Edit"] = "Bewerken";
$a->strings["Client key starts with"] = "";
$a->strings["No name"] = "Geen naam";
$a->strings["Remove authorization"] = "Verwijder authorisatie";
$a->strings["No Addon settings configured"] = "";
$a->strings["Addon Settings"] = "";
$a->strings["Off"] = "Uit";
$a->strings["On"] = "Aan";
$a->strings["Additional Features"] = "Extra functies";
$a->strings["Diaspora"] = "Diaspora";
$a->strings["enabled"] = "ingeschakeld";
$a->strings["disabled"] = "uitgeschakeld";
$a->strings["Built-in support for %s connectivity is %s"] = "Ingebouwde ondersteuning voor connectiviteit met %s is %s";
$a->strings["GNU Social (OStatus)"] = "";
$a->strings["Email access is disabled on this site."] = "E-mailtoegang is op deze website uitgeschakeld.";
$a->strings["General Social Media Settings"] = "";
$a->strings["Disable intelligent shortening"] = "";
$a->strings["Normally the system tries to find the best link to add to shortened posts. If this option is enabled then every shortened post will always point to the original friendica post."] = "";
$a->strings["Automatically follow any GNU Social (OStatus) followers/mentioners"] = "";
$a->strings["If you receive a message from an unknown OStatus user, this option decides what to do. If it is checked, a new contact will be created for every unknown user."] = "";
$a->strings["Default group for OStatus contacts"] = "";
$a->strings["Your legacy GNU Social account"] = "";
$a->strings["If you enter your old GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done."] = "";
$a->strings["Repair OStatus subscriptions"] = "";
$a->strings["Email/Mailbox Setup"] = "E-mail Instellen";
$a->strings["If you wish to communicate with email contacts using this service (optional), please specify how to connect to your mailbox."] = "Als je wilt communiceren met e-mail contacten via deze dienst (optioneel), moet je hier opgeven hoe ik jouw mailbox kan bereiken.";
$a->strings["Last successful email check:"] = "Laatste succesvolle e-mail controle:";
$a->strings["IMAP server name:"] = "IMAP server naam:";
$a->strings["IMAP port:"] = "IMAP poort:";
$a->strings["Security:"] = "Beveiliging:";
$a->strings["None"] = "Geen";
$a->strings["Email login name:"] = "E-mail login naam:";
$a->strings["Email password:"] = "E-mail wachtwoord:";
$a->strings["Reply-to address:"] = "Antwoord adres:";
$a->strings["Send public posts to all email contacts:"] = "Openbare posts naar alle e-mail contacten versturen:";
$a->strings["Action after import:"] = "Actie na importeren:";
$a->strings["Mark as seen"] = "Als 'gelezen' markeren";
$a->strings["Move to folder"] = "Naar map verplaatsen";
$a->strings["Move to folder:"] = "Verplaatsen naar map:";
$a->strings["No special theme for mobile devices"] = "Geen speciaal thema voor mobiele apparaten";
$a->strings["%s - (Unsupported)"] = "";
$a->strings["%s - (Experimental)"] = "";
$a->strings["Display Settings"] = "Scherminstellingen";
$a->strings["Display Theme:"] = "Schermthema:";
$a->strings["Mobile Theme:"] = "Mobiel thema:";
$a->strings["Suppress warning of insecure networks"] = "";
$a->strings["Should the system suppress the warning that the current group contains members of networks that can't receive non public postings."] = "";
$a->strings["Update browser every xx seconds"] = "Browser elke xx seconden verversen";
$a->strings["Minimum of 10 seconds. Enter -1 to disable it."] = "";
$a->strings["Number of items to display per page:"] = "Aantal items te tonen per pagina:";
$a->strings["Maximum of 100 items"] = "Maximum 100 items";
$a->strings["Number of items to display per page when viewed from mobile device:"] = "Aantal items per pagina als je een mobiel toestel gebruikt:";
$a->strings["Don't show emoticons"] = "Emoticons niet tonen";
$a->strings["Calendar"] = "";
$a->strings["Beginning of week:"] = "";
$a->strings["Don't show notices"] = "";
$a->strings["Infinite scroll"] = "Oneindig scrollen";
$a->strings["Automatic updates only at the top of the network page"] = "";
$a->strings["When disabled, the network page is updated all the time, which could be confusing while reading."] = "";
$a->strings["Bandwith Saver Mode"] = "";
$a->strings["When enabled, embedded content is not displayed on automatic updates, they only show on page reload."] = "";
$a->strings["Smart Threading"] = "";
$a->strings["When enabled, suppress extraneous thread indentation while keeping it where it matters. Only works if threading is available and enabled."] = "";
$a->strings["General Theme Settings"] = "";
$a->strings["Custom Theme Settings"] = "";
$a->strings["Content Settings"] = "";
$a->strings["Theme settings"] = "Thema-instellingen";
$a->strings["Unable to find your profile. Please contact your admin."] = "";
$a->strings["Account Types"] = "";
$a->strings["Personal Page Subtypes"] = "";
$a->strings["Community Forum Subtypes"] = "";
$a->strings["Personal Page"] = "";
$a->strings["Account for a personal profile."] = "";
$a->strings["Organisation Page"] = "";
$a->strings["Account for an organisation that automatically approves contact requests as \"Followers\"."] = "";
$a->strings["News Page"] = "";
$a->strings["Account for a news reflector that automatically approves contact requests as \"Followers\"."] = "";
$a->strings["Community Forum"] = "";
$a->strings["Account for community discussions."] = "";
$a->strings["Normal Account Page"] = "Normale accountpagina";
$a->strings["Account for a regular personal profile that requires manual approval of \"Friends\" and \"Followers\"."] = "";
$a->strings["Soapbox Page"] = "Zeepkist-pagina";
$a->strings["Account for a public profile that automatically approves contact requests as \"Followers\"."] = "";
$a->strings["Public Forum"] = "";
$a->strings["Automatically approves all contact requests."] = "";
$a->strings["Automatic Friend Page"] = "Automatisch Vriendschapspagina";
$a->strings["Account for a popular profile that automatically approves contact requests as \"Friends\"."] = "";
$a->strings["Private Forum [Experimental]"] = "Privé-forum [experimenteel]";
$a->strings["Requires manual approval of contact requests."] = "";
$a->strings["OpenID:"] = "OpenID:";
$a->strings["(Optional) Allow this OpenID to login to this account."] = "(Optioneel) Laat dit OpenID toe om in te loggen op deze account.";
$a->strings["Publish your default profile in your local site directory?"] = "Je standaardprofiel in je lokale gids publiceren?";
$a->strings["Your profile will be published in the global friendica directories (e.g. <a href=\"%s\">%s</a>). Your profile will be visible in public."] = "";
$a->strings["Publish your default profile in the global social directory?"] = "Je standaardprofiel in de globale sociale gids publiceren?";
$a->strings["Your profile will be published in this node's <a href=\"%s\">local directory</a>. Your profile details may be publicly visible depending on the system settings."] = "";
$a->strings["Hide your contact/friend list from viewers of your default profile?"] = "Je vrienden/contacten verbergen voor bezoekers van je standaard profiel?";
$a->strings["Your contact list won't be shown in your default profile page. You can decide to show your contact list separately for each additional profile you create"] = "";
$a->strings["Hide your profile details from anonymous viewers?"] = "";
$a->strings["Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Disables posting public messages to Diaspora and other networks."] = "";
$a->strings["Allow friends to post to your profile page?"] = "Vrienden toestaan om op jou profielpagina te posten?";
$a->strings["Your contacts may write posts on your profile wall. These posts will be distributed to your contacts"] = "";
$a->strings["Allow friends to tag your posts?"] = "Sta vrienden toe om jouw berichten te labelen?";
$a->strings["Your contacts can add additional tags to your posts."] = "";
$a->strings["Allow us to suggest you as a potential friend to new members?"] = "Sta je mij toe om jou als mogelijke vriend voor te stellen aan nieuwe leden?";
$a->strings["If you like, Friendica may suggest new members to add you as a contact."] = "";
$a->strings["Permit unknown people to send you private mail?"] = "Mogen onbekende personen jou privé berichten sturen?";
$a->strings["Friendica network users may send you private messages even if they are not in your contact list."] = "";
$a->strings["Profile is <strong>not published</strong>."] = "Profiel is <strong>niet gepubliceerd</strong>.";
$a->strings["Your Identity Address is <strong>'%s'</strong> or '%s'."] = "";
$a->strings["Automatically expire posts after this many days:"] = "Laat berichten automatisch vervallen na zo veel dagen:";
$a->strings["If empty, posts will not expire. Expired posts will be deleted"] = "Berichten zullen niet vervallen indien leeg. Vervallen berichten zullen worden verwijderd.";
$a->strings["Advanced expiration settings"] = "Geavanceerde instellingen voor vervallen";
$a->strings["Advanced Expiration"] = "Geavanceerd Verval:";
$a->strings["Expire posts:"] = "Laat berichten vervallen:";
$a->strings["Expire personal notes:"] = "Laat persoonlijke aantekeningen verlopen:";
$a->strings["Expire starred posts:"] = "Laat berichten met ster verlopen";
$a->strings["Expire photos:"] = "Laat foto's vervallen:";
$a->strings["Only expire posts by others:"] = "Laat alleen berichten door anderen vervallen:";
$a->strings["Account Settings"] = "Account Instellingen";
$a->strings["Password Settings"] = "Wachtwoord Instellingen";
$a->strings["New Password:"] = "Nieuw Wachtwoord:";
$a->strings["Confirm:"] = "Bevestig:";
$a->strings["Leave password fields blank unless changing"] = "Laat de wachtwoord-velden leeg, tenzij je het wilt veranderen";
$a->strings["Current Password:"] = "Huidig wachtwoord:";
$a->strings["Your current password to confirm the changes"] = "Je huidig wachtwoord om de wijzigingen te bevestigen";
$a->strings["Password:"] = "Wachtwoord:";
$a->strings["Basic Settings"] = "Basis Instellingen";
$a->strings["Full Name:"] = "Volledige Naam:";
$a->strings["Email Address:"] = "E-mailadres:";
$a->strings["Your Timezone:"] = "Je Tijdzone:";
$a->strings["Your Language:"] = "";
$a->strings["Set the language we use to show you friendica interface and to send you emails"] = "";
$a->strings["Default Post Location:"] = "Standaard locatie:";
$a->strings["Use Browser Location:"] = "Gebruik Webbrowser Locatie:";
$a->strings["Security and Privacy Settings"] = "Instellingen voor Beveiliging en Privacy";
$a->strings["Maximum Friend Requests/Day:"] = "Maximum aantal vriendschapsverzoeken per dag:";
$a->strings["(to prevent spam abuse)"] = "(om spam misbruik te voorkomen)";
$a->strings["Default Post Permissions"] = "Standaard rechten voor nieuwe berichten";
$a->strings["(click to open/close)"] = "(klik om te openen/sluiten)";
$a->strings["Default Private Post"] = "Standaard Privé Post";
$a->strings["Default Public Post"] = "Standaard Publieke Post";
$a->strings["Default Permissions for New Posts"] = "Standaard rechten voor nieuwe berichten";
$a->strings["Maximum private messages per day from unknown people:"] = "Maximum aantal privé-berichten per dag van onbekende personen:";
$a->strings["Notification Settings"] = "Notificatie Instellingen";
$a->strings["By default post a status message when:"] = "Post automatisch een bericht op je tijdlijn wanneer:";
$a->strings["accepting a friend request"] = "Een vriendschapsverzoek accepteren";
$a->strings["joining a forum/community"] = "Lid worden van een groep/forum";
$a->strings["making an <em>interesting</em> profile change"] = "Een <em>interessante</em> verandering aan je profiel";
$a->strings["Send a notification email when:"] = "Stuur een notificatie e-mail wanneer:";
$a->strings["You receive an introduction"] = "Je ontvangt een vriendschaps- of connectieverzoek";
$a->strings["Your introductions are confirmed"] = "Jouw vriendschaps- of connectieverzoeken zijn bevestigd";
$a->strings["Someone writes on your profile wall"] = "Iemand iets op je tijdlijn schrijft";
$a->strings["Someone writes a followup comment"] = "Iemand een reactie schrijft";
$a->strings["You receive a private message"] = "Je een privé-bericht ontvangt";
$a->strings["You receive a friend suggestion"] = "Je een suggestie voor een vriendschap ontvangt";
$a->strings["You are tagged in a post"] = "Je expliciet in een bericht bent genoemd";
$a->strings["You are poked/prodded/etc. in a post"] = "Je in een bericht bent aangestoten/gepord/etc.";
$a->strings["Activate desktop notifications"] = "";
$a->strings["Show desktop popup on new notifications"] = "";
$a->strings["Text-only notification emails"] = "";
$a->strings["Send text only notification emails, without the html part"] = "";
$a->strings["Show detailled notifications"] = "";
$a->strings["Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed."] = "";
$a->strings["Advanced Account/Page Type Settings"] = "";
$a->strings["Change the behaviour of this account for special situations"] = "";
$a->strings["Relocate"] = "";
$a->strings["If you have moved this profile from another server, and some of your contacts don't receive your updates, try pushing this button."] = "";
$a->strings["Resend relocate message to contacts"] = "";
$a->strings["Status:"] = "Tijdlijn:"; $a->strings["Status:"] = "Tijdlijn:";
$a->strings["Homepage:"] = "Website:"; $a->strings["Homepage:"] = "Website:";
$a->strings["Global Directory"] = "Globale gids"; $a->strings["Global Directory"] = "Globale gids";
@ -1275,6 +1074,7 @@ $a->strings["Only show archived contacts"] = "Toon alleen gearchiveerde contacte
$a->strings["Hidden"] = "Verborgen"; $a->strings["Hidden"] = "Verborgen";
$a->strings["Only show hidden contacts"] = "Toon alleen verborgen contacten"; $a->strings["Only show hidden contacts"] = "Toon alleen verborgen contacten";
$a->strings["Search your contacts"] = "Doorzoek je contacten"; $a->strings["Search your contacts"] = "Doorzoek je contacten";
$a->strings["Update"] = "Wijzigen";
$a->strings["Archive"] = "Archiveer"; $a->strings["Archive"] = "Archiveer";
$a->strings["Unarchive"] = "Archiveer niet meer"; $a->strings["Unarchive"] = "Archiveer niet meer";
$a->strings["Batch Actions"] = ""; $a->strings["Batch Actions"] = "";
@ -1340,7 +1140,9 @@ $a->strings["Your invitation code: "] = "";
$a->strings["Registration"] = "Registratie"; $a->strings["Registration"] = "Registratie";
$a->strings["Your Full Name (e.g. Joe Smith, real or real-looking): "] = ""; $a->strings["Your Full Name (e.g. Joe Smith, real or real-looking): "] = "";
$a->strings["Your Email Address: (Initial information will be send there, so this has to be an existing address.)"] = ""; $a->strings["Your Email Address: (Initial information will be send there, so this has to be an existing address.)"] = "";
$a->strings["New Password:"] = "Nieuw Wachtwoord:";
$a->strings["Leave empty for an auto generated password."] = ""; $a->strings["Leave empty for an auto generated password."] = "";
$a->strings["Confirm:"] = "Bevestig:";
$a->strings["Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be '<strong>nickname@%s</strong>'."] = ""; $a->strings["Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be '<strong>nickname@%s</strong>'."] = "";
$a->strings["Choose a nickname: "] = "Kies een bijnaam:"; $a->strings["Choose a nickname: "] = "Kies een bijnaam:";
$a->strings["Register"] = "Registreer"; $a->strings["Register"] = "Registreer";
@ -1352,7 +1154,9 @@ $a->strings["Federation Statistics"] = "";
$a->strings["Configuration"] = ""; $a->strings["Configuration"] = "";
$a->strings["Site"] = "Website"; $a->strings["Site"] = "Website";
$a->strings["Users"] = "Gebruiker"; $a->strings["Users"] = "Gebruiker";
$a->strings["Addons"] = "";
$a->strings["Themes"] = "Thema's"; $a->strings["Themes"] = "Thema's";
$a->strings["Additional features"] = "Extra functies";
$a->strings["Database"] = ""; $a->strings["Database"] = "";
$a->strings["DB updates"] = "DB aanpassingen"; $a->strings["DB updates"] = "DB aanpassingen";
$a->strings["Inspect Queue"] = ""; $a->strings["Inspect Queue"] = "";
@ -1449,6 +1253,7 @@ $a->strings["Version"] = "Versie";
$a->strings["Active addons"] = ""; $a->strings["Active addons"] = "";
$a->strings["Can not parse base url. Must have at least <scheme>://<domain>"] = ""; $a->strings["Can not parse base url. Must have at least <scheme>://<domain>"] = "";
$a->strings["Site settings updated."] = "Site instellingen gewijzigd."; $a->strings["Site settings updated."] = "Site instellingen gewijzigd.";
$a->strings["No special theme for mobile devices"] = "Geen speciaal thema voor mobiele apparaten";
$a->strings["No community page"] = ""; $a->strings["No community page"] = "";
$a->strings["Public postings from users of this site"] = ""; $a->strings["Public postings from users of this site"] = "";
$a->strings["Public postings from the federated network"] = ""; $a->strings["Public postings from the federated network"] = "";
@ -1484,7 +1289,7 @@ $a->strings["The email address your server shall use to send notification emails
$a->strings["Banner/Logo"] = "Banner/Logo"; $a->strings["Banner/Logo"] = "Banner/Logo";
$a->strings["Shortcut icon"] = ""; $a->strings["Shortcut icon"] = "";
$a->strings["Link to an icon that will be used for browsers."] = ""; $a->strings["Link to an icon that will be used for browsers."] = "";
$a->strings["Touch icon"] = ""; $a->strings["Touch icon"] = "Pictogram voor smartphones";
$a->strings["Link to an icon that will be used for tablets and mobiles."] = ""; $a->strings["Link to an icon that will be used for tablets and mobiles."] = "";
$a->strings["Additional Info"] = ""; $a->strings["Additional Info"] = "";
$a->strings["For public servers: you can add additional information here that will be listed at %s/servers."] = ""; $a->strings["For public servers: you can add additional information here that will be listed at %s/servers."] = "";
@ -1638,9 +1443,9 @@ $a->strings["Executing %s failed with error: %s"] = "";
$a->strings["Update %s was successfully applied."] = "Wijziging %s geslaagd."; $a->strings["Update %s was successfully applied."] = "Wijziging %s geslaagd.";
$a->strings["Update %s did not return a status. Unknown if it succeeded."] = "Wijziging %s gaf geen status terug. We weten niet of de wijziging geslaagd is."; $a->strings["Update %s did not return a status. Unknown if it succeeded."] = "Wijziging %s gaf geen status terug. We weten niet of de wijziging geslaagd is.";
$a->strings["There was no additional update function %s that needed to be called."] = ""; $a->strings["There was no additional update function %s that needed to be called."] = "";
$a->strings["No failed updates."] = "Geen misluke wijzigingen"; $a->strings["No failed updates."] = "Geen mislukte wijzigingen";
$a->strings["Check database structure"] = ""; $a->strings["Check database structure"] = "";
$a->strings["Failed Updates"] = "Misluke wijzigingen"; $a->strings["Failed Updates"] = "Mislukte wijzigingen";
$a->strings["This does not include updates prior to 1139, which did not return a status."] = "Dit is zonder de wijzigingen voor 1139, welke geen status teruggaven."; $a->strings["This does not include updates prior to 1139, which did not return a status."] = "Dit is zonder de wijzigingen voor 1139, welke geen status teruggaven.";
$a->strings["Mark success (if update was manually applied)"] = "Markeren als succes (als aanpassing manueel doorgevoerd werd)"; $a->strings["Mark success (if update was manually applied)"] = "Markeren als succes (als aanpassing manueel doorgevoerd werd)";
$a->strings["Attempt to execute this update step automatically"] = "Probeer deze stap automatisch uit te voeren"; $a->strings["Attempt to execute this update step automatically"] = "Probeer deze stap automatisch uit te voeren";
@ -1662,6 +1467,7 @@ $a->strings["Email"] = "E-mail";
$a->strings["Register date"] = "Registratiedatum"; $a->strings["Register date"] = "Registratiedatum";
$a->strings["Last login"] = "Laatste login"; $a->strings["Last login"] = "Laatste login";
$a->strings["Last item"] = "Laatste item"; $a->strings["Last item"] = "Laatste item";
$a->strings["Account"] = "Account";
$a->strings["Add User"] = "Gebruiker toevoegen"; $a->strings["Add User"] = "Gebruiker toevoegen";
$a->strings["User registrations waiting for confirm"] = "Gebruikersregistraties wachten op een bevestiging"; $a->strings["User registrations waiting for confirm"] = "Gebruikersregistraties wachten op een bevestiging";
$a->strings["User waiting for permanent deletion"] = ""; $a->strings["User waiting for permanent deletion"] = "";
@ -1706,8 +1512,206 @@ $a->strings["PHP logging"] = "";
$a->strings["To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."] = ""; $a->strings["To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."] = "";
$a->strings["Error trying to open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s exist and is readable."] = ""; $a->strings["Error trying to open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s exist and is readable."] = "";
$a->strings["Couldn't open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s is readable."] = ""; $a->strings["Couldn't open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s is readable."] = "";
$a->strings["Off"] = "Uit";
$a->strings["On"] = "Aan";
$a->strings["Lock feature %s"] = ""; $a->strings["Lock feature %s"] = "";
$a->strings["Manage Additional Features"] = ""; $a->strings["Manage Additional Features"] = "";
$a->strings["Display"] = "Weergave";
$a->strings["Social Networks"] = "Sociale netwerken";
$a->strings["Delegations"] = "";
$a->strings["Connected apps"] = "Verbonden applicaties";
$a->strings["Remove account"] = "Account verwijderen";
$a->strings["Missing some important data!"] = "Een belangrijk gegeven ontbreekt!";
$a->strings["Failed to connect with email account using the settings provided."] = "Ik kon geen verbinding maken met het e-mail account met de gegeven instellingen.";
$a->strings["Email settings updated."] = "E-mail instellingen bijgewerkt..";
$a->strings["Features updated"] = "Functies bijgewerkt";
$a->strings["Relocate message has been send to your contacts"] = "";
$a->strings["Passwords do not match. Password unchanged."] = "Wachtwoorden komen niet overeen. Wachtwoord niet gewijzigd.";
$a->strings["Empty passwords are not allowed. Password unchanged."] = "Lege wachtwoorden zijn niet toegelaten. Wachtwoord niet gewijzigd.";
$a->strings["The new password has been exposed in a public data dump, please choose another."] = "";
$a->strings["Wrong password."] = "Verkeerd wachtwoord.";
$a->strings["Password changed."] = "Wachtwoord gewijzigd.";
$a->strings["Password update failed. Please try again."] = "Wachtwoord-)wijziging mislukt. Probeer opnieuw.";
$a->strings[" Please use a shorter name."] = "Gebruik een kortere naam.";
$a->strings[" Name too short."] = "Naam te kort.";
$a->strings["Wrong Password"] = "Verkeerd wachtwoord";
$a->strings["Invalid email."] = "";
$a->strings["Cannot change to that email."] = "";
$a->strings["Private forum has no privacy permissions. Using default privacy group."] = "Privéforum/-groep heeft geen privacyrechten. De standaard privacygroep wordt gebruikt.";
$a->strings["Private forum has no privacy permissions and no default privacy group."] = "Privéforum/-groep heeft geen privacyrechten en geen standaard privacygroep.";
$a->strings["Settings updated."] = "Instellingen bijgewerkt.";
$a->strings["Add application"] = "Toepassing toevoegen";
$a->strings["Consumer Key"] = "Gebruikerssleutel";
$a->strings["Consumer Secret"] = "Gebruikersgeheim";
$a->strings["Redirect"] = "Doorverwijzing";
$a->strings["Icon url"] = "URL pictogram";
$a->strings["You can't edit this application."] = "Je kunt deze toepassing niet wijzigen.";
$a->strings["Connected Apps"] = "Verbonden applicaties";
$a->strings["Edit"] = "Bewerken";
$a->strings["Client key starts with"] = "";
$a->strings["No name"] = "Geen naam";
$a->strings["Remove authorization"] = "Verwijder authorisatie";
$a->strings["No Addon settings configured"] = "";
$a->strings["Addon Settings"] = "";
$a->strings["Additional Features"] = "Extra functies";
$a->strings["Diaspora"] = "Diaspora";
$a->strings["enabled"] = "ingeschakeld";
$a->strings["disabled"] = "uitgeschakeld";
$a->strings["Built-in support for %s connectivity is %s"] = "Ingebouwde ondersteuning voor connectiviteit met %s is %s";
$a->strings["GNU Social (OStatus)"] = "";
$a->strings["Email access is disabled on this site."] = "E-mailtoegang is op deze website uitgeschakeld.";
$a->strings["General Social Media Settings"] = "";
$a->strings["Disable Content Warning"] = "";
$a->strings["Users on networks like Mastodon or Pleroma are able to set a content warning field which collapse their post by default. This disables the automatic collapsing and sets the content warning as the post title. Doesn't affect any other content filtering you eventually set up."] = "";
$a->strings["Disable intelligent shortening"] = "";
$a->strings["Normally the system tries to find the best link to add to shortened posts. If this option is enabled then every shortened post will always point to the original friendica post."] = "";
$a->strings["Automatically follow any GNU Social (OStatus) followers/mentioners"] = "";
$a->strings["If you receive a message from an unknown OStatus user, this option decides what to do. If it is checked, a new contact will be created for every unknown user."] = "";
$a->strings["Default group for OStatus contacts"] = "";
$a->strings["Your legacy GNU Social account"] = "";
$a->strings["If you enter your old GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done."] = "";
$a->strings["Repair OStatus subscriptions"] = "";
$a->strings["Email/Mailbox Setup"] = "E-mail Instellen";
$a->strings["If you wish to communicate with email contacts using this service (optional), please specify how to connect to your mailbox."] = "Als je wilt communiceren met e-mail contacten via deze dienst (optioneel), moet je hier opgeven hoe ik jouw mailbox kan bereiken.";
$a->strings["Last successful email check:"] = "Laatste succesvolle e-mail controle:";
$a->strings["IMAP server name:"] = "IMAP server naam:";
$a->strings["IMAP port:"] = "IMAP poort:";
$a->strings["Security:"] = "Beveiliging:";
$a->strings["None"] = "Geen";
$a->strings["Email login name:"] = "E-mail login naam:";
$a->strings["Email password:"] = "E-mail wachtwoord:";
$a->strings["Reply-to address:"] = "Antwoord adres:";
$a->strings["Send public posts to all email contacts:"] = "Openbare posts naar alle e-mail contacten versturen:";
$a->strings["Action after import:"] = "Actie na importeren:";
$a->strings["Mark as seen"] = "Als 'gelezen' markeren";
$a->strings["Move to folder"] = "Naar map verplaatsen";
$a->strings["Move to folder:"] = "Verplaatsen naar map:";
$a->strings["%s - (Unsupported)"] = "";
$a->strings["%s - (Experimental)"] = "";
$a->strings["Display Settings"] = "Scherminstellingen";
$a->strings["Display Theme:"] = "Schermthema:";
$a->strings["Mobile Theme:"] = "Mobiel thema:";
$a->strings["Suppress warning of insecure networks"] = "";
$a->strings["Should the system suppress the warning that the current group contains members of networks that can't receive non public postings."] = "";
$a->strings["Update browser every xx seconds"] = "Browser elke xx seconden verversen";
$a->strings["Minimum of 10 seconds. Enter -1 to disable it."] = "";
$a->strings["Number of items to display per page:"] = "Aantal items te tonen per pagina:";
$a->strings["Maximum of 100 items"] = "Maximum 100 items";
$a->strings["Number of items to display per page when viewed from mobile device:"] = "Aantal items per pagina als je een mobiel toestel gebruikt:";
$a->strings["Don't show emoticons"] = "Emoticons niet tonen";
$a->strings["Calendar"] = "";
$a->strings["Beginning of week:"] = "";
$a->strings["Don't show notices"] = "";
$a->strings["Infinite scroll"] = "Oneindig scrollen";
$a->strings["Automatic updates only at the top of the network page"] = "";
$a->strings["When disabled, the network page is updated all the time, which could be confusing while reading."] = "";
$a->strings["Bandwith Saver Mode"] = "";
$a->strings["When enabled, embedded content is not displayed on automatic updates, they only show on page reload."] = "";
$a->strings["Smart Threading"] = "";
$a->strings["When enabled, suppress extraneous thread indentation while keeping it where it matters. Only works if threading is available and enabled."] = "";
$a->strings["General Theme Settings"] = "";
$a->strings["Custom Theme Settings"] = "";
$a->strings["Content Settings"] = "";
$a->strings["Theme settings"] = "Thema-instellingen";
$a->strings["Unable to find your profile. Please contact your admin."] = "";
$a->strings["Account Types"] = "";
$a->strings["Personal Page Subtypes"] = "";
$a->strings["Community Forum Subtypes"] = "";
$a->strings["Personal Page"] = "";
$a->strings["Account for a personal profile."] = "";
$a->strings["Organisation Page"] = "";
$a->strings["Account for an organisation that automatically approves contact requests as \"Followers\"."] = "";
$a->strings["News Page"] = "";
$a->strings["Account for a news reflector that automatically approves contact requests as \"Followers\"."] = "";
$a->strings["Community Forum"] = "";
$a->strings["Account for community discussions."] = "";
$a->strings["Normal Account Page"] = "Normale accountpagina";
$a->strings["Account for a regular personal profile that requires manual approval of \"Friends\" and \"Followers\"."] = "";
$a->strings["Soapbox Page"] = "Zeepkist-pagina";
$a->strings["Account for a public profile that automatically approves contact requests as \"Followers\"."] = "";
$a->strings["Public Forum"] = "";
$a->strings["Automatically approves all contact requests."] = "";
$a->strings["Automatic Friend Page"] = "Automatisch Vriendschapspagina";
$a->strings["Account for a popular profile that automatically approves contact requests as \"Friends\"."] = "";
$a->strings["Private Forum [Experimental]"] = "Privé-forum [experimenteel]";
$a->strings["Requires manual approval of contact requests."] = "";
$a->strings["OpenID:"] = "OpenID:";
$a->strings["(Optional) Allow this OpenID to login to this account."] = "(Optioneel) Laat dit OpenID toe om in te loggen op deze account.";
$a->strings["Publish your default profile in your local site directory?"] = "Je standaardprofiel in je lokale gids publiceren?";
$a->strings["Your profile will be published in the global friendica directories (e.g. <a href=\"%s\">%s</a>). Your profile will be visible in public."] = "";
$a->strings["Publish your default profile in the global social directory?"] = "Je standaardprofiel in de globale sociale gids publiceren?";
$a->strings["Your profile will be published in this node's <a href=\"%s\">local directory</a>. Your profile details may be publicly visible depending on the system settings."] = "";
$a->strings["Hide your contact/friend list from viewers of your default profile?"] = "Je vrienden/contacten verbergen voor bezoekers van je standaard profiel?";
$a->strings["Your contact list won't be shown in your default profile page. You can decide to show your contact list separately for each additional profile you create"] = "";
$a->strings["Hide your profile details from anonymous viewers?"] = "";
$a->strings["Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Disables posting public messages to Diaspora and other networks."] = "";
$a->strings["Allow friends to post to your profile page?"] = "Vrienden toestaan om op jou profielpagina te posten?";
$a->strings["Your contacts may write posts on your profile wall. These posts will be distributed to your contacts"] = "";
$a->strings["Allow friends to tag your posts?"] = "Sta vrienden toe om jouw berichten te labelen?";
$a->strings["Your contacts can add additional tags to your posts."] = "";
$a->strings["Allow us to suggest you as a potential friend to new members?"] = "Sta je mij toe om jou als mogelijke vriend voor te stellen aan nieuwe leden?";
$a->strings["If you like, Friendica may suggest new members to add you as a contact."] = "";
$a->strings["Permit unknown people to send you private mail?"] = "Mogen onbekende personen jou privé berichten sturen?";
$a->strings["Friendica network users may send you private messages even if they are not in your contact list."] = "";
$a->strings["Profile is <strong>not published</strong>."] = "Profiel is <strong>niet gepubliceerd</strong>.";
$a->strings["Your Identity Address is <strong>'%s'</strong> or '%s'."] = "";
$a->strings["Automatically expire posts after this many days:"] = "Laat berichten automatisch vervallen na zo veel dagen:";
$a->strings["If empty, posts will not expire. Expired posts will be deleted"] = "Berichten zullen niet vervallen indien leeg. Vervallen berichten zullen worden verwijderd.";
$a->strings["Advanced expiration settings"] = "Geavanceerde instellingen voor vervallen";
$a->strings["Advanced Expiration"] = "Geavanceerd Verval:";
$a->strings["Expire posts:"] = "Laat berichten vervallen:";
$a->strings["Expire personal notes:"] = "Laat persoonlijke aantekeningen verlopen:";
$a->strings["Expire starred posts:"] = "Laat berichten met ster verlopen";
$a->strings["Expire photos:"] = "Laat foto's vervallen:";
$a->strings["Only expire posts by others:"] = "Laat alleen berichten door anderen vervallen:";
$a->strings["Account Settings"] = "Account Instellingen";
$a->strings["Password Settings"] = "Wachtwoord Instellingen";
$a->strings["Leave password fields blank unless changing"] = "Laat de wachtwoord-velden leeg, tenzij je het wilt veranderen";
$a->strings["Current Password:"] = "Huidig wachtwoord:";
$a->strings["Your current password to confirm the changes"] = "Je huidig wachtwoord om de wijzigingen te bevestigen";
$a->strings["Password:"] = "Wachtwoord:";
$a->strings["Basic Settings"] = "Basis Instellingen";
$a->strings["Full Name:"] = "Volledige Naam:";
$a->strings["Email Address:"] = "E-mailadres:";
$a->strings["Your Timezone:"] = "Je Tijdzone:";
$a->strings["Your Language:"] = "";
$a->strings["Set the language we use to show you friendica interface and to send you emails"] = "";
$a->strings["Default Post Location:"] = "Standaard locatie:";
$a->strings["Use Browser Location:"] = "Gebruik Webbrowser Locatie:";
$a->strings["Security and Privacy Settings"] = "Instellingen voor Beveiliging en Privacy";
$a->strings["Maximum Friend Requests/Day:"] = "Maximum aantal vriendschapsverzoeken per dag:";
$a->strings["(to prevent spam abuse)"] = "(om spam misbruik te voorkomen)";
$a->strings["Default Post Permissions"] = "Standaard rechten voor nieuwe berichten";
$a->strings["(click to open/close)"] = "(klik om te openen/sluiten)";
$a->strings["Default Private Post"] = "Standaard Privé Post";
$a->strings["Default Public Post"] = "Standaard Publieke Post";
$a->strings["Default Permissions for New Posts"] = "Standaard rechten voor nieuwe berichten";
$a->strings["Maximum private messages per day from unknown people:"] = "Maximum aantal privé-berichten per dag van onbekende personen:";
$a->strings["Notification Settings"] = "Notificatie Instellingen";
$a->strings["By default post a status message when:"] = "Post automatisch een bericht op je tijdlijn wanneer:";
$a->strings["accepting a friend request"] = "Een vriendschapsverzoek accepteren";
$a->strings["joining a forum/community"] = "Lid worden van een groep/forum";
$a->strings["making an <em>interesting</em> profile change"] = "Een <em>interessante</em> verandering aan je profiel";
$a->strings["Send a notification email when:"] = "Stuur een notificatie e-mail wanneer:";
$a->strings["You receive an introduction"] = "Je ontvangt een vriendschaps- of connectieverzoek";
$a->strings["Your introductions are confirmed"] = "Jouw vriendschaps- of connectieverzoeken zijn bevestigd";
$a->strings["Someone writes on your profile wall"] = "Iemand iets op je tijdlijn schrijft";
$a->strings["Someone writes a followup comment"] = "Iemand een reactie schrijft";
$a->strings["You receive a private message"] = "Je een privé-bericht ontvangt";
$a->strings["You receive a friend suggestion"] = "Je een suggestie voor een vriendschap ontvangt";
$a->strings["You are tagged in a post"] = "Je expliciet in een bericht bent genoemd";
$a->strings["You are poked/prodded/etc. in a post"] = "Je in een bericht bent aangestoten/gepord/etc.";
$a->strings["Activate desktop notifications"] = "";
$a->strings["Show desktop popup on new notifications"] = "";
$a->strings["Text-only notification emails"] = "";
$a->strings["Send text only notification emails, without the html part"] = "";
$a->strings["Show detailled notifications"] = "";
$a->strings["Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed."] = "";
$a->strings["Advanced Account/Page Type Settings"] = "";
$a->strings["Change the behaviour of this account for special situations"] = "";
$a->strings["Relocate"] = "";
$a->strings["If you have moved this profile from another server, and some of your contacts don't receive your updates, try pushing this button."] = "";
$a->strings["Resend relocate message to contacts"] = "";
$a->strings["Error decoding account file"] = ""; $a->strings["Error decoding account file"] = "";
$a->strings["Error! No version data in file! This is not a Friendica account file?"] = ""; $a->strings["Error! No version data in file! This is not a Friendica account file?"] = "";
$a->strings["User '%s' already exists on this server!"] = "Gebruiker '%s' bestaat al op deze server!"; $a->strings["User '%s' already exists on this server!"] = "Gebruiker '%s' bestaat al op deze server!";
@ -1886,36 +1890,36 @@ $a->strings["%d contact in common"] = [
1 => "%d gedeelde contacten", 1 => "%d gedeelde contacten",
]; ];
$a->strings["Frequently"] = "Frequent"; $a->strings["Frequently"] = "Frequent";
$a->strings["Hourly"] = "elk uur"; $a->strings["Hourly"] = "Ieder uur";
$a->strings["Twice daily"] = "Twee keer per dag"; $a->strings["Twice daily"] = "Twee maal daags";
$a->strings["Daily"] = "dagelijks"; $a->strings["Daily"] = "Dagelijks";
$a->strings["Weekly"] = "wekelijks"; $a->strings["Weekly"] = "Wekelijks";
$a->strings["Monthly"] = "maandelijks"; $a->strings["Monthly"] = "Maandelijks";
$a->strings["OStatus"] = "OStatus"; $a->strings["OStatus"] = "OStatus";
$a->strings["RSS/Atom"] = "RSS/Atom"; $a->strings["RSS/Atom"] = "RSS/Atom";
$a->strings["Facebook"] = "Facebook"; $a->strings["Facebook"] = "Facebook";
$a->strings["Zot!"] = "Zot!"; $a->strings["Zot!"] = "Zot!";
$a->strings["LinkedIn"] = "Linkedln"; $a->strings["LinkedIn"] = "LinkedIn";
$a->strings["XMPP/IM"] = "XMPP/IM"; $a->strings["XMPP/IM"] = "XMPP/Chat";
$a->strings["MySpace"] = "Myspace"; $a->strings["MySpace"] = "MySpace";
$a->strings["Google+"] = "Google+"; $a->strings["Google+"] = "Google+";
$a->strings["pump.io"] = "pump.io"; $a->strings["pump.io"] = "pump.io";
$a->strings["Twitter"] = "Twitter"; $a->strings["Twitter"] = "Twitter";
$a->strings["Diaspora Connector"] = "Diaspora-connector"; $a->strings["Diaspora Connector"] = "Diaspora Connector";
$a->strings["GNU Social Connector"] = ""; $a->strings["GNU Social Connector"] = "GNU Social Connector";
$a->strings["pnut"] = ""; $a->strings["pnut"] = "pnut";
$a->strings["App.net"] = ""; $a->strings["App.net"] = "App.net";
$a->strings["Male"] = "Man"; $a->strings["Male"] = "Mannelijk";
$a->strings["Female"] = "Vrouw"; $a->strings["Female"] = "Vrouwelijk";
$a->strings["Currently Male"] = "Momenteel mannelijk"; $a->strings["Currently Male"] = "Momenteel mannelijk";
$a->strings["Currently Female"] = "Momenteel vrouwelijk"; $a->strings["Currently Female"] = "Momenteel vrouwelijk";
$a->strings["Mostly Male"] = "Meestal mannelijk"; $a->strings["Mostly Male"] = "Hoofdzakelijk mannelijk";
$a->strings["Mostly Female"] = "Meestal vrouwelijk"; $a->strings["Mostly Female"] = "Hoofdzakelijk vrouwelijk";
$a->strings["Transgender"] = "Transgender"; $a->strings["Transgender"] = "Transgender";
$a->strings["Intersex"] = "Interseksueel"; $a->strings["Intersex"] = "Intersex";
$a->strings["Transsexual"] = "Transseksueel"; $a->strings["Transsexual"] = "Transeksueel";
$a->strings["Hermaphrodite"] = "Hermafrodiet"; $a->strings["Hermaphrodite"] = "Hermafrodiet";
$a->strings["Neuter"] = "Genderneutraal"; $a->strings["Neuter"] = "Onzijdig";
$a->strings["Non-specific"] = "Niet-specifiek"; $a->strings["Non-specific"] = "Niet-specifiek";
$a->strings["Other"] = "Anders"; $a->strings["Other"] = "Anders";
$a->strings["Males"] = "Mannen"; $a->strings["Males"] = "Mannen";
@ -1962,9 +1966,9 @@ $a->strings["Uncertain"] = "Onzeker";
$a->strings["It's complicated"] = "Het is gecompliceerd"; $a->strings["It's complicated"] = "Het is gecompliceerd";
$a->strings["Don't care"] = "Kan me niet schelen"; $a->strings["Don't care"] = "Kan me niet schelen";
$a->strings["Ask me"] = "Vraag me"; $a->strings["Ask me"] = "Vraag me";
$a->strings["There are no tables on MyISAM."] = ""; $a->strings["There are no tables on MyISAM."] = "Er zijn geen MyISAM tabellen.";
$a->strings["\n\t\t\t\tThe friendica developers released update %s recently,\n\t\t\t\tbut when I tried to install it, something went terribly wrong.\n\t\t\t\tThis needs to be fixed soon and I can't do it alone. Please contact a\n\t\t\t\tfriendica developer if you can not help me on your own. My database might be invalid."] = ""; $a->strings["\n\t\t\t\tThe friendica developers released update %s recently,\n\t\t\t\tbut when I tried to install it, something went terribly wrong.\n\t\t\t\tThis needs to be fixed soon and I can't do it alone. Please contact a\n\t\t\t\tfriendica developer if you can not help me on your own. My database might be invalid."] = "\n\t\t\t\tDe Friendica ontwikkelaars hebben recent update %svrijgegeven,\n \t\t\t\tmaar wanneer ik deze probeerde te installeren ging het verschrikkelijk fout.\n \t\t\t\tDit moet snel opgelost worden en ik kan het niet alleen. Contacteer alstublieft\n \t\t\t\teen Friendica ontwikkelaar als je mij zelf niet kan helpen. Mijn database kan ongeldig zijn.";
$a->strings["The error message is\n[pre]%s[/pre]"] = ""; $a->strings["The error message is\n[pre]%s[/pre]"] = "De foutboodschap is\n[pre]%s[/pre]";
$a->strings["\nError %d occurred during database update:\n%s\n"] = ""; $a->strings["\nError %d occurred during database update:\n%s\n"] = "";
$a->strings["Errors encountered performing database changes: "] = ""; $a->strings["Errors encountered performing database changes: "] = "";
$a->strings[": Database update"] = ""; $a->strings[": Database update"] = "";
@ -2067,6 +2071,7 @@ $a->strings["An error occurred creating your default contact group. Please try a
$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account is pending for approval by the administrator.\n\t\t"] = ""; $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account is pending for approval by the administrator.\n\t\t"] = "";
$a->strings["Registration at %s"] = ""; $a->strings["Registration at %s"] = "";
$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t\t"] = ""; $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t\t"] = "";
$a->strings["\n\t\t\tThe login details are as follows:\n\n\t\t\tSite Location:\t%3\$s\n\t\t\tLogin Name:\t\t%1\$s\n\t\t\tPassword:\t\t%5\$s\n\n\t\t\tYou may change your password from your account \"Settings\" page after logging\n\t\t\tin.\n\n\t\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\t\tYou may also wish to add some basic information to your default profile\n\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\t\tWe recommend setting your full name, adding a profile photo,\n\t\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\t\tthan that.\n\n\t\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\t\tIf you are new and do not know anybody here, they may help\n\t\t\tyou to make some new and interesting friends.\n\n\t\t\tIf you ever want to delete your account, you can do so at %3\$s/removeme\n\n\t\t\tThank you and welcome to %2\$s."] = "";
$a->strings["%s is now following %s."] = "%s volgt nu %s."; $a->strings["%s is now following %s."] = "%s volgt nu %s.";
$a->strings["following"] = "volgend"; $a->strings["following"] = "volgend";
$a->strings["%s stopped following %s."] = "%s stopte %s te volgen."; $a->strings["%s stopped following %s."] = "%s stopte %s te volgen.";
@ -2141,7 +2146,7 @@ $a->strings["Check image permissions if all users are allowed to visit the image
$a->strings["Select scheme"] = ""; $a->strings["Select scheme"] = "";
$a->strings["Navigation bar background color"] = ""; $a->strings["Navigation bar background color"] = "";
$a->strings["Navigation bar icon color "] = ""; $a->strings["Navigation bar icon color "] = "";
$a->strings["Link color"] = ""; $a->strings["Link color"] = "Link kleur";
$a->strings["Set the background color"] = ""; $a->strings["Set the background color"] = "";
$a->strings["Content background opacity"] = ""; $a->strings["Content background opacity"] = "";
$a->strings["Set the background image"] = ""; $a->strings["Set the background image"] = "";

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,18 @@ $db_user = '{{$dbuser}}';
$db_pass = '{{$dbpass}}'; $db_pass = '{{$dbpass}}';
$db_data = '{{$dbdata}}'; $db_data = '{{$dbdata}}';
// Use environment variables for mysql if they are set beforehand
if (!empty(getenv('MYSQL_HOST'))
&& !empty(getenv('MYSQL_PORT'))
&& !empty(getenv('MYSQL_USERNAME'))
&& !empty(getenv('MYSQL_PASSWORD'))
&& !empty(getenv('MYSQL_DATABASE'))) {
$db_host = getenv('MYSQL_HOST') . ':' . getenv('MYSQL_PORT');
$db_user = getenv('MYSQL_USERNAME');
$db_pass = getenv('MYSQL_PASSWORD');
$db_data = getenv('MYSQL_DATABASE');
}
// Set the database connection charset to full Unicode (utf8mb4). // Set the database connection charset to full Unicode (utf8mb4).
// Changing this value will likely corrupt the special characters. // Changing this value will likely corrupt the special characters.
// You have been warned. // You have been warned.

View file

@ -5,6 +5,7 @@
{{if $displayprivstatement}} {{if $displayprivstatement}}
<h2>{{$privstatementtitle}}</h2> <h2>{{$privstatementtitle}}</h2>
<p>{{$privoperate}}</p> <p>{{$privoperate}}</p>
<p>{{$privdistribute}}</p>
<p>{{$privdelete}}</p> <p>{{$privdelete}}</p>
{{/if}} {{/if}}

View file

@ -0,0 +1,17 @@
#admin-users.adminpage { padding-left:0; padding-right: 0;}
#admin-users.adminpage > h1 { padding: 0 15px; }
#admin-users td { word-break: break-all; }
#admin-users #users th:first-of-type { width: 1em; }
#admin-users #users th:nth-of-type(2) { width: 40px; }
#admin-users #users th:last-of-type { width: 1em; }
#admin-users #deleted th:first-of-type { width: 40px; }
#admin-users #users img.avatar-nano, #deleted img.avatar-nano { height: 24px; width: 24px; }
.opened .caret { transform: rotate(180deg); }
tr.details td,
tr.details th
{ border-top: 0!important; }

View file

@ -20,6 +20,7 @@ $(function() {
} }
}); });
function selectall(cls) { function selectall(cls) {
$('.' + cls).prop('checked', true); $('.' + cls).prop('checked', true);
return false; return false;
@ -28,4 +29,17 @@ $(function() {
$('.' + cls).prop('checked', false); $('.' + cls).prop('checked', false);
return false; return false;
} }
}); });
// Users
function confirm_delete(msg, uname){
return confirm(msg.format(uname));
}
function details(uid) {
$("#user-"+uid+"-detail").toggleClass("hidden");
$("#user-"+uid).toggleClass("opened");
return false;
}

View file

@ -0,0 +1,285 @@
<script type="text/javascript" src="view/theme/frio/js/mod_admin.js"></script>
<link rel="stylesheet" href="view/theme/frio/css/mod_admin.css" type="text/css" media="screen"/>
<div id="admin-users" class="adminpage generic-page-wrapper">
<h1>{{$title}} - {{$page}}</h1>
<form action="{{$baseurl}}/admin/users" method="post">
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
<!--
**
*
* PENDING Users table
*
**
-->
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{$h_pending}}</h3></div>
{{if $pending}}
<table id="pending" class="table table-hover">
<thead>
<tr>
<th></th>
{{foreach $th_pending as $th}}<th>{{$th}}</th>{{/foreach}}
<th></th>
</tr>
</thead>
<tbody>
{{foreach $pending as $u}}
<tr>
<td><input type="checkbox" class="pending_ckbx" id="id_pending_{{$u.hash}}" name="pending[]" value="{{$u.hash}}" /></td>
<td>{{$u.created}}</td>
<td>{{$u.name}}</td>
<td>{{$u.email}}</td>
<td>
<a href="{{$baseurl}}/regmod/allow/{{$u.hash}}" title="{{$approve}}"><i class="fa fa-thumbs-up" aria-hidden="true"></i></a>
<a href="{{$baseurl}}/regmod/deny/{{$u.hash}}" title="{{$deny}}"><i class="fa fa-thumbs-down" aria-hidden="true"></i></a>
</td>
</tr>
<tr class="details">
<td></td>
<th>{{$pendingnotetext}}</th>
<td colspan="4">{{$u.note}}</td>
</tr>
{{/foreach}}
</tbody>
</table>
<div class="panel-footer">
<div class="row">
<div class="col-xs-3">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default selectall" data-select-all="pending_ckbx"><i class="fa fa-check-square-o" aria-hidden="true"></i></button>
<button type="button" class="btn btn-default selectnone" data-select-none="pending_ckbx"><i class="fa fa-square-o" aria-hidden="true"></i></button>
</div>
</div>
<div class="col-xs-9 text-right">
<button type="submit" name="page_users_deny" class="btn btn-primary"><i class="fa fa-thumbs-down" aria-hidden="true"></i> {{$deny}}</button>
<button type="submit" name="page_users_approve" class="btn btn-warinig"><i class="fa fa-thumbs-up" aria-hidden="true"></i> {{$approve}}</button>
</div>
</div>
</div>
{{else}}
<div class="panel-body text-center text-muted">{{$no_pending}}</div>
{{/if}}
</div>
<!--
**
*
* USERS Table
*
**
-->
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{$h_users}}</h3></div>
{{if $users}}
<table id="users" class="table table-hover">
<thead>
<tr>
<th></th>
<th></th>
{{foreach $th_users as $k=>$th}}
{{if $k < 2 || $order_users == $th.1 || ($k==5 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1])) }}
<th class="th-{{$k}}">
<a href="{{$baseurl}}/admin/users/?o={{if $order_direction_users == "+"}}-{{/if}}{{$th.1}}">
{{if $order_users == $th.1}}
{{if $order_direction_users == "+"}}
&#8595;
{{else}}
&#8593;
{{/if}}
{{else}}
&#8597;
{{/if}}
{{$th.0}}</a>
</th>
{{/if}}
{{/foreach}}
<th></th>
</tr>
</thead>
<tbody>
{{foreach $users as $u}}
<tr id="user-{{$u.uid}}">
<td>
{{if $u.is_deletable}}
<input type="checkbox" class="users_ckbx" id="id_user_{{$u.uid}}" name="user[]" value="{{$u.uid}}"/>
{{else}}
&nbsp;
{{/if}}
</td>
<td><img class="avatar-nano" src="{{$u.micro}}" title="{{$u.nickname}}"></td>
<td><a href="{{$u.url}}" title="{{$u.nickname}}"> {{$u.name}}</a></td>
<td>{{$u.email}}</td>
{{if $order_users == $th_users.2.1}}
<td>{{$u.register_date}}</td>
{{/if}}
{{if $order_users == $th_users.3.1}}
<td>{{$u.login_date}}</td>
{{/if}}
{{if $order_users == $th_users.4.1}}
<td>{{$u.lastitem_date}}</td>
{{/if}}
{{if !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }}
<td>
<i class="fa
{{if $u.page_flags_raw==0}}fa-user{{/if}} {{* PAGE_NORMAL *}}
{{if $u.page_flags_raw==1}}fa-bullhorn{{/if}} {{* PAGE_SOAPBOX *}}
{{if $u.page_flags_raw==2}}fa-users{{/if}} {{* PAGE_COMMUNITY *}}
{{if $u.page_flags_raw==3}}fa-heart{{/if}} {{* PAGE_FREELOVE *}}
{{if $u.page_flags_raw==4}}fa-rss{{/if}} {{* PAGE_BLOG *}}
{{if $u.page_flags_raw==5}}fa-user-secret{{/if}} {{* PAGE_PRVGROUP *}}
" title="{{$u.page_flags}}"></i>
{{if $u.page_flags_raw==0 && $u.account_type_raw > 0}}
<i class="fa
{{if $u.account_type_raw==1}}fa-sitemap{{/if}} {{* ACCOUNT_TYPE_ORGANISATION *}}
{{if $u.account_type_raw==2}}fa-newspaper-o{{/if}} {{* ACCOUNT_TYPE_NEWS *}}
{{if $u.account_type_raw==3}}fa-comments{{/if}} {{* ACCOUNT_TYPE_COMMUNITY *}}
" title="{{$u.account_type}}"></i>
{{/if}}
{{if $u.is_admin}}<i class="fa fa-user-md text-primary" title="{{$siteadmin}}"></i>{{/if}}
{{if $u.account_expired}}<i class="fa fa-clock-o text-warning" title="{{$accountexpired}}"></i>{{/if}}
</td>
{{/if}}
<td class="text-right">
<button type="button" class="btn-link" onclick="return details({{$u.uid}})"><span class="caret"></span></button>
</td>
</tr>
<tr id="user-{{$u.uid}}-detail" class="hidden details">
<td>&nbsp;</td>
<td colspan="4">
{{if $order_users != $th_users.2.1}}
<p><a href="{{$baseurl}}/admin/users/?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.2.1}}">
&#8597; {{$th_users.2.0}}</a> : {{$u.register_date}}</p>
{{/if}}
{{if $order_users != $th_users.3.1}}
<p><a href="{{$baseurl}}/admin/users/?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.3.1}}">
&#8597; {{$th_users.3.0}}</a> : {{$u.login_date}}</p>
{{/if}}
{{if $order_users != $th_users.4.1}}
<p><a href="{{$baseurl}}/admin/users/?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.4.1}}">
&#8597; {{$th_users.4.0}}</a> : {{$u.lastitem_date}}</p>
{{/if}}
{{if in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }}
<p><a href="{{$baseurl}}/admin/users/?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.5.1}}">
&#8597; {{$th_users.5.0}}</a> : {{$u.page_flags}}{{if $u.page_flags_raw==0 && $u.account_type_raw > 0}}, {{$u.account_type}}{{/if}} {{if $u.is_admin}}({{$siteadmin}}){{/if}} {{if $u.account_expired}}({{$accountexpired}}){{/if}}</p>
{{/if}}
</td>
<td class="text-right">
{{if $u.is_deletable}}
<a href="{{$baseurl}}/admin/users/block/{{$u.uid}}?t={{$form_security_token}}" title="{{if $u.blocked}}{{$unblock}}{{else}}{{$block}}{{/if}}">
{{if $u.blocked==0}}
<i class="fa fa-ban" aria-hidden="true"></i>
{{else}}
<i class="fa fa-circle-o" aria-hidden="true"></i>
{{/if}}
</a>
<a href="{{$baseurl}}/admin/users/delete/{{$u.uid}}?t={{$form_security_token}}" title="{{$delete}}" onclick="return confirm_delete('{{$confirm_delete}}','{{$u.name}}')"><i class="fa fa-trash" aria-hidden="true"></i></a>
{{else}}
&nbsp;
{{/if}}
</td>
</tr>
{{/foreach}}
</tbody>
</table>
<div class="panel-footer">
<div class="row">
<div class="col-xs-3">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default selectall" data-select-all="users_ckbx"><i class="fa fa-check-square-o" aria-hidden="true"></i></button>
<button type="button" class="btn btn-default selectnone" data-select-none="users_ckbx"><i class="fa fa-square-o" aria-hidden="true"></i></button>
</div>
</div>
<div class="col-xs-9 text-right">
<button type="submit" name="page_users_block" class="btn btn-warning"> <i class="fa fa-ban" aria-hidden="true"></i> {{$block}} / <i class="fa fa-circle-o" aria-hidden="true"></i> {{$unblock}}</button>
<button type="submit" name="page_users_delete" class="btn btn-danger" onclick="return confirm_delete('{{$confirm_delete_multi}}')"><i class="fa fa-trash" aria-hidden="true"></i> {{$delete}}</button>
</div>
</div>
</div>
{{else}}
<div class="panel-body text-center bg-danger">NO USERS?!?</div>
{{/if}}
</div>
</form>
<!--
**
*
* DELETED Users table
*
**
-->
{{if $deleted}}
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{$h_deleted}}</h3></div>
<table id="deleted" class="table table-hover">
<thead>
<tr>
<th></th>
{{foreach $th_deleted as $k=>$th}}
{{if in_array($k,[0,1,5])}}
<th>{{$th}}</th>
{{/if}}
{{/foreach}}
</tr>
</thead>
<tbody>
{{foreach $deleted as $u}}
<tr>
<td><img class="avatar-nano" src="{{$u.micro}}" title="{{$u.nickname}}"></td>
<td><a href="{{$u.url}}" title="{{$u.nickname}}" >{{$u.name}}</a></td>
<td>{{$u.email}}</td>
<td>{{$u.deleted}}</td>
</tr>
{{/foreach}}
</tbody>
</table>
</div>
{{/if}}
<!--
**
*
* NEW USER Form
*
**
-->
<form action="{{$baseurl}}/admin/users" method="post">
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{$h_newuser}}</h3></div>
<div class="panel-body">
{{include file="field_input.tpl" field=$newusername}}
{{include file="field_input.tpl" field=$newusernickname}}
{{include file="field_input.tpl" field=$newuseremail}}
</div>
<div class="panel-footer text-right">
<button type="submit" class="btn btn-primary">{{$submit}}</button>
</form>
</div>
</form>
</div>

View file

@ -164,6 +164,11 @@
<button type="submit" name="submit" class="btn btn-primary" value="{{$submit|escape:'html'}}">{{$submit}}</button> <button type="submit" name="submit" class="btn btn-primary" value="{{$submit|escape:'html'}}">{{$submit}}</button>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
{{if $reason}}
<h4>{{$lbl_info2}}</h4>
<p>{{$reason}}</p>
<div class="clear"></div>
{{/if}}
</div> </div>
</div> </div>
</div> </div>

View file

@ -81,6 +81,15 @@
<h4>{{$lbl_vis1}}</h4> <h4>{{$lbl_vis1}}</h4>
<p>{{$lbl_vis2}}</p> <p>{{$lbl_vis2}}</p>
</div> </div>
{{if $reason}}
<div id="contact-info-wrapper">
<h4>{{$lbl_info2}}</h4>
<p>{{$reason}}</p>
</div>
<div id="contact-info-end"></div>
{{/if}}
{{$profile_select}} {{$profile_select}}
<div id="contact-edit-profile-select-end"></div> <div id="contact-edit-profile-select-end"></div>

View file

@ -75,6 +75,15 @@
<h4>{{$lbl_vis1}}</h4> <h4>{{$lbl_vis1}}</h4>
<p>{{$lbl_vis2}}</p> <p>{{$lbl_vis2}}</p>
</div> </div>
{{if $reason}}
<div id="contact-info-wrapper">
<h4>{{$lbl_info2}}</h4>
<p>{{$reason}}</p>
</div>
<div id="contact-info-end"></div>
{{/if}}
{{$profile_select}} {{$profile_select}}
<div id="contact-edit-profile-select-end"></div> <div id="contact-edit-profile-select-end"></div>

View file

@ -82,6 +82,14 @@
</div> </div>
<div id="contact-edit-info-end"></div> <div id="contact-edit-info-end"></div>
{{if $reason}}
<div id="contact-info-wrapper">
<h4>{{$lbl_info2}}</h4>
<p>{{$reason}}</p>
</div>
<div id="contact-info-end"></div>
{{/if}}
{{if $profile_select}} {{if $profile_select}}
<div id="contact-edit-profile-select-text"> <div id="contact-edit-profile-select-text">
<h4>{{$lbl_vis1}}</h4> <h4>{{$lbl_vis1}}</h4>