diff --git a/doc/api.md b/doc/api.md index 08fca74fa4..07813b6a77 100644 --- a/doc/api.md +++ b/doc/api.md @@ -634,6 +634,73 @@ Friendica doesn't allow showing the friends of other users. * trim_user * contributor_details +--- + +### Return values for statuses/* api calls + +Returned status object is conform to GNU Social/Twitter api. + +Friendica adds some addictional fields: + +- owner: a user object, it's the owner of the item. +- private: boolean, true if the item is marked as private +- activities: map with activities related to the item. Every activity is a list of user objects. + +This properties are prefixed with "friendica_" in JSON responses and namespaced under "http://friendi.ca/schema/api/1/" in XML responses + +JSON: + +```json +[ + { + // ... + 'friendica_owner' : { + // user object + }, + 'friendica_private' : true, + 'friendica_activities': { + 'like': [ + { + // user object + }, + // ... + ], + 'dislike': [], + 'attendyes': [], + 'attendno': [], + 'attendmaybe': [] + } + }, + // ... +] +``` + +XML: + +```xml + + + + + true + + + + + + + + + + + + + + + +``` + + --- ### statusnet/config (*) diff --git a/include/api.php b/include/api.php index 7450d650eb..f40674b894 100644 --- a/include/api.php +++ b/include/api.php @@ -2888,6 +2888,7 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json") 'favorited' => $item['starred'] ? true : false, 'user' => $status_user , 'friendica_owner' => $owner_user, + 'friendica_private' => $item['private'] == 1, //'entities' => NULL, 'statusnet_html' => $converted["html"], 'statusnet_conversation_id' => $item['parent'], diff --git a/include/conversation.php b/include/conversation.php index 665d9d4831..5a26700fd7 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -471,6 +471,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o . "'; var profile_page = " . $a->pager['page'] . "; \r\n"; } } elseif ($mode === 'profile') { + $items = conversation_add_children($items, false, $order, $uid); $profile_owner = $a->profile['profile_uid']; if (!$update) { @@ -490,6 +491,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o } } } elseif ($mode === 'notes') { + $items = conversation_add_children($items, false, $order, $uid); $profile_owner = local_user(); if (!$update) { @@ -498,6 +500,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o . "; var netargs = '/?f='; var profile_page = " . $a->pager['page'] . "; \r\n"; } } elseif ($mode === 'display') { + $items = conversation_add_children($items, false, $order, $uid); $profile_owner = $a->profile['uid']; if (!$update) { diff --git a/include/dba.php b/include/dba.php index 6480b28ed2..9e168eac79 100644 --- a/include/dba.php +++ b/include/dba.php @@ -5,9 +5,9 @@ use Friendica\Database\DBA; /** * @brief execute SQL query with printf style args - deprecated * - * Please use the dba:: functions instead: - * dba::select, dba::exists, dba::insert - * dba::delete, dba::update, dba::p, dba::e + * Please use the DBA:: functions instead: + * DBA::select, DBA::exists, DBA::insert + * DBA::delete, DBA::update, DBA::p, DBA::e * * @param $args Query parameters (1 to N parameters of different types) * @return array|bool Query array diff --git a/include/enotify.php b/include/enotify.php index 0ef3c56765..70abce5845 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -32,6 +32,20 @@ function notification($params) logger('Missing parameters.' . System::callstack()); } + // Ensure that the important fields are set at any time + $fields = ['notify-flags', 'language', 'username', 'email']; + $user = DBA::selectFirst('user', $fields, ['uid' => $params['uid']]); + + if (!DBA::isResult($user)) { + logger('Unknown user ' . $params['uid']); + return; + } + + $params['notify_flags'] = defaults($params, 'notify_flags', $user['notify-flags']); + $params['language'] = defaults($params, 'language', $user['language']); + $params['to_name'] = defaults($params, 'to_name', $user['username']); + $params['to_email'] = defaults($params, 'to_email', $user['email']); + // from here on everything is in the recipients language L10n::pushLang($params['language']); @@ -510,7 +524,7 @@ function notification($params) } // send email notification if notification preferences permit - if ((!empty($params['notify_flags']) & intval($params['type'])) + if ((intval($params['notify_flags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM || $params['type'] == SYSTEM_EMAIL) { @@ -661,7 +675,7 @@ function check_item_notification($itemid, $uid, $defaulttype = "") { $profiles = $notification_data["profiles"]; - $fields = ['notify-flags', 'language', 'username', 'email', 'nickname']; + $fields = ['nickname']; $user = DBA::selectFirst('user', $fields, ['uid' => $uid]); if (!DBA::isResult($user)) { return false; @@ -724,10 +738,6 @@ function check_item_notification($itemid, $uid, $defaulttype = "") { // Generate the notification array $params = []; $params["uid"] = $uid; - $params["notify_flags"] = $user["notify-flags"]; - $params["language"] = $user["language"]; - $params["to_name"] = $user["username"]; - $params["to_email"] = $user["email"]; $params["item"] = $item; $params["parent"] = $item["parent"]; $params["link"] = System::baseUrl().'/display/'.urlencode($item["guid"]); diff --git a/include/items.php b/include/items.php index 9922c447f0..08858682e6 100644 --- a/include/items.php +++ b/include/items.php @@ -371,7 +371,7 @@ function drop_item($id) if ((local_user() == $item['uid']) || $contact_id) { // Check if we should do HTML-based delete confirmation - if ($_REQUEST['confirm']) { + if (!empty($_REQUEST['confirm'])) { //
can't take arguments in its "action" parameter // so add any arguments as hidden inputs $query = explode_querystring($a->query_string); @@ -395,7 +395,7 @@ function drop_item($id) ]); } // Now check how the user responded to the confirmation query - if ($_REQUEST['canceled']) { + if (!empty($_REQUEST['canceled'])) { goaway(System::baseUrl() . '/' . $_SESSION['return_url']); } diff --git a/mod/community.php b/mod/community.php index cb4f69c917..9c9fb43900 100644 --- a/mod/community.php +++ b/mod/community.php @@ -10,6 +10,7 @@ use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Database\DBA; +use Friendica\Model\Contact; function community_init(App $a) { @@ -35,6 +36,25 @@ function community_content(App $a, $update = 0) return; } + $accounttype = null; + + if ($a->argc > 2) { + switch ($a->argv[2]) { + case 'person': + $accounttype = Contact::ACCOUNT_TYPE_PERSON; + break; + case 'organisation': + $accounttype = Contact::ACCOUNT_TYPE_ORGANISATION; + break; + case 'news': + $accounttype = Contact::ACCOUNT_TYPE_NEWS; + break; + case 'community': + $accounttype = Contact::ACCOUNT_TYPE_COMMUNITY; + break; + } + } + if ($a->argc > 1) { $content = $a->argv[1]; } else { @@ -135,7 +155,7 @@ function community_content(App $a, $update = 0) $a->set_pager_itemspage($itemspage_network); - $r = community_getitems($a->pager['start'], $a->pager['itemspage'], $content); + $r = community_getitems($a->pager['start'], $a->pager['itemspage'], $content, $accounttype); if (!DBA::isResult($r)) { info(L10n::t('No results.') . EOL); @@ -164,7 +184,7 @@ function community_content(App $a, $update = 0) } } if (count($s) < $a->pager['itemspage']) { - $r = community_getitems($a->pager['start'] + ($count * $a->pager['itemspage']), $a->pager['itemspage'], $content); + $r = community_getitems($a->pager['start'] + ($count * $a->pager['itemspage']), $a->pager['itemspage'], $content, $accounttype); } } while ((count($s) < $a->pager['itemspage']) && ( ++$count < 50) && (count($r) > 0)); } else { @@ -186,24 +206,40 @@ function community_content(App $a, $update = 0) ]); } -function community_getitems($start, $itemspage, $content) +function community_getitems($start, $itemspage, $content, $accounttype) { if ($content == 'local') { + if (!is_null($accounttype)) { + $sql_accounttype = " AND `user`.`account-type` = ?"; + $values = [$accounttype, $start, $itemspage]; + } else { + $sql_accounttype = ""; + $values = [$start, $itemspage]; + } + $r = DBA::p("SELECT `item`.`uri`, `author`.`url` AS `author-link` FROM `thread` INNER JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall` INNER JOIN `item` ON `item`.`id` = `thread`.`iid` INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated` - AND NOT `thread`.`private` AND `thread`.`wall` AND `thread`.`origin` - ORDER BY `thread`.`commented` DESC LIMIT " . intval($start) . ", " . intval($itemspage) - ); + AND NOT `thread`.`private` AND `thread`.`wall` AND `thread`.`origin` $sql_accounttype + ORDER BY `thread`.`commented` DESC LIMIT ?, ?", $values); return DBA::toArray($r); } elseif ($content == 'global') { + if (!is_null($accounttype)) { + $sql_accounttype = " AND `owner`.`contact-type` = ?"; + $values = [$accounttype, $start, $itemspage]; + } else { + $sql_accounttype = ""; + $values = [$start, $itemspage]; + } + $r = DBA::p("SELECT `uri` FROM `thread` INNER JOIN `item` ON `item`.`id` = `thread`.`iid` INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` - WHERE `thread`.`uid` = 0 AND NOT `author`.`hidden` AND NOT `author`.`blocked` - ORDER BY `thread`.`commented` DESC LIMIT " . intval($start) . ", " . intval($itemspage)); + INNER JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id` + WHERE `thread`.`uid` = 0 AND NOT `author`.`hidden` AND NOT `author`.`blocked` $sql_accounttype + ORDER BY `thread`.`commented` DESC LIMIT ?, ?", $values); return DBA::toArray($r); } diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index f107e12984..88f706385b 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -71,7 +71,7 @@ function dfrn_notify_post(App $a) { $user = DBA::selectFirst('user', ['uid'], ['nickname' => $a->argv[1]]); if (!DBA::isResult($user)) { - logger('User not found for nickname ' . $$a->argv[1]); + logger('User not found for nickname ' . $a->argv[1]); System::xmlExit(3, 'User not found'); } @@ -280,7 +280,7 @@ function dfrn_notify_content(App $a) { $user = DBA::selectFirst('user', ['uid'], ['nickname' => $a->argv[1]]); if (!DBA::isResult($user)) { - logger('User not found for nickname ' . $$a->argv[1]); + logger('User not found for nickname ' . $a->argv[1]); killme(); } diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index 5e5540be14..54539ee03d 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -480,6 +480,12 @@ function dfrn_poll_content(App $a) } if (($type === 'profile') && (strlen($sec))) { + // heluecht: I don't know why we don't fail immediately when the user or contact hadn't been found. + // Since it doesn't make sense to continue from this point on, we now fail here. This should be safe. + if (!DBA::isResult($r)) { + System::httpExit(404, ["title" => L10n::t('Page not found.')]); + } + // URL reply if ($dfrn_version < 2.2) { $s = Network::fetchUrl($r[0]['poll'] diff --git a/mod/display.php b/mod/display.php index 2d32eed5eb..907bf8ebba 100644 --- a/mod/display.php +++ b/mod/display.php @@ -333,35 +333,34 @@ function display_content(App $a, $update = false, $update_uid = 0) return ''; } - $condition = ["`item`.`parent-uri` = (SELECT `parent-uri` FROM `item` WHERE `id` = ?) - AND `item`.`uid` IN (0, ?) " . $sql_extra, $item_id, local_user()]; - $params = ['order' => ['uid', 'parent' => true, 'gravity', 'id']]; - $items_obj = Item::selectForUser(local_user(), [], $condition, $params); + $condition = ["`id` = ? AND `item`.`uid` IN (0, ?) " . $sql_extra, $item_id, local_user()]; + $fields = ['parent-uri', 'body', 'title', 'author-name', 'author-avatar', 'plink']; + $item = Item::selectFirstForUser(local_user(), $fields, $condition); - if (!DBA::isResult($items_obj)) { + if (!DBA::isResult($item)) { notice(L10n::t('Item not found.') . EOL); return $o; } + $item['uri'] = $item['parent-uri']; + if ($unseen) { $condition = ['parent-uri' => $item_parent_uri, 'uid' => local_user(), 'unseen' => true]; Item::update(['unseen' => false], $condition); } - $items = Item::inArray($items_obj); - $conversation_items = conv_sort($items, "`commented`"); - if (!$update) { $o .= ""; } - $o .= conversation($a, $conversation_items, 'display', $update_uid, false, 'commented', local_user()); + + $o .= conversation($a, [$item], 'display', $update_uid, false, 'commented', local_user()); // Preparing the meta header - $description = trim(HTML::toPlaintext(BBCode::convert($items[0]["body"], false), 0, true)); - $title = trim(HTML::toPlaintext(BBCode::convert($items[0]["title"], false), 0, true)); - $author_name = $items[0]["author-name"]; + $description = trim(HTML::toPlaintext(BBCode::convert($item["body"], false), 0, true)); + $title = trim(HTML::toPlaintext(BBCode::convert($item["title"], false), 0, true)); + $author_name = $item["author-name"]; - $image = $a->remove_baseurl($items[0]["author-avatar"]); + $image = $a->remove_baseurl($item["author-avatar"]); if ($title == "") { $title = $author_name; @@ -393,7 +392,7 @@ function display_content(App $a, $update = false, $update_uid = 0) $a->page['htmlhead'] .= ''."\n"; $a->page['htmlhead'] .= ''."\n"; $a->page['htmlhead'] .= ''."\n"; - $a->page['htmlhead'] .= ''."\n"; + $a->page['htmlhead'] .= ''."\n"; // Dublin Core $a->page['htmlhead'] .= ''."\n"; @@ -403,7 +402,7 @@ function display_content(App $a, $update = false, $update_uid = 0) $a->page['htmlhead'] .= ''."\n"; $a->page['htmlhead'] .= ''."\n"; $a->page['htmlhead'] .= ''."\n"; - $a->page['htmlhead'] .= ''."\n"; + $a->page['htmlhead'] .= ''."\n"; $a->page['htmlhead'] .= ''."\n"; $a->page['htmlhead'] .= ''."\n"; // article:tag diff --git a/mod/follow.php b/mod/follow.php index ef2325ad03..627ab52033 100644 --- a/mod/follow.php +++ b/mod/follow.php @@ -16,9 +16,7 @@ use Friendica\Util\Proxy as ProxyUtils; function follow_post(App $a) { if (!local_user()) { - notice(L10n::t('Permission denied.')); - goaway($_SESSION['return_url']); - // NOTREACHED + System::httpExit(403, ['title' => L10n::t('Access denied.')]); } if (isset($_REQUEST['cancel'])) { diff --git a/mod/install.php b/mod/install.php index 11031acf46..fa20fd76cb 100644 --- a/mod/install.php +++ b/mod/install.php @@ -72,7 +72,20 @@ function install_post(App $a) { // connect to db DBA::connect($dbhost, $dbuser, $dbpass, $dbdata); - Install::install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail); + $errors = Install::createConfig($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail); + + if ($errors) { + $a->data['db_failed'] = $errors; + return; + } + + $errors = Install::installDatabaseStructure(); + + if ($errors) { + $a->data['db_failed'] = $errors; + } else { + $a->data['db_installed'] = true; + } return; break; diff --git a/mod/notes.php b/mod/notes.php index 608d01cf8c..68a870e9d6 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -65,26 +65,13 @@ function notes_content(App $a, $update = false) $params = ['order' => ['created' => true], 'limit' => [$a->pager['start'], $a->pager['itemspage']]]; - $r = Item::selectForUser(local_user(), ['id'], $condition, $params); + $r = Item::selectThreadForUser(local_user(), ['uri'], $condition, $params); $count = 0; if (DBA::isResult($r)) { $count = count($r); - $parents_arr = []; - - while ($rr = Item::fetch($r)) { - $parents_arr[] = $rr['id']; - } - DBA::close($r); - - $condition = ['uid' => local_user(), 'parent' => $parents_arr]; - $result = Item::selectForUser(local_user(), [], $condition); - - if (DBA::isResult($result)) { - $items = conv_sort(Item::inArray($result), 'commented'); - $o .= conversation($a, $items, 'notes', $update); - } + $o .= conversation($a, DBA::toArray($r), 'notes', $update); } $o .= alt_pager($a, $count); diff --git a/mod/photos.php b/mod/photos.php index e2682498be..e246c98c3d 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -1093,6 +1093,12 @@ function photos_content(App $a) '$albumselect' => $albumselect, '$permissions' => L10n::t('Permissions'), '$aclselect' => $aclselect_e, + '$lockstate' => is_array($a->user) + && (strlen($a->user['allow_cid']) + || strlen($a->user['allow_gid']) + || strlen($a->user['deny_cid']) + || strlen($a->user['deny_gid']) + ) ? 'lock' : 'unlock', '$alt_uploader' => $ret['addon_text'], '$default_upload_box' => ($ret['default_upload'] ? $default_upload_box : ''), '$default_upload_submit' => ($ret['default_upload'] ? $default_upload_submit : ''), diff --git a/mod/profile.php b/mod/profile.php index 5d7489ebb4..4f2e22d674 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -23,7 +23,7 @@ use Friendica\Util\DateTimeFormat; function profile_init(App $a) { - if (!x($a->page, 'aside')) { + if (empty($a->page['aside'])) { $a->page['aside'] = ''; } @@ -54,15 +54,15 @@ function profile_init(App $a) $blocked = !local_user() && !remote_user() && Config::get('system', 'block_public'); $userblock = !local_user() && !remote_user() && $a->profile['hidewall']; - if (x($a->profile, 'page-flags') && $a->profile['page-flags'] == Contact::PAGE_COMMUNITY) { + if (!empty($a->profile['page-flags']) && $a->profile['page-flags'] == Contact::PAGE_COMMUNITY) { $a->page['htmlhead'] .= ''; } - if (x($a->profile, 'openidserver')) { + if (!empty($a->profile['openidserver'])) { $a->page['htmlhead'] .= '' . "\r\n"; } - if (x($a->profile, 'openid')) { + if (!empty($a->profile['openid'])) { $delegate = strstr($a->profile['openid'], '://') ? $a->profile['openid'] : 'https://' . $a->profile['openid']; $a->page['htmlhead'] .= '' . "\r\n"; } @@ -109,7 +109,7 @@ function profile_content(App $a, $update = 0) } } - if (!x($category)) { + if (empty($category)) { $category = defaults($_GET, 'category', ''); } @@ -140,7 +140,7 @@ function profile_content(App $a, $update = 0) $contact_id = 0; - if (x($_SESSION, 'remote') && is_array($_SESSION['remote'])) { + if (!empty($_SESSION['remote'])) { foreach ($_SESSION['remote'] as $v) { if ($v['uid'] == $a->profile['profile_uid']) { $contact_id = $v['cid']; @@ -171,14 +171,14 @@ function profile_content(App $a, $update = 0) $is_owner = local_user() == $a->profile['profile_uid']; $last_updated_key = "profile:" . $a->profile['profile_uid'] . ":" . local_user() . ":" . remote_user(); - if (x($a->profile, 'hidewall') && !$is_owner && !$remote_contact) { + if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact) { notice(L10n::t('Access to this profile has been restricted.') . EOL); return; } if (!$update) { $tab = false; - if (x($_GET, 'tab')) { + if (!empty($_GET['tab'])) { $tab = notags(trim($_GET['tab'])); } @@ -196,7 +196,7 @@ function profile_content(App $a, $update = 0) $commvisitor = $commpage && $remote_contact; $a->page['aside'] .= posted_date_widget(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'], true); - $a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (x($category) ? xmlify($category) : '')); + $a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (!empty($category) ? xmlify($category) : '')); $a->page['aside'] .= Widget::tagCloud(); if (can_write_wall($a->profile['profile_uid'])) { @@ -227,7 +227,7 @@ function profile_content(App $a, $update = 0) $sql_extra2 = ''; if ($update) { - $last_updated = (x($_SESSION['last_updated'], $last_updated_key) ? $_SESSION['last_updated'][$last_updated_key] : 0); + $last_updated = (!empty($_SESSION['last_updated'][$last_updated_key]) ? $_SESSION['last_updated'][$last_updated_key] : 0); // If the page user is the owner of the page we should query for unseen // items. Otherwise use a timestamp of the last succesful update request. @@ -238,7 +238,7 @@ function profile_content(App $a, $update = 0) $sql_extra4 = " AND `item`.`received` > '" . $gmupdate . "'"; } - $r = q("SELECT distinct(parent) AS `item_id`, `item`.`network` AS `item_network`, `item`.`created` + $items = q("SELECT DISTINCT(`parent-uri`) AS `uri` FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND NOT `contact`.`blocked` AND NOT `contact`.`pending` WHERE `item`.`uid` = %d AND `item`.`visible` AND @@ -250,38 +250,33 @@ function profile_content(App $a, $update = 0) intval($a->profile['profile_uid']), intval(GRAVITY_ACTIVITY) ); - if (!DBA::isResult($r)) { + if (!DBA::isResult($items)) { return ''; } } else { $sql_post_table = ""; - if (x($category)) { + if (!empty($category)) { $sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ", DBA::escape(protect_sprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($a->profile['profile_uid'])); } - if (x($hashtags)) { + if (!empty($hashtags)) { $sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ", DBA::escape(protect_sprintf($hashtags)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), intval($a->profile['profile_uid'])); } - if ($datequery) { + if (!empty($datequery)) { $sql_extra2 .= protect_sprintf(sprintf(" AND `thread`.`created` <= '%s' ", DBA::escape(DateTimeFormat::convert($datequery, 'UTC', date_default_timezone_get())))); } - if ($datequery2) { + if (!empty($datequery2)) { $sql_extra2 .= protect_sprintf(sprintf(" AND `thread`.`created` >= '%s' ", DBA::escape(DateTimeFormat::convert($datequery2, 'UTC', date_default_timezone_get())))); } - // Belongs the profile page to a forum? + // Does the profile page belong to a forum? // If not then we can improve the performance with an additional condition - $r = q("SELECT `uid` FROM `user` WHERE `uid` = %d AND `page-flags` IN (%d, %d)", - intval($a->profile['profile_uid']), - intval(Contact::PAGE_COMMUNITY), - intval(Contact::PAGE_PRVGROUP) - ); - - if (!DBA::isResult($r)) { + $condition = ['uid' => $a->profile['profile_uid'], 'page-flags' => [Contact::PAGE_COMMUNITY, Contact::PAGE_PRVGROUP]]; + if (!DBA::exists('user', $condition)) { $sql_extra3 = sprintf(" AND `thread`.`contact-id` = %d ", intval(intval($a->profile['contact_id']))); } else { $sql_extra3 = ""; @@ -305,7 +300,7 @@ function profile_content(App $a, $update = 0) $pager_sql = sprintf(" LIMIT %d, %d ", intval($a->pager['start']), intval($a->pager['itemspage'])); - $r = q("SELECT `thread`.`iid` AS `item_id`, `thread`.`network` AS `item_network` + $items = q("SELECT `item`.`uri` FROM `thread` STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid` $sql_post_table @@ -321,31 +316,15 @@ function profile_content(App $a, $update = 0) ); } - $parents_arr = []; - $parents_str = ''; - // Set a time stamp for this page. We will make use of it when we // search for new items (update routine) $_SESSION['last_updated'][$last_updated_key] = time(); - if (DBA::isResult($r)) { - foreach ($r as $rr) { - $parents_arr[] = $rr['item_id']; - } - - $condition = ['uid' => $a->profile['profile_uid'], 'parent' => $parents_arr]; - $result = Item::selectForUser($a->profile['profile_uid'], [], $condition); - $items = conv_sort(Item::inArray($result), 'created'); - } else { - $items = []; - } - if ($is_owner && !$update && !Config::get('theme', 'hide_eventlist')) { $o .= Profile::getBirthdays(); $o .= Profile::getEventsReminderHTML(); } - if ($is_owner) { $unseen = Item::exists(['wall' => true, 'unseen' => true, 'uid' => local_user()]); if ($unseen) { diff --git a/mod/redir.php b/mod/redir.php index 727b70d660..3acf960dab 100644 --- a/mod/redir.php +++ b/mod/redir.php @@ -23,7 +23,7 @@ function redir_init(App $a) { } if (!empty($cid)) { - $fields = ['id', 'uid', 'nurl', 'url', 'addr', 'name', 'network', 'poll', 'issued-id', 'dfrn-id', 'duplex']; + $fields = ['id', 'uid', 'nurl', 'url', 'addr', 'name', 'network', 'poll', 'issued-id', 'dfrn-id', 'duplex', 'pending']; $contact = DBA::selectFirst('contact', $fields, ['id' => $cid, 'uid' => [0, local_user()]]); if (!DBA::isResult($contact)) { notice(L10n::t('Contact not found.')); @@ -80,7 +80,7 @@ function redir_init(App $a) { } // Doing remote auth with dfrn. - if (local_user()&& (!empty($contact['dfrn-id']) || !empty($contact['issued-id']))) { + if (local_user() && (!empty($contact['dfrn-id']) || !empty($contact['issued-id'])) && empty($contact['pending'])) { $dfrn_id = $orig_id = (($contact['issued-id']) ? $contact['issued-id'] : $contact['dfrn-id']); if ($contact['duplex'] && $contact['issued-id']) { diff --git a/src/App.php b/src/App.php index d02ea73ca4..55fa517342 100644 --- a/src/App.php +++ b/src/App.php @@ -140,6 +140,8 @@ class App * @brief App constructor. * * @param string $basepath Path to the app base folder + * + * @throws Exception if the Basepath is not usable */ public function __construct($basepath) { diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index 43c79bfb57..a8489e7c8d 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -4,6 +4,7 @@ namespace Friendica\Core\Console; use Asika\SimpleConsole\Console; use Friendica\App; +use Friendica\BaseObject; use Friendica\Core\Config; use Friendica\Core\Install; use Friendica\Core\Theme; @@ -20,19 +21,51 @@ class AutomaticInstallation extends Console return << prepared config file (e.g. "config/local.ini.php" itself) which will override every other config option - except the environment variables) + -s|--savedb Save the DB credentials to the file (if environment variables is used) + -h|--dbhost The host of the mysql database (env MYSQL_HOST) + -p|--dbport The port of the mysql database (env MYSQL_PORT) + -d|--dbdata The name of the mysql database (env MYSQL_DATABASE) + -U|--dbuser The username of the mysql database login (env MYSQL_USER or MYSQL_USERNAME) + -P|--dbpass The password of the mysql database login (env MYSQL_PASSWORD) + -b|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) + -A|--admin The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL) + -T|--tz The timezone of Friendica (env FRIENDICA_TZ) + -L|--lang The language of Friendica (env FRIENDICA_LANG) + +Environment variables + MYSQL_HOST The host of the mysql database (mandatory if mysql and environment is used) + MYSQL_PORT The port of the mysql database + MYSQL_USERNAME|MYSQL_USER The username of the mysql database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb) + MYSQL_PASSWORD The password of the mysql database login + MYSQL_DATABASE The name of the mysql database + FRIENDICA_PHP_PATH The path of the PHP binary + FRIENDICA_ADMIN_MAIL The admin email address of Friendica + FRIENDICA_TZ The timezone of Friendica + FRIENDICA_LANG The langauge of Friendica + +Examples + bin/console autoinstall -f 'input.ini.php + Installs Friendica with the prepared 'input.ini.php' file + + bin/console autoinstall --savedb + Installs Friendica with environment variables and saves them to the 'config/local.ini.php' file + + bin/console autoinstall -h localhost -p 3365 -U user -P passwort1234 -d friendica + Installs Friendica with a local mysql database with credentials + HELP; } @@ -41,18 +74,59 @@ HELP; // Initialise the app $this->out("Initializing setup...\n"); - $a = get_app(); - $db_host = ''; - $db_user = ''; - $db_pass = ''; - $db_data = ''; + // if a config file is set, + $config_file = $this->getOption(['f', 'file']); - $config_file = $this->getOption('f', 'htconfig.php'); + if (!empty($config_file)) { + if ($config_file != 'config/local.ini.php') { + // Copy config file + $this->out("Copying config file...\n"); + if (!copy($config_file, 'config/local.ini.php')) { + throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to 'config/local.ini.php' manually.\n"); + } + } - $this->out("Using config $config_file...\n"); - require_once $config_file; + // load the app after copying the file + $a = BaseObject::getApp(); - Install::setInstallMode(); + $db_host = $a->getConfigValue('database', 'hostname'); + $db_user = $a->getConfigValue('database', 'username'); + $db_pass = $a->getConfigValue('database', 'password'); + $db_data = $a->getConfigValue('database', 'database'); + } else { + // Creating config file + $this->out("Creating config file...\n"); + + // load the app first (for the template engine) + $a = BaseObject::getApp(); + + $save_db = $this->getOption(['s', 'savedb'], false); + + $db_host = $this->getOption(['h', 'dbhost'], ($save_db) ? getenv('MYSQL_HOST') : ''); + $db_port = $this->getOption(['p', 'dbport'], ($save_db) ? getenv('MYSQL_PORT') : null); + $db_data = $this->getOption(['d', 'dbdata'], ($save_db) ? getenv('MYSQL_DATABASE') : ''); + $db_user = $this->getOption(['U', 'dbuser'], ($save_db) ? getenv('MYSQL_USER') . getenv('MYSQL_USERNAME') : ''); + $db_pass = $this->getOption(['P', 'dbpass'], ($save_db) ? getenv('MYSQL_PASSWORD') : ''); + $php_path = $this->getOption(['b', 'phppath'], (!empty('FRIENDICA_PHP_PATH')) ? getenv('FRIENDICA_PHP_PATH') : ''); + $admin_mail = $this->getOption(['A', 'admin'], (!empty('FRIENDICA_ADMIN_MAIL')) ? getenv('FRIENDICA_ADMIN_MAIL') : ''); + $tz = $this->getOption(['T', 'tz'], (!empty('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : ''); + $lang = $this->getOption(['L', 'lang'], (!empty('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : ''); + + // creating config file + $this->out("Creating config file...\n"); + + Install::createConfig( + $php_path, + $db_host, + $db_user, + $db_pass, + $db_data, + $php_path, + $tz, + $lang, + $admin_mail + ); + } $this->out(" Complete!\n\n"); @@ -99,15 +173,9 @@ HELP; Theme::install(Config::get('system', 'theme')); $this->out(" Complete\n\n"); } else { - $this->out(" Theme setting is empty. Please check the file htconfig.php\n\n"); + $this->out(" Theme setting is empty. Please check the file 'config/local.ini.php'\n\n"); } - // Copy config file - $this->out("Saving config file...\n"); - if ($config_file != '.htconfig.php' && !copy($config_file, '.htconfig.php')) { - throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '.htconfig.php' manually.\n"); - } - $this->out(" Complete!\n\n"); $this->out("\nInstallation is finished\n"); return 0; diff --git a/src/Core/Install.php b/src/Core/Install.php index ec33ef9634..e8f014618d 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -1,427 +1,409 @@ -mode = App::MODE_INSTALL; - } - - /** - * Checks the current installation environment. There are optional and mandatory checks. - * - * @param string $phpath Optional path to the PHP binary (Default is 'php') - * - * @return array First element is a list of all checks and their results, - * the second element is a list of passed checks - */ - public static function check($phpath = 'php') - { - $checks = []; - - self::checkFunctions($checks); - - self::checkImagick($checks); - - self::checkLocalIni($checks); - - self::checkSmarty3($checks); - - self::checkKeys($checks); - - self::checkPHP($phpath, $checks); - - self::checkHtAccess($checks); - - $checkspassed = array_reduce($checks, - function ($v, $c) { - if (!empty($c['require'])) { - $v = $v && $c['status']; - } - return $v; - }, - true); - - return array($checks, $checkspassed); - } - - /** - * Executes the installation of Friendica in the given environment. - * - Creates `config/local.ini.php` - * - Installs Database Structure - * - * @param string $urlpath Path based on the URL of Friendica (e.g. '/friendica') - * @param string $dbhost Hostname/IP of the Friendica Database - * @param string $dbuser Username of the Database connection credentials - * @param string $dbpass Password of the Database connection credentials - * @param string $dbdata Name of the Database - * @param string $phpath Path to the PHP-Binary (e.g. 'php' or '/usr/bin/php') - * @param string $timezone Timezone of the Friendica Installaton (e.g. 'Europe/Berlin') - * @param string $language 2-letter ISO 639-1 code (eg. 'en') - * @param string $adminmail Mail-Adress of the administrator - * @param int $rino Rino-enabled (1 = true, 0 = false) - */ - public static function install($urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $phpath, $timezone, $language, $adminmail) - { - $tpl = get_markup_template('local.ini.tpl'); - $txt = replace_macros($tpl,[ - '$dbhost' => $dbhost, - '$dbuser' => $dbuser, - '$dbpass' => $dbpass, - '$dbdata' => $dbdata, - '$timezone' => $timezone, - '$language' => $language, - '$urlpath' => $urlpath, - '$phpath' => $phpath, - '$adminmail' => $adminmail, - ]); - - $result = file_put_contents('config/local.ini.php', $txt); - if (! $result) { - self::getApp()->data['txt'] = $txt; - } - - $errors = self::installDatabaseStructure(); - - if ($errors) { - self::getApp()->data['db_failed'] = $errors; - } else { - self::getApp()->data['db_installed'] = true; - } - } - - /** - * Adds new checks to the array $checks - * - * @param array $checks The list of all checks (by-ref parameter!) - * @param string $title The title of the current check - * @param bool $status 1 = check passed, 0 = check not passed - * @param bool $required 1 = check is mandatory, 0 = check is optional - * @param string $help A help-string for the current check - * @param string $error_msg Optional. A error message, if the current check failed - */ - private static function addCheck(&$checks, $title, $status, $required, $help, $error_msg = "") - { - $checks[] = [ - 'title' => $title, - 'status' => $status, - 'required' => $required, - 'help' => $help, - 'error_msg' => $error_msg, - ]; - } - - /** - * PHP Check - * - * Checks the PHP environment. - * - * - Checks if a PHP binary is available - * - Checks if it is the CLI version - * - Checks if "register_argc_argv" is enabled - * - * @param string $phpath Optional. The Path to the PHP-Binary - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkPHP(&$phpath, &$checks) - { - $passed = $passed2 = $passed3 = false; - if (strlen($phpath)) { - $passed = file_exists($phpath); - } else { - $phpath = trim(shell_exec('which php')); - $passed = strlen($phpath); - } - $help = ""; - if (!$passed) { - $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL; - $help .= L10n::t("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 'Setup the worker'") . EOL; - $help .= EOL . EOL; - $tpl = get_markup_template('field_input.tpl'); - $help .= replace_macros($tpl, [ - '$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')], - ]); - $phpath = ""; - } - - self::addCheck($checks, L10n::t('Command line PHP').($passed?" ($phpath)":""), $passed, false, $help); - - if ($passed) { - $cmd = "$phpath -v"; - $result = trim(shell_exec($cmd)); - $passed2 = (strpos($result, "(cli)") !== false); - list($result) = explode("\n", $result); - $help = ""; - if (!$passed2) { - $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL; - $help .= L10n::t('Found PHP version: ') . "$result"; - } - self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help); - } - - if ($passed2) { - $str = autoname(8); - $cmd = "$phpath testargs.php $str"; - $result = trim(shell_exec($cmd)); - $passed3 = $result == $str; - $help = ""; - if (!$passed3) { - $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL; - $help .= L10n::t('This is required for message delivery to work.'); - } - self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help); - } - } - - /** - * OpenSSL Check - * - * Checks the OpenSSL Environment - * - * - Checks, if the command "openssl_pkey_new" is available - * - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkKeys(&$checks) - { - $help = ''; - $res = false; - - if (function_exists('openssl_pkey_new')) { - $res = openssl_pkey_new([ - 'digest_alg' => 'sha1', - 'private_key_bits' => 4096, - 'encrypt_key' => false - ]); - } - - // Get private key - if (!$res) { - $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL; - $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); - } - self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help); - } - - /** - * PHP functions Check - * - * Checks the following PHP functions - * - libCurl - * - GD Graphics - * - OpenSSL - * - PDO or MySQLi - * - mb_string - * - XML - * - iconv - * - POSIX - * - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkFunctions(&$checks) - { - $ck_funcs = []; - self::addCheck($ck_funcs, L10n::t('libCurl PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('GD graphics PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('mb_string PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('XML PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('iconv PHP module'), true, true, ""); - self::addCheck($ck_funcs, L10n::t('POSIX PHP module'), true, true, ""); - - if (function_exists('apache_get_modules')) { - if (! in_array('mod_rewrite',apache_get_modules())) { - self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.')); - } else { - self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, ""); - } - } - - if (!function_exists('curl_init')) { - $ck_funcs[0]['status'] = false; - $ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.'); - } - if (!function_exists('imagecreatefromjpeg')) { - $ck_funcs[1]['status'] = false; - $ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'); - } - if (!function_exists('openssl_public_encrypt')) { - $ck_funcs[2]['status'] = false; - $ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.'); - } - if (!function_exists('mysqli_connect') && !class_exists('pdo')) { - $ck_funcs[3]['status'] = false; - $ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.'); - } - if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) { - $ck_funcs[3]['status'] = false; - $ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.'); - } - if (!function_exists('mb_strlen')) { - $ck_funcs[4]['status'] = false; - $ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.'); - } - if (!function_exists('iconv_strlen')) { - $ck_funcs[6]['status'] = false; - $ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.'); - } - if (!function_exists('posix_kill')) { - $ck_funcs[7]['status'] = false; - $ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.'); - } - - $checks = array_merge($checks, $ck_funcs); - - // check for XML DOM Documents being able to be generated - try { - $xml = new DOMDocument(); - } catch (Exception $e) { - $ck_funcs[5]['status'] = false; - $ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.'); - } - } - - /** - * "config/local.ini.php" - Check - * - * Checks if it's possible to create the "config/local.ini.php" - * - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkLocalIni(&$checks) - { - $status = true; - $help = ""; - if ((file_exists('config/local.ini.php') && !is_writable('config/local.ini.php')) || - (!file_exists('config/local.ini.php') && !is_writable('.'))) { - - $status = false; - $help = L10n::t('The web installer needs to be able to create a file called "local.ini.php" in the "config" folder of your web server and it is unable to do so.') . EOL; - $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL; - $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named local.ini.php in your Friendica "config" folder.') . EOL; - $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL; - } - - self::addCheck($checks, L10n::t('config/local.ini.php is writable'), $status, false, $help); - - } - - /** - * Smarty3 Template Check - * - * Checks, if the directory of Smarty3 is writable - * - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkSmarty3(&$checks) - { - $status = true; - $help = ""; - if (!is_writable('view/smarty3')) { - - $status = false; - $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL; - $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL; - $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL; - $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL; - } - - self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help); - } - - /** - * ".htaccess" - Check - * - * Checks, if "url_rewrite" is enabled in the ".htaccess" file - * - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkHtAccess(&$checks) - { - $status = true; - $help = ""; - $error_msg = ""; - if (function_exists('curl_init')) { - $test = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite"); - - $url = normalise_link(System::baseUrl() . "/install/testrewrite"); - if ($test['body'] != "ok") { - $test = Network::fetchUrlFull($url); - } - - if ($test['body'] != "ok") { - $status = false; - $help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.'); - $error_msg = []; - $error_msg['head'] = L10n::t('Error message from Curl when fetching'); - $error_msg['url'] = $test['redirect_url']; - $error_msg['msg'] = defaults($test, 'error', ''); - } - self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help, $error_msg); - } else { - // cannot check modrewrite if libcurl is not installed - /// @TODO Maybe issue warning here? - } - } - - /** - * Imagick Check - * - * Checks, if the imagick module is available - * - * @param array $checks The list of all checks (by-ref parameter!) - */ - public static function checkImagick(&$checks) - { - $imagick = false; - $gif = false; - - if (class_exists('Imagick')) { - $imagick = true; - $supported = Image::supportedTypes(); - if (array_key_exists('image/gif', $supported)) { - $gif = true; - } - } - if ($imagick == false) { - self::addCheck($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, ""); - } else { - self::addCheck($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, ""); - if ($imagick) { - self::addCheck($checks, L10n::t('ImageMagick supports GIF'), $gif, false, ""); - } - } - } - - /** - * Installs the Database structure - * - * @return string A possible error - */ - public static function installDatabaseStructure() - { - $errors = DBStructure::update(false, true, true); - - return $errors; - } -} + $dbhost, + '$dbuser' => $dbuser, + '$dbpass' => $dbpass, + '$dbdata' => $dbdata, + '$timezone' => $timezone, + '$language' => $language, + '$urlpath' => $urlpath, + '$phpath' => $phpath, + '$adminmail' => $adminmail, + ]); + + $result = file_put_contents('config/local.ini.php', $txt); + if (!$result) { + self::getApp()->data['txt'] = $txt; + } + + } + + /** + * Adds new checks to the array $checks + * + * @param array $checks The list of all checks (by-ref parameter!) + * @param string $title The title of the current check + * @param bool $status 1 = check passed, 0 = check not passed + * @param bool $required 1 = check is mandatory, 0 = check is optional + * @param string $help A help-string for the current check + * @param string $error_msg Optional. A error message, if the current check failed + */ + private static function addCheck(&$checks, $title, $status, $required, $help, $error_msg = "") + { + $checks[] = [ + 'title' => $title, + 'status' => $status, + 'required' => $required, + 'help' => $help, + 'error_msg' => $error_msg, + ]; + } + + /** + * PHP Check + * + * Checks the PHP environment. + * + * - Checks if a PHP binary is available + * - Checks if it is the CLI version + * - Checks if "register_argc_argv" is enabled + * + * @param string $phpath Optional. The Path to the PHP-Binary + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkPHP($phpath, &$checks) + { + $passed = $passed2 = $passed3 = false; + if (strlen($phpath)) { + $passed = file_exists($phpath); + } else { + $phpath = trim(shell_exec('which php')); + $passed = strlen($phpath); + } + $help = ""; + if (!$passed) { + $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL; + $help .= L10n::t("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 'Setup the worker'") . EOL; + $help .= EOL . EOL; + $tpl = get_markup_template('field_input.tpl'); + $help .= replace_macros($tpl, [ + '$field' => ['phpath', L10n::t('PHP executable path'), $phpath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')], + ]); + $phpath = ""; + } + + self::addCheck($checks, L10n::t('Command line PHP').($passed?" ($phpath)":""), $passed, false, $help); + + if ($passed) { + $cmd = "$phpath -v"; + $result = trim(shell_exec($cmd)); + $passed2 = (strpos($result, "(cli)") !== false); + list($result) = explode("\n", $result); + $help = ""; + if (!$passed2) { + $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL; + $help .= L10n::t('Found PHP version: ') . "$result"; + } + self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help); + } + + if ($passed2) { + $str = autoname(8); + $cmd = "$phpath testargs.php $str"; + $result = trim(shell_exec($cmd)); + $passed3 = $result == $str; + $help = ""; + if (!$passed3) { + $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL; + $help .= L10n::t('This is required for message delivery to work.'); + } + self::addCheck($checks, L10n::t('PHP register_argc_argv'), $passed3, true, $help); + } + } + + /** + * OpenSSL Check + * + * Checks the OpenSSL Environment + * + * - Checks, if the command "openssl_pkey_new" is available + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkKeys(&$checks) + { + $help = ''; + $res = false; + + if (function_exists('openssl_pkey_new')) { + $res = openssl_pkey_new([ + 'digest_alg' => 'sha1', + 'private_key_bits' => 4096, + 'encrypt_key' => false + ]); + } + + // Get private key + if (!$res) { + $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL; + $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); + } + self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help); + } + + /** + * PHP functions Check + * + * Checks the following PHP functions + * - libCurl + * - GD Graphics + * - OpenSSL + * - PDO or MySQLi + * - mb_string + * - XML + * - iconv + * - POSIX + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkFunctions(&$checks) + { + $ck_funcs = []; + self::addCheck($ck_funcs, L10n::t('libCurl PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('GD graphics PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('OpenSSL PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('mb_string PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('XML PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('iconv PHP module'), true, true, ""); + self::addCheck($ck_funcs, L10n::t('POSIX PHP module'), true, true, ""); + + if (function_exists('apache_get_modules')) { + if (! in_array('mod_rewrite',apache_get_modules())) { + self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), false, true, L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.')); + } else { + self::addCheck($ck_funcs, L10n::t('Apache mod_rewrite module'), true, true, ""); + } + } + + if (!function_exists('curl_init')) { + $ck_funcs[0]['status'] = false; + $ck_funcs[0]['help'] = L10n::t('Error: libCURL PHP module required but not installed.'); + } + if (!function_exists('imagecreatefromjpeg')) { + $ck_funcs[1]['status'] = false; + $ck_funcs[1]['help'] = L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'); + } + if (!function_exists('openssl_public_encrypt')) { + $ck_funcs[2]['status'] = false; + $ck_funcs[2]['help'] = L10n::t('Error: openssl PHP module required but not installed.'); + } + if (!function_exists('mysqli_connect') && !class_exists('pdo')) { + $ck_funcs[3]['status'] = false; + $ck_funcs[3]['help'] = L10n::t('Error: PDO or MySQLi PHP module required but not installed.'); + } + if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) { + $ck_funcs[3]['status'] = false; + $ck_funcs[3]['help'] = L10n::t('Error: The MySQL driver for PDO is not installed.'); + } + if (!function_exists('mb_strlen')) { + $ck_funcs[4]['status'] = false; + $ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.'); + } + if (!function_exists('iconv_strlen')) { + $ck_funcs[6]['status'] = false; + $ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.'); + } + if (!function_exists('posix_kill')) { + $ck_funcs[7]['status'] = false; + $ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.'); + } + + $checks = array_merge($checks, $ck_funcs); + + // check for XML DOM Documents being able to be generated + try { + $xml = new DOMDocument(); + } catch (Exception $e) { + $ck_funcs[5]['status'] = false; + $ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.'); + } + } + + /** + * "config/local.ini.php" - Check + * + * Checks if it's possible to create the "config/local.ini.php" + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkLocalIni(&$checks) + { + $status = true; + $help = ""; + if ((file_exists('config/local.ini.php') && !is_writable('config/local.ini.php')) || + (!file_exists('config/local.ini.php') && !is_writable('.'))) { + + $status = false; + $help = L10n::t('The web installer needs to be able to create a file called "local.ini.php" in the "config" folder of your web server and it is unable to do so.') . EOL; + $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL; + $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named local.ini.php in your Friendica "config" folder.') . EOL; + $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL; + } + + self::addCheck($checks, L10n::t('config/local.ini.php is writable'), $status, false, $help); + + } + + /** + * Smarty3 Template Check + * + * Checks, if the directory of Smarty3 is writable + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkSmarty3(&$checks) + { + $status = true; + $help = ""; + if (!is_writable('view/smarty3')) { + + $status = false; + $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL; + $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL; + $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL; + $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL; + } + + self::addCheck($checks, L10n::t('view/smarty3 is writable'), $status, true, $help); + } + + /** + * ".htaccess" - Check + * + * Checks, if "url_rewrite" is enabled in the ".htaccess" file + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkHtAccess(&$checks) + { + $status = true; + $help = ""; + $error_msg = ""; + if (function_exists('curl_init')) { + $test = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite"); + + $url = normalise_link(System::baseUrl() . "/install/testrewrite"); + if ($test['body'] != "ok") { + $test = Network::fetchUrlFull($url); + } + + if ($test['body'] != "ok") { + $status = false; + $help = L10n::t('Url rewrite in .htaccess is not working. Check your server configuration.'); + $error_msg = []; + $error_msg['head'] = L10n::t('Error message from Curl when fetching'); + $error_msg['url'] = $test['redirect_url']; + $error_msg['msg'] = defaults($test, 'error', ''); + } + self::addCheck($checks, L10n::t('Url rewrite is working'), $status, true, $help, $error_msg); + } else { + // cannot check modrewrite if libcurl is not installed + /// @TODO Maybe issue warning here? + } + } + + /** + * Imagick Check + * + * Checks, if the imagick module is available + * + * @param array $checks The list of all checks (by-ref parameter!) + */ + public static function checkImagick(&$checks) + { + $imagick = false; + $gif = false; + + if (class_exists('Imagick')) { + $imagick = true; + $supported = Image::supportedTypes(); + if (array_key_exists('image/gif', $supported)) { + $gif = true; + } + } + if ($imagick == false) { + self::addCheck($checks, L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, ""); + } else { + self::addCheck($checks, L10n::t('ImageMagick PHP extension is installed'), $imagick, false, ""); + if ($imagick) { + self::addCheck($checks, L10n::t('ImageMagick supports GIF'), $gif, false, ""); + } + } + } + + /** + * Installs the Database structure + * + * @return string A possible error + */ + public static function installDatabaseStructure() + { + $errors = DBStructure::update(false, true, true); + + return $errors; + } +} diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php index c994755e7a..d256b9adc1 100644 --- a/src/Core/NotificationsManager.php +++ b/src/Core/NotificationsManager.php @@ -344,6 +344,10 @@ class NotificationsManager extends BaseObject break; case ACTIVITY_FRIEND: + if (!isset($it['object'])) { + logger('Incomplete data: ' . json_encode($it) . ' - ' . System::callstack(20), LOGGER_DEBUG); + } + $xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">"; $obj = XML::parseString($xmlhead . $it['object']); $it['fname'] = $obj->title; diff --git a/src/Core/System.php b/src/Core/System.php index 4e2b63f044..88b89cda27 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -65,7 +65,7 @@ class System extends BaseObject while ($func = array_pop($trace)) { if (!empty($func['class'])) { // Don't show multiple calls from the "dba" class to show the essential parts of the callstack - if ((($previous['class'] != $func['class']) || ($func['class'] != 'dba')) && ($previous['function'] != 'q')) { + if ((($previous['class'] != $func['class']) || ($func['class'] != 'Friendica\Database\DBA')) && ($previous['function'] != 'q')) { $classparts = explode("\\", $func['class']); $callstack[] = array_pop($classparts).'::'.$func['function']; $previous = $func; diff --git a/src/Database/DBA.php b/src/Database/DBA.php index c0b783c29d..bf480dad2c 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -372,7 +372,7 @@ class DBA * @usage Example: $r = p("SELECT * FROM `item` WHERE `guid` = ?", $guid); * * Please only use it with complicated queries. - * For all regular queries please use dba::select or dba::exists + * For all regular queries please use DBA::select or DBA::exists * * @param string $sql SQL statement * @return bool|object statement object or result object @@ -590,7 +590,7 @@ class DBA /** * @brief Executes a prepared statement like UPDATE or INSERT that doesn't return data * - * Please use dba::delete, dba::insert, dba::update, ... instead + * Please use DBA::delete, DBA::insert, DBA::update, ... instead * * @param string $sql SQL statement * @return boolean Was the query successfull? False is returned only if an error occurred @@ -685,7 +685,7 @@ class DBA /** * Fetches the first row * - * Please use dba::selectFirst or dba::exists whenever this is possible. + * Please use DBA::selectFirst or DBA::exists whenever this is possible. * * @brief Fetches the first row * @param string $sql SQL statement @@ -1303,7 +1303,7 @@ class DBA * * $params = array("order" => array("id", "received" => true), "limit" => 10); * - * $data = dba::select($table, $fields, $condition, $params); + * $data = DBA::select($table, $fields, $condition, $params); */ public static function select($table, array $fields = [], array $condition = [], array $params = []) { @@ -1345,7 +1345,7 @@ class DBA * or: * $condition = ["`uid` = ? AND `network` IN (?, ?)", 1, 'dfrn', 'dspr']; * - * $count = dba::count($table, $condition); + * $count = DBA::count($table, $condition); */ public static function count($table, array $condition = []) { @@ -1399,7 +1399,7 @@ class DBA /* Workaround for MySQL Bug #64791. * Never mix data types inside any IN() condition. * In case of mixed types, cast all as string. - * Logic needs to be consistent with dba::p() data types. + * Logic needs to be consistent with DBA::p() data types. */ $is_int = false; $is_alpha = false; @@ -1459,7 +1459,7 @@ class DBA $limit_string = ''; if (isset($params['limit']) && is_int($params['limit'])) { - $limit_string = " LIMIT " . $params['limit']; + $limit_string = " LIMIT " . intval($params['limit']); } if (isset($params['limit']) && is_array($params['limit'])) { @@ -1530,7 +1530,7 @@ class DBA case 'mysqli': // MySQLi offers both a mysqli_stmt and a mysqli_result class. // We should be careful not to assume the object type of $stmt - // because dba::p() has been able to return both types. + // because DBA::p() has been able to return both types. if ($stmt instanceof mysqli_stmt) { $stmt->free_result(); $ret = $stmt->close(); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index f8bfe3f0b8..4c41fdc3fe 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -364,8 +364,13 @@ class Contact extends BaseObject */ public static function markForArchival(array $contact) { - - if (!isset($contact['url'])) { + if (!isset($contact['url']) && !empty($contact['id'])) { + $fields = ['id', 'url', 'archive', 'self', 'term-date']; + $contact = DBA::selectFirst('contact', [], ['id' => $contact['id']]); + if (!DBA::isResult($contact)) { + return; + } + } elseif (!isset($contact['url'])) { logger('Empty contact: ' . json_encode($contact) . ' - ' . System::callstack(20), LOGGER_DEBUG); } @@ -376,10 +381,7 @@ class Contact extends BaseObject if ($contact['term-date'] <= NULL_DATE) { DBA::update('contact', ['term-date' => DateTimeFormat::utcNow()], ['id' => $contact['id']]); - - if ($contact['url'] != '') { - DBA::update('contact', ['term-date' => DateTimeFormat::utcNow()], ['`nurl` = ? AND `term-date` <= ? AND NOT `self`', normalise_link($contact['url']), NULL_DATE]); - } + DBA::update('contact', ['term-date' => DateTimeFormat::utcNow()], ['`nurl` = ? AND `term-date` <= ? AND NOT `self`', normalise_link($contact['url']), NULL_DATE]); } else { /* @todo * We really should send a notification to the owner after 2-3 weeks @@ -397,10 +399,7 @@ class Contact extends BaseObject * the whole process over again. */ DBA::update('contact', ['archive' => 1], ['id' => $contact['id']]); - - if ($contact['url'] != '') { - DBA::update('contact', ['archive' => 1], ['nurl' => normalise_link($contact['url']), 'self' => false]); - } + DBA::update('contact', ['archive' => 1], ['nurl' => normalise_link($contact['url']), 'self' => false]); } } } @@ -423,13 +422,18 @@ class Contact extends BaseObject return; } + if (!isset($contact['url']) && !empty($contact['id'])) { + $fields = ['id', 'url', 'batch']; + $contact = DBA::selectFirst('contact', [], ['id' => $contact['id']]); + if (!DBA::isResult($contact)) { + return; + } + } + // It's a miracle. Our dead contact has inexplicably come back to life. $fields = ['term-date' => NULL_DATE, 'archive' => false]; DBA::update('contact', $fields, ['id' => $contact['id']]); - - 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' => self::ACCOUNT_TYPE_RELAY]; diff --git a/src/Model/Group.php b/src/Model/Group.php index b01fc19701..71f7941189 100644 --- a/src/Model/Group.php +++ b/src/Model/Group.php @@ -273,36 +273,25 @@ class Group extends BaseObject * * @param array $group_ids * @param boolean $check_dead - * @param boolean $use_gcontact * @return array */ - public static function expand($group_ids, $check_dead = false, $use_gcontact = false) + public static function expand($group_ids, $check_dead = false) { if (!is_array($group_ids) || !count($group_ids)) { return []; } - $condition = '`gid` IN (' . substr(str_repeat("?, ", count($group_ids)), 0, -2) . ')'; - if ($use_gcontact) { - $sql = 'SELECT `gcontact`.`id` AS `contact-id` FROM `group_member` - INNER JOIN `contact` ON `contact`.`id` = `group_member`.`contact-id` - INNER JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl` - WHERE ' . $condition; - $param_arr = array_merge([$sql], $group_ids); - $stmt = call_user_func_array('dba::p', $param_arr); - } else { - $condition_array = array_merge([$condition], $group_ids); - $stmt = DBA::select('group_member', ['contact-id'], $condition_array); - } + $stmt = DBA::select('group_member', ['contact-id'], ['gid' => $group_ids]); $return = []; while($group_member = DBA::fetch($stmt)) { $return[] = $group_member['contact-id']; } - if ($check_dead && !$use_gcontact) { + if ($check_dead) { Contact::pruneUnavailable($return); } + return $return; } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 6e4996de54..5bbdf7c4e0 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -933,7 +933,12 @@ class Probe } $prof_data = []; - $prof_data["addr"] = $data["addr"]; + + // The "addr" is not always part of the fetched data + if (!empty($data["addr"])) { + $prof_data["addr"] = $data["addr"]; + } + $prof_data["nick"] = $data["nick"]; $prof_data["dfrn-request"] = $data["request"]; $prof_data["dfrn-confirm"] = $data["confirm"]; diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 8decec0d02..a7f34b7a6d 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -1050,7 +1050,7 @@ class Diaspora return false; } - $contact = dba::selectFirst('contact', [], ['id' => $cid]); + $contact = DBA::selectFirst('contact', [], ['id' => $cid]); if (!DBA::isResult($contact)) { // This here shouldn't happen at all logger("Haven't found a contact for user " . $uid . " and handle " . $handle, LOGGER_DEBUG); @@ -1079,7 +1079,7 @@ class Diaspora // It is deactivated by now, due to side effects. See issue https://github.com/friendica/friendica/pull/4033 // It is not removed by now. Possibly the code is needed? //if (!$is_comment && $contact["rel"] == Contact::FOLLOWER && in_array($importer["page-flags"], array(Contact::PAGE_FREELOVE))) { - // dba::update( + // DBA::update( // 'contact', // array('rel' => Contact::FRIEND, 'writable' => true), // array('id' => $contact["id"], 'uid' => $contact["uid"]) @@ -1821,10 +1821,10 @@ class Diaspora "to_name" => $importer["username"], "to_email" => $importer["email"], "uid" =>$importer["uid"], - "item" => ["subject" => $subject, "body" => $body], + "item" => ["id" => $conversation["id"], "title" => $subject, "subject" => $subject, "body" => $body], "source_name" => $person["name"], "source_link" => $person["url"], - "source_photo" => $person["thumb"], + "source_photo" => $person["photo"], "verb" => ACTIVITY_POST, "otype" => "mail"] ); @@ -3075,7 +3075,7 @@ class Diaspora logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code); if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) { - if (!$no_queue && ($contact['contact-type'] != Contact::ACCOUNT_TYPE_RELAY)) { + if (!$no_queue && !empty($contact['contact-type']) && ($contact['contact-type'] != Contact::ACCOUNT_TYPE_RELAY)) { logger("queue message"); // queue message for redelivery Queue::add($contact["id"], Protocol::DIASPORA, $envelope, $public_batch, $guid); diff --git a/src/Util/Network.php b/src/Util/Network.php index e3b640fa77..49ed03dc3e 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -716,7 +716,7 @@ class Network $url = self::stripTrackingQueryParams($url); if ($depth > 10) { - return($url); + return $url; } $url = trim($url, "'"); @@ -739,16 +739,14 @@ class Network $a->save_timestamp($stamp1, "network"); if ($http_code == 0) { - return($url); + return $url; } - if ((($curl_info['http_code'] == "301") || ($curl_info['http_code'] == "302")) - && (($curl_info['redirect_url'] != "") || ($curl_info['location'] != "")) - ) { - if ($curl_info['redirect_url'] != "") { - return(self::finalUrl($curl_info['redirect_url'], ++$depth, $fetchbody)); - } else { - return(self::finalUrl($curl_info['location'], ++$depth, $fetchbody)); + if (in_array($http_code, ['301', '302'])) { + if (!empty($curl_info['redirect_url'])) { + return self::finalUrl($curl_info['redirect_url'], ++$depth, $fetchbody); + } elseif (!empty($curl_info['location'])) { + return self::finalUrl($curl_info['location'], ++$depth, $fetchbody); } } @@ -759,12 +757,12 @@ class Network // if the file is too large then exit if ($curl_info["download_content_length"] > 1000000) { - return($url); + return $url; } // if it isn't a HTML file then exit - if (($curl_info["content_type"] != "") && !strstr(strtolower($curl_info["content_type"]), "html")) { - return($url); + if (!empty($curl_info["content_type"]) && !strstr(strtolower($curl_info["content_type"]), "html")) { + return $url; } $stamp1 = microtime(true); @@ -783,7 +781,7 @@ class Network $a->save_timestamp($stamp1, "network"); if (trim($body) == "") { - return($url); + return $url; } // Check for redirect in meta elements @@ -806,7 +804,7 @@ class Network $pathinfo = explode(";", $path); foreach ($pathinfo as $value) { if (substr(strtolower($value), 0, 4) == "url=") { - return(self::finalUrl(substr($value, 4), ++$depth)); + return self::finalUrl(substr($value, 4), ++$depth); } } } diff --git a/src/Worker/DBClean.php b/src/Worker/DBClean.php index c839bced19..ca0da954c0 100644 --- a/src/Worker/DBClean.php +++ b/src/Worker/DBClean.php @@ -84,7 +84,7 @@ class DBClean { $r = DBA::p("SELECT `id` FROM `item` WHERE `uid` = 0 AND NOT EXISTS (SELECT `guid` FROM `item` AS `i` WHERE `item`.`guid` = `i`.`guid` AND `i`.`uid` != 0) AND `received` < UTC_TIMESTAMP() - INTERVAL ? DAY AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $days_unclaimed, $last_id); + ORDER BY `id` LIMIT ?", $days_unclaimed, $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found global item orphans: ".$count); @@ -106,7 +106,7 @@ class DBClean { logger("Deleting items without parents. Last ID: ".$last_id); $r = DBA::p("SELECT `id` FROM `item` WHERE NOT EXISTS (SELECT `id` FROM `item` AS `i` WHERE `item`.`parent` = `i`.`id`) - AND `id` >= ? ORDER BY `id` LIMIT ".intval($limit), $last_id); + AND `id` >= ? ORDER BY `id` LIMIT ?", $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found item orphans without parents: ".$count); @@ -132,7 +132,7 @@ class DBClean { logger("Deleting orphaned data from thread table. Last ID: ".$last_id); $r = DBA::p("SELECT `iid` FROM `thread` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `thread`.`iid`) AND `iid` >= ? - ORDER BY `iid` LIMIT ".intval($limit), $last_id); + ORDER BY `iid` LIMIT ?", $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found thread orphans: ".$count); @@ -158,7 +158,7 @@ class DBClean { logger("Deleting orphaned data from notify table. Last ID: ".$last_id); $r = DBA::p("SELECT `iid`, `id` FROM `notify` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `notify`.`iid`) AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); + ORDER BY `id` LIMIT ?", $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found notify orphans: ".$count); @@ -184,7 +184,7 @@ class DBClean { logger("Deleting orphaned data from notify-threads table. Last ID: ".$last_id); $r = DBA::p("SELECT `id` FROM `notify-threads` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `notify-threads`.`master-parent-item`) AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); + ORDER BY `id` LIMIT ?", $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found notify-threads orphans: ".$count); @@ -210,7 +210,7 @@ class DBClean { logger("Deleting orphaned data from sign table. Last ID: ".$last_id); $r = DBA::p("SELECT `iid`, `id` FROM `sign` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `sign`.`iid`) AND `id` >= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id); + ORDER BY `id` LIMIT ?", $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found sign orphans: ".$count); @@ -236,7 +236,7 @@ class DBClean { logger("Deleting orphaned data from term table. Last ID: ".$last_id); $r = DBA::p("SELECT `oid`, `tid` FROM `term` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `term`.`oid`) AND `tid` >= ? - ORDER BY `tid` LIMIT ".intval($limit), $last_id); + ORDER BY `tid` LIMIT ?", $last_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found term orphans: ".$count); @@ -303,7 +303,7 @@ class DBClean { $r = DBA::p("SELECT `id` FROM `item` WHERE `uid` = 0 AND NOT EXISTS (SELECT `guid` FROM `item` AS `i` WHERE `item`.`guid` = `i`.`guid` AND `i`.`uid` != 0) AND `received` < UTC_TIMESTAMP() - INTERVAL 90 DAY AND `id` >= ? AND `id` <= ? - ORDER BY `id` LIMIT ".intval($limit), $last_id, $till_id); + ORDER BY `id` LIMIT ?", $last_id, $till_id, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found global item entries from expired threads: ".$count); @@ -326,7 +326,7 @@ class DBClean { logger("Deleting old conversations. Last created: ".$last_id); $r = DBA::p("SELECT `received`, `item-uri` FROM `conversation` WHERE `received` < UTC_TIMESTAMP() - INTERVAL ? DAY - ORDER BY `received` LIMIT ".intval($limit), $days); + ORDER BY `received` LIMIT ?", $days, $limit); $count = DBA::numRows($r); if ($count > 0) { logger("found old conversations: ".$count); diff --git a/src/Worker/DiscoverPoCo.php b/src/Worker/DiscoverPoCo.php index bf1c2a64a7..e6fc8391ff 100644 --- a/src/Worker/DiscoverPoCo.php +++ b/src/Worker/DiscoverPoCo.php @@ -216,7 +216,7 @@ class DiscoverPoCo $x = Network::fetchUrl(get_server()."/lsearch?p=1&n=500&search=".urlencode($search)); $j = json_decode($x); - if (count($j->results)) { + if (!empty($j->results)) { foreach ($j->results as $jj) { // Check if the contact already exists $exists = q("SELECT `id`, `last_contact`, `last_failure`, `updated` FROM `gcontact` WHERE `nurl` = '%s'", normalise_link($jj->url)); diff --git a/view/js/ajaxupload.js b/view/js/ajaxupload.js index 1c34b11b9e..131ab078e6 100644 --- a/view/js/ajaxupload.js +++ b/view/js/ajaxupload.js @@ -380,7 +380,8 @@ 'cursor' : 'pointer' }); - var div = document.createElement("div"); + var div = document.createElement("div"); + div.setAttribute('class', 'ajaxbutton-wrapper'); addStyles(div, { 'display' : 'block', 'position' : 'absolute', diff --git a/view/templates/profile_edit.tpl b/view/templates/profile_edit.tpl index a25945c689..2363bd3f06 100644 --- a/view/templates/profile_edit.tpl +++ b/view/templates/profile_edit.tpl @@ -439,8 +439,10 @@ + + diff --git a/view/theme/frio/config.php b/view/theme/frio/config.php index 13ab78477c..8bab362ff9 100644 --- a/view/theme/frio/config.php +++ b/view/theme/frio/config.php @@ -15,14 +15,14 @@ function theme_post(App $a) } if (isset($_POST['frio-settings-submit'])) { - PConfig::set(local_user(), 'frio', 'scheme', defaults($_POST, 'frio_scheme')); - PConfig::set(local_user(), 'frio', 'nav_bg', defaults($_POST, 'frio_nav_bg')); - PConfig::set(local_user(), 'frio', 'nav_icon_color', defaults($_POST, 'frio_nav_icon_color')); - PConfig::set(local_user(), 'frio', 'link_color', defaults($_POST, 'frio_link_color')); - PConfig::set(local_user(), 'frio', 'background_color', defaults($_POST, 'frio_background_color')); - PConfig::set(local_user(), 'frio', 'contentbg_transp', defaults($_POST, 'frio_contentbg_transp')); - PConfig::set(local_user(), 'frio', 'background_image', defaults($_POST, 'frio_background_image')); - PConfig::set(local_user(), 'frio', 'bg_image_option', defaults($_POST, 'frio_bg_image_option')); + PConfig::set(local_user(), 'frio', 'scheme', defaults($_POST, 'frio_scheme', '')); + PConfig::set(local_user(), 'frio', 'nav_bg', defaults($_POST, 'frio_nav_bg', '')); + PConfig::set(local_user(), 'frio', 'nav_icon_color', defaults($_POST, 'frio_nav_icon_color', '')); + PConfig::set(local_user(), 'frio', 'link_color', defaults($_POST, 'frio_link_color', '')); + PConfig::set(local_user(), 'frio', 'background_color', defaults($_POST, 'frio_background_color', '')); + PConfig::set(local_user(), 'frio', 'contentbg_transp', defaults($_POST, 'frio_contentbg_transp', '')); + PConfig::set(local_user(), 'frio', 'background_image', defaults($_POST, 'frio_background_image', '')); + PConfig::set(local_user(), 'frio', 'bg_image_option', defaults($_POST, 'frio_bg_image_option', '')); PConfig::set(local_user(), 'frio', 'css_modified', time()); } } diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 6197438179..b96e53fa1a 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -958,6 +958,10 @@ nav.navbar a, nav.navbar .btn-link { color: #fff!important; background-color: $menu_background_hover_color !important; } +#photo-edit-link-wrap { + color: #555; + margin-bottom: 15px; +} .nav-pills.preferences .dropdown .dropdown-toggle, .nav-pills.preferences > li > .btn { color: #bebebe; @@ -1418,6 +1422,15 @@ section #jotOpen { color: #fff; } +.fa.lock:before { + font-family: FontAwesome; + content: "\f023"; +} +.fa.unlock:before { + font-family: FontAwesome; + content: "\f09c"; +} + /* Filebrowser */ .fbrowser .breadcrumb { margin-bottom: 0px; diff --git a/view/theme/frio/js/modal.js b/view/theme/frio/js/modal.js index 46bb1e5143..2b3059eaf1 100644 --- a/view/theme/frio/js/modal.js +++ b/view/theme/frio/js/modal.js @@ -12,7 +12,7 @@ $(document).ready(function(){ // with AjaxUpload. $(".fbrowser").remove(); // Remove the AjaxUpload element. - $("[name=userfile]").parent().remove(); + $(".ajaxbutton-wrapper").remove(); }); // Clear bs modal on close. diff --git a/view/theme/frio/php/default.php b/view/theme/frio/php/default.php index 28f44504b6..cb68328531 100644 --- a/view/theme/frio/php/default.php +++ b/view/theme/frio/php/default.php @@ -44,7 +44,7 @@ if (!isset($minimal)) { $uid = Profile::getThemeUid(); } $scheme = PConfig::get($uid, 'frio', 'scheme', PConfig::get($uid, 'frio', 'schema')); - if (($scheme) && ($scheme != '---')) { + if ($scheme && ($scheme != '---')) { if (file_exists('view/theme/frio/scheme/' . $scheme . '.php')) { $schemefile = 'view/theme/frio/scheme/' . $scheme . '.php'; require_once $schemefile; @@ -52,7 +52,7 @@ if (!isset($minimal)) { } else { $nav_bg = PConfig::get($uid, 'frio', 'nav_bg'); } - if (!$nav_bg) { + if (empty($nav_bg)) { $nav_bg = "#708fa0"; } echo ' diff --git a/view/theme/frio/templates/like_noshare.tpl b/view/theme/frio/templates/like_noshare.tpl index d22804dcda..deb2383f4b 100644 --- a/view/theme/frio/templates/like_noshare.tpl +++ b/view/theme/frio/templates/like_noshare.tpl @@ -1,8 +1,13 @@
- + {{if $nolike}} - + + {{/if}}
diff --git a/view/theme/frio/templates/photo_view.tpl b/view/theme/frio/templates/photo_view.tpl index ce058f507e..e610926d4c 100644 --- a/view/theme/frio/templates/photo_view.tpl +++ b/view/theme/frio/templates/photo_view.tpl @@ -4,16 +4,30 @@
-

{{$album.1}}

- -