]> git.mxchange.org Git - friendica.git/blob - mod/poco.php
Merge pull request #11346 from MrPetovan/bug/11343-memcached-bad-key
[friendica.git] / mod / poco.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  * @see https://web.archive.org/web/20160405005550/http://portablecontacts.net/draft-spec.html
21  */
22
23 use Friendica\App;
24 use Friendica\Content\Text\BBCode;
25 use Friendica\Core\Logger;
26 use Friendica\Core\Protocol;
27 use Friendica\Core\Renderer;
28 use Friendica\Database\DBA;
29 use Friendica\DI;
30 use Friendica\Util\DateTimeFormat;
31 use Friendica\Util\Strings;
32 use Friendica\Util\XML;
33
34 function poco_init(App $a) {
35         if (intval(DI::config()->get('system', 'block_public')) || (DI::config()->get('system', 'block_local_dir'))) {
36                 throw new \Friendica\Network\HTTPException\ForbiddenException();
37         }
38
39         if (DI::args()->getArgc() > 1) {
40                 // Only the system mode is supported 
41                 throw new \Friendica\Network\HTTPException\NotFoundException();
42         }
43
44         $format = ($_GET['format'] ?? '') ?: 'json';
45
46         $totalResults = DBA::count('profile', ['net-publish' => true]);
47         if ($totalResults == 0) {
48                 throw new \Friendica\Network\HTTPException\ForbiddenException();
49         }
50
51         if (!empty($_GET['startIndex'])) {
52                 $startIndex = intval($_GET['startIndex']);
53         } else {
54                 $startIndex = 0;
55         }
56         $itemsPerPage = (!empty($_GET['count']) ? intval($_GET['count']) : $totalResults);
57
58         Logger::info("Start system mode query");
59         $contacts = DBA::selectToArray('owner-view', [], ['net-publish' => true], ['limit' => [$startIndex, $itemsPerPage]]);
60
61         Logger::info("Query done");
62
63         $ret = [];
64         if (!empty($_GET['sorted'])) {
65                 $ret['sorted'] = false;
66         }
67         if (!empty($_GET['filtered'])) {
68                 $ret['filtered'] = false;
69         }
70         if (!empty($_GET['updatedSince'])) {
71                 $ret['updatedSince'] = false;
72         }
73         $ret['startIndex']   = (int) $startIndex;
74         $ret['itemsPerPage'] = (int) $itemsPerPage;
75         $ret['totalResults'] = (int) $totalResults;
76         $ret['entry']        = [];
77
78         $fields_ret = [
79                 'id' => false,
80                 'displayName' => false,
81                 'urls' => false,
82                 'updated' => false,
83                 'preferredUsername' => false,
84                 'photos' => false,
85                 'aboutMe' => false,
86                 'currentLocation' => false,
87                 'network' => false,
88                 'tags' => false,
89                 'address' => false,
90                 'contactType' => false,
91                 'generation' => false
92         ];
93
94         if (empty($_GET['fields'])) {
95                 foreach ($fields_ret as $k => $v) {
96                         $fields_ret[$k] = true;
97                 }
98         } else {
99                 $fields_req = explode(',', $_GET['fields']);
100                 foreach ($fields_req as $f) {
101                         $fields_ret[trim($f)] = true;
102                 }
103         }
104
105         if (!is_array($contacts)) {
106                 throw new \Friendica\Network\HTTPException\InternalServerErrorException();
107         }
108
109         if (DBA::isResult($contacts)) {
110                 foreach ($contacts as $contact) {
111                         if (!isset($contact['updated'])) {
112                                 $contact['updated'] = '';
113                         }
114
115                         if (! isset($contact['generation'])) {
116                                 $contact['generation'] = 1;
117                         }
118
119                         if (($contact['keywords'] == "") && isset($contact['pub_keywords'])) {
120                                 $contact['keywords'] = $contact['pub_keywords'];
121                         }
122                         if (isset($contact['account-type'])) {
123                                 $contact['contact-type'] = $contact['account-type'];
124                         }
125
126                         $cacheKey = 'about:' . $contact['nick'] . ':' . DateTimeFormat::utc($contact['updated'], DateTimeFormat::ATOM);
127                         $about = DI::cache()->get($cacheKey);
128                         if (is_null($about)) {
129                                 $about = BBCode::convertForUriId($contact['uri-id'], $contact['about']);
130                                 DI::cache()->set($cacheKey, $about);
131                         }
132
133                         // Non connected persons can only see the keywords of a Diaspora account
134                         if ($contact['network'] == Protocol::DIASPORA) {
135                                 $contact['location'] = "";
136                                 $about = "";
137                         }
138
139                         $entry = [];
140                         if ($fields_ret['id']) {
141                                 $entry['id'] = (int)$contact['id'];
142                         }
143                         if ($fields_ret['displayName']) {
144                                 $entry['displayName'] = $contact['name'];
145                         }
146                         if ($fields_ret['aboutMe']) {
147                                 $entry['aboutMe'] = $about;
148                         }
149                         if ($fields_ret['currentLocation']) {
150                                 $entry['currentLocation'] = $contact['location'];
151                         }
152                         if ($fields_ret['generation']) {
153                                 $entry['generation'] = (int)$contact['generation'];
154                         }
155                         if ($fields_ret['urls']) {
156                                 $entry['urls'] = [['value' => $contact['url'], 'type' => 'profile']];
157                                 if ($contact['addr'] && ($contact['network'] !== Protocol::MAIL)) {
158                                         $entry['urls'][] = ['value' => 'acct:' . $contact['addr'], 'type' => 'webfinger'];
159                                 }
160                         }
161                         if ($fields_ret['preferredUsername']) {
162                                 $entry['preferredUsername'] = $contact['nick'];
163                         }
164                         if ($fields_ret['updated']) {
165                                 $entry['updated'] = $contact['success_update'];
166
167                                 if ($contact['name-date'] > $entry['updated']) {
168                                         $entry['updated'] = $contact['name-date'];
169                                 }
170                                 if ($contact['uri-date'] > $entry['updated']) {
171                                         $entry['updated'] = $contact['uri-date'];
172                                 }
173                                 if ($contact['avatar-date'] > $entry['updated']) {
174                                         $entry['updated'] = $contact['avatar-date'];
175                                 }
176                                 $entry['updated'] = date("c", strtotime($entry['updated']));
177                         }
178                         if ($fields_ret['photos']) {
179                                 $entry['photos'] = [['value' => $contact['photo'], 'type' => 'profile']];
180                         }
181                         if ($fields_ret['network']) {
182                                 $entry['network'] = $contact['network'];
183                                 if ($entry['network'] == Protocol::STATUSNET) {
184                                         $entry['network'] = Protocol::OSTATUS;
185                                 }
186                                 if (($entry['network'] == "") && ($contact['self'])) {
187                                         $entry['network'] = Protocol::DFRN;
188                                 }
189                         }
190                         if ($fields_ret['tags']) {
191                                 $tags = str_replace(",", " ", $contact['keywords']);
192                                 $tags = explode(" ", $tags);
193
194                                 $cleaned = [];
195                                 foreach ($tags as $tag) {
196                                         $tag = trim(strtolower($tag));
197                                         if ($tag != "") {
198                                                 $cleaned[] = $tag;
199                                         }
200                                 }
201
202                                 $entry['tags'] = [$cleaned];
203                         }
204                         if ($fields_ret['address']) {
205                                 $entry['address'] = [];
206
207                                 if (isset($contact['locality'])) {
208                                         $entry['address']['locality'] = $contact['locality'];
209                                 }
210
211                                 if (isset($contact['region'])) {
212                                         $entry['address']['region'] = $contact['region'];
213                                 }
214
215                                 if (isset($contact['country'])) {
216                                         $entry['address']['country'] = $contact['country'];
217                                 }
218                         }
219
220                         if ($fields_ret['contactType']) {
221                                 $entry['contactType'] = intval($contact['contact-type']);
222                         }
223                         $ret['entry'][] = $entry;
224                 }
225         } else {
226                 $ret['entry'][] = [];
227         }
228
229         Logger::info("End of poco");
230
231         if ($format === 'xml') {
232                 header('Content-type: text/xml');
233                 echo Renderer::replaceMacros(Renderer::getMarkupTemplate('poco_xml.tpl'), XML::arrayEscape(['$response' => $ret]));
234                 exit();
235         }
236         if ($format === 'json') {
237                 header('Content-type: application/json');
238                 echo json_encode($ret);
239                 exit();
240         } else {
241                 throw new \Friendica\Network\HTTPException\InternalServerErrorException();
242         }
243 }