|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file contains the files necessary to display news as an XML feed. |
|
5
|
|
|
* |
|
6
|
|
|
* Simple Machines Forum (SMF) |
|
7
|
|
|
* |
|
8
|
|
|
* @package SMF |
|
9
|
|
|
* @author Simple Machines http://www.simplemachines.org |
|
10
|
|
|
* @copyright 2017 Simple Machines and individual contributors |
|
11
|
|
|
* @license http://www.simplemachines.org/about/smf/license.php BSD |
|
12
|
|
|
* |
|
13
|
|
|
* @version 2.1 Beta 4 |
|
14
|
|
|
*/ |
|
15
|
|
|
|
|
16
|
|
|
if (!defined('SMF')) |
|
17
|
|
|
die('No direct access...'); |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* Outputs xml data representing recent information or a profile. |
|
21
|
|
|
* Can be passed 4 subactions which decide what is output: |
|
22
|
|
|
* 'recent' for recent posts, |
|
23
|
|
|
* 'news' for news topics, |
|
24
|
|
|
* 'members' for recently registered members, |
|
25
|
|
|
* 'profile' for a member's profile. |
|
26
|
|
|
* To display a member's profile, a user id has to be given. (;u=1) |
|
27
|
|
|
* Outputs an rss feed instead of a proprietary one if the 'type' $_GET |
|
28
|
|
|
* parameter is 'rss' or 'rss2'. |
|
29
|
|
|
* Accessed via ?action=.xml. |
|
30
|
|
|
* Does not use any templates, sub templates, or template layers. |
|
31
|
|
|
* |
|
32
|
|
|
* @uses Stats language file. |
|
33
|
|
|
*/ |
|
34
|
|
|
function ShowXmlFeed() |
|
35
|
|
|
{ |
|
36
|
|
|
global $board, $board_info, $context, $scripturl, $boardurl, $txt, $modSettings, $user_info; |
|
37
|
|
|
global $query_this_board, $smcFunc, $forum_version, $settings; |
|
38
|
|
|
|
|
39
|
|
|
// If it's not enabled, die. |
|
40
|
|
|
if (empty($modSettings['xmlnews_enable'])) |
|
41
|
|
|
obExit(false); |
|
42
|
|
|
|
|
43
|
|
|
loadLanguage('Stats'); |
|
44
|
|
|
|
|
45
|
|
|
// Default to latest 5. No more than 255, please. |
|
46
|
|
|
$_GET['limit'] = empty($_GET['limit']) || (int) $_GET['limit'] < 1 ? 5 : min((int) $_GET['limit'], 255); |
|
47
|
|
|
|
|
48
|
|
|
// Some general metadata for this feed. We'll change some of these values below. |
|
49
|
|
|
$feed_meta = array( |
|
50
|
|
|
'title' => '', |
|
51
|
|
|
'desc' => $txt['xml_rss_desc'], |
|
52
|
|
|
'author' => $context['forum_name'], |
|
53
|
|
|
'source' => $scripturl, |
|
54
|
|
|
'rights' => '© ' . date('Y') . ' ' . $context['forum_name'], |
|
55
|
|
|
'icon' => !empty($settings['og_image']) ? $settings['og_image'] : $boardurl . '/favicon.ico', |
|
56
|
|
|
'language' => !empty($txt['lang_locale']) ? str_replace("_", "-", substr($txt['lang_locale'], 0, strcspn($txt['lang_locale'], "."))) : 'en', |
|
|
|
|
|
|
57
|
|
|
); |
|
58
|
|
|
|
|
59
|
|
|
// Handle the cases where a board, boards, or category is asked for. |
|
60
|
|
|
$query_this_board = 1; |
|
61
|
|
|
$context['optimize_msg'] = array( |
|
62
|
|
|
'highest' => 'm.id_msg <= b.id_last_msg', |
|
63
|
|
|
); |
|
64
|
|
|
if (!empty($_REQUEST['c']) && empty($board)) |
|
65
|
|
|
{ |
|
66
|
|
|
$_REQUEST['c'] = explode(',', $_REQUEST['c']); |
|
67
|
|
|
foreach ($_REQUEST['c'] as $i => $c) |
|
68
|
|
|
$_REQUEST['c'][$i] = (int) $c; |
|
69
|
|
|
|
|
70
|
|
|
if (count($_REQUEST['c']) == 1) |
|
71
|
|
|
{ |
|
72
|
|
|
$request = $smcFunc['db_query']('', ' |
|
73
|
|
|
SELECT name |
|
74
|
|
|
FROM {db_prefix}categories |
|
75
|
|
|
WHERE id_cat = {int:current_category}', |
|
76
|
|
|
array( |
|
77
|
|
|
'current_category' => (int) $_REQUEST['c'][0], |
|
78
|
|
|
) |
|
79
|
|
|
); |
|
80
|
|
|
list ($feed_meta['title']) = $smcFunc['db_fetch_row']($request); |
|
81
|
|
|
$smcFunc['db_free_result']($request); |
|
82
|
|
|
|
|
83
|
|
|
$feed_meta['title'] = ' - ' . strip_tags($feed_meta['title']); |
|
84
|
|
|
} |
|
85
|
|
|
|
|
86
|
|
|
$request = $smcFunc['db_query']('', ' |
|
87
|
|
|
SELECT b.id_board, b.num_posts |
|
88
|
|
|
FROM {db_prefix}boards AS b |
|
89
|
|
|
WHERE b.id_cat IN ({array_int:current_category_list}) |
|
90
|
|
|
AND {query_see_board}', |
|
91
|
|
|
array( |
|
92
|
|
|
'current_category_list' => $_REQUEST['c'], |
|
93
|
|
|
) |
|
94
|
|
|
); |
|
95
|
|
|
$total_cat_posts = 0; |
|
96
|
|
|
$boards = array(); |
|
97
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
98
|
|
|
{ |
|
99
|
|
|
$boards[] = $row['id_board']; |
|
100
|
|
|
$total_cat_posts += $row['num_posts']; |
|
101
|
|
|
} |
|
102
|
|
|
$smcFunc['db_free_result']($request); |
|
103
|
|
|
|
|
104
|
|
|
if (!empty($boards)) |
|
105
|
|
|
$query_this_board = 'b.id_board IN (' . implode(', ', $boards) . ')'; |
|
106
|
|
|
|
|
107
|
|
|
// Try to limit the number of messages we look through. |
|
108
|
|
View Code Duplication |
if ($total_cat_posts > 100 && $total_cat_posts > $modSettings['totalMessages'] / 15) |
|
109
|
|
|
$context['optimize_msg']['lowest'] = 'm.id_msg >= ' . max(0, $modSettings['maxMsgID'] - 400 - $_GET['limit'] * 5); |
|
110
|
|
|
} |
|
111
|
|
|
elseif (!empty($_REQUEST['boards'])) |
|
112
|
|
|
{ |
|
113
|
|
|
$_REQUEST['boards'] = explode(',', $_REQUEST['boards']); |
|
114
|
|
|
foreach ($_REQUEST['boards'] as $i => $b) |
|
115
|
|
|
$_REQUEST['boards'][$i] = (int) $b; |
|
116
|
|
|
|
|
117
|
|
|
$request = $smcFunc['db_query']('', ' |
|
118
|
|
|
SELECT b.id_board, b.num_posts, b.name |
|
119
|
|
|
FROM {db_prefix}boards AS b |
|
120
|
|
|
WHERE b.id_board IN ({array_int:board_list}) |
|
121
|
|
|
AND {query_see_board} |
|
122
|
|
|
LIMIT {int:limit}', |
|
123
|
|
|
array( |
|
124
|
|
|
'board_list' => $_REQUEST['boards'], |
|
125
|
|
|
'limit' => count($_REQUEST['boards']), |
|
126
|
|
|
) |
|
127
|
|
|
); |
|
128
|
|
|
|
|
129
|
|
|
// Either the board specified doesn't exist or you have no access. |
|
130
|
|
|
$num_boards = $smcFunc['db_num_rows']($request); |
|
131
|
|
|
if ($num_boards == 0) |
|
132
|
|
|
fatal_lang_error('no_board'); |
|
133
|
|
|
|
|
134
|
|
|
$total_posts = 0; |
|
135
|
|
|
$boards = array(); |
|
136
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
137
|
|
|
{ |
|
138
|
|
|
if ($num_boards == 1) |
|
139
|
|
|
$feed_meta['title'] = ' - ' . strip_tags($row['name']); |
|
140
|
|
|
|
|
141
|
|
|
$boards[] = $row['id_board']; |
|
142
|
|
|
$total_posts += $row['num_posts']; |
|
143
|
|
|
} |
|
144
|
|
|
$smcFunc['db_free_result']($request); |
|
145
|
|
|
|
|
146
|
|
|
if (!empty($boards)) |
|
147
|
|
|
$query_this_board = 'b.id_board IN (' . implode(', ', $boards) . ')'; |
|
148
|
|
|
|
|
149
|
|
|
// The more boards, the more we're going to look through... |
|
150
|
|
View Code Duplication |
if ($total_posts > 100 && $total_posts > $modSettings['totalMessages'] / 12) |
|
151
|
|
|
$context['optimize_msg']['lowest'] = 'm.id_msg >= ' . max(0, $modSettings['maxMsgID'] - 500 - $_GET['limit'] * 5); |
|
152
|
|
|
} |
|
153
|
|
|
elseif (!empty($board)) |
|
154
|
|
|
{ |
|
155
|
|
|
$request = $smcFunc['db_query']('', ' |
|
156
|
|
|
SELECT num_posts |
|
157
|
|
|
FROM {db_prefix}boards |
|
158
|
|
|
WHERE id_board = {int:current_board} |
|
159
|
|
|
LIMIT 1', |
|
160
|
|
|
array( |
|
161
|
|
|
'current_board' => $board, |
|
162
|
|
|
) |
|
163
|
|
|
); |
|
164
|
|
|
list ($total_posts) = $smcFunc['db_fetch_row']($request); |
|
165
|
|
|
$smcFunc['db_free_result']($request); |
|
166
|
|
|
|
|
167
|
|
|
$feed_meta['title'] = ' - ' . strip_tags($board_info['name']); |
|
168
|
|
|
$feed_meta['source'] .= '?board=' . $board . '.0' ; |
|
169
|
|
|
|
|
170
|
|
|
$query_this_board = 'b.id_board = ' . $board; |
|
171
|
|
|
|
|
172
|
|
|
// Try to look through just a few messages, if at all possible. |
|
173
|
|
View Code Duplication |
if ($total_posts > 80 && $total_posts > $modSettings['totalMessages'] / 10) |
|
174
|
|
|
$context['optimize_msg']['lowest'] = 'm.id_msg >= ' . max(0, $modSettings['maxMsgID'] - 600 - $_GET['limit'] * 5); |
|
175
|
|
|
} |
|
176
|
|
|
else |
|
177
|
|
|
{ |
|
178
|
|
|
$query_this_board = '{query_see_board}' . (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 ? ' |
|
179
|
|
|
AND b.id_board != ' . $modSettings['recycle_board'] : ''); |
|
180
|
|
|
$context['optimize_msg']['lowest'] = 'm.id_msg >= ' . max(0, $modSettings['maxMsgID'] - 100 - $_GET['limit'] * 5); |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
// Show in rss or proprietary format? |
|
184
|
|
|
$xml_format = isset($_GET['type']) && in_array($_GET['type'], array('smf', 'rss', 'rss2', 'atom', 'rdf')) ? $_GET['type'] : 'rss2'; |
|
185
|
|
|
|
|
186
|
|
|
// @todo Birthdays? |
|
|
|
|
|
|
187
|
|
|
|
|
188
|
|
|
// List all the different types of data they can pull. |
|
189
|
|
|
$subActions = array( |
|
190
|
|
|
'recent' => array('getXmlRecent', 'recent-post'), |
|
191
|
|
|
'news' => array('getXmlNews', 'article'), |
|
192
|
|
|
'members' => array('getXmlMembers', 'member'), |
|
193
|
|
|
'profile' => array('getXmlProfile', null), |
|
194
|
|
|
); |
|
195
|
|
|
|
|
196
|
|
|
// Easy adding of sub actions |
|
197
|
|
|
call_integration_hook('integrate_xmlfeeds', array(&$subActions)); |
|
198
|
|
|
|
|
199
|
|
|
if (empty($_GET['sa']) || !isset($subActions[$_GET['sa']])) |
|
200
|
|
|
$_GET['sa'] = 'recent'; |
|
201
|
|
|
|
|
202
|
|
|
// We only want some information, not all of it. |
|
203
|
|
|
$cachekey = array($xml_format, $_GET['action'], $_GET['limit'], $_GET['sa']); |
|
204
|
|
|
foreach (array('board', 'boards', 'c') as $var) |
|
205
|
|
|
if (isset($_REQUEST[$var])) |
|
206
|
|
|
$cachekey[] = $_REQUEST[$var]; |
|
207
|
|
|
$cachekey = md5($smcFunc['json_encode']($cachekey) . (!empty($query_this_board) ? $query_this_board : '')); |
|
208
|
|
|
$cache_t = microtime(); |
|
209
|
|
|
|
|
210
|
|
|
// Get the associative array representing the xml. |
|
211
|
|
|
if (!empty($modSettings['cache_enable']) && (!$user_info['is_guest'] || $modSettings['cache_enable'] >= 3)) |
|
212
|
|
|
$xml_data = cache_get_data('xmlfeed-' . $xml_format . ':' . ($user_info['is_guest'] ? '' : $user_info['id'] . '-') . $cachekey, 240); |
|
213
|
|
|
if (empty($xml_data)) |
|
214
|
|
|
{ |
|
215
|
|
|
$call = call_helper($subActions[$_GET['sa']][0], true); |
|
216
|
|
|
|
|
217
|
|
|
if (!empty($call)) |
|
218
|
|
|
$xml_data = call_user_func($call, $xml_format); |
|
219
|
|
|
|
|
220
|
|
|
if (!empty($modSettings['cache_enable']) && (($user_info['is_guest'] && $modSettings['cache_enable'] >= 3) |
|
221
|
|
|
|| (!$user_info['is_guest'] && (array_sum(explode(' ', microtime())) - array_sum(explode(' ', $cache_t)) > 0.2)))) |
|
222
|
|
|
cache_put_data('xmlfeed-' . $xml_format . ':' . ($user_info['is_guest'] ? '' : $user_info['id'] . '-') . $cachekey, $xml_data, 240); |
|
|
|
|
|
|
223
|
|
|
} |
|
224
|
|
|
|
|
225
|
|
|
$feed_meta['title'] = $smcFunc['htmlspecialchars'](strip_tags($context['forum_name'])) . (isset($feed_meta['title']) ? $feed_meta['title'] : ''); |
|
226
|
|
|
|
|
227
|
|
|
// Allow mods to add extra namespaces and tags to the feed/channel |
|
228
|
|
|
$namespaces = array( |
|
229
|
|
|
'rss' => array(), |
|
230
|
|
|
'rss2' => array('atom' => 'http://www.w3.org/2005/Atom'), |
|
231
|
|
|
'atom' => array('' => 'http://www.w3.org/2005/Atom'), |
|
232
|
|
|
'rdf' => array( |
|
233
|
|
|
'' => 'http://purl.org/rss/1.0/', |
|
234
|
|
|
'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', |
|
235
|
|
|
'dc' => 'http://purl.org/dc/elements/1.1/', |
|
236
|
|
|
), |
|
237
|
|
|
'smf' => array( |
|
238
|
|
|
'' => 'http://www.simplemachines.org/xml/' . $_GET['sa'], |
|
239
|
|
|
'smf' => 'http://www.simplemachines.org/', |
|
240
|
|
|
), |
|
241
|
|
|
); |
|
242
|
|
|
$extraFeedTags = array( |
|
243
|
|
|
'rss' => array(), |
|
244
|
|
|
'rss2' => array(), |
|
245
|
|
|
'atom' => array(), |
|
246
|
|
|
'rdf' => array(), |
|
247
|
|
|
'smf' => array(), |
|
248
|
|
|
); |
|
249
|
|
|
|
|
250
|
|
|
// Allow mods to specify any keys that need special handling |
|
251
|
|
|
$forceCdataKeys = array(); |
|
252
|
|
|
$nsKeys = array(); |
|
253
|
|
|
|
|
254
|
|
|
// Remember this, just in case... |
|
255
|
|
|
$orig_feed_meta = $feed_meta; |
|
256
|
|
|
|
|
257
|
|
|
// If mods want to do somthing with this feed, let them do that now. |
|
258
|
|
|
// Provide the feed's data, metadata, namespaces, extra feed-level tags, keys that need special handling, the feed format, and the requested subaction |
|
259
|
|
|
call_integration_hook('integrate_xml_data', array(&$xml_data, &$feed_meta, &$namespaces, &$extraFeedTags, &$forceCdataKeys, &$nsKeys, $xml_format, $_GET['sa'])); |
|
260
|
|
|
|
|
261
|
|
|
// These can't be empty |
|
262
|
|
|
foreach (array('title', 'desc', 'source') as $mkey) |
|
263
|
|
|
$feed_meta[$mkey] = !empty($feed_meta[$mkey]) ? $feed_meta[$mkey] : $orig_feed_meta[$mkey]; |
|
264
|
|
|
|
|
265
|
|
|
// Sanitize basic feed metadata values |
|
266
|
|
|
foreach ($feed_meta as $mkey => $mvalue) |
|
267
|
|
|
$feed_meta[$mkey] = cdata_parse(strip_tags(fix_possible_url($feed_meta[$mkey]))); |
|
268
|
|
|
|
|
269
|
|
|
$ns_string = ''; |
|
270
|
|
|
if (!empty($namespaces[$xml_format])) |
|
271
|
|
|
{ |
|
272
|
|
|
foreach ($namespaces[$xml_format] as $nsprefix => $nsurl) |
|
273
|
|
|
$ns_string .= ' xmlns' . ($nsprefix !== '' ? ':' : '') . $nsprefix . '="' . $nsurl . '"'; |
|
274
|
|
|
} |
|
275
|
|
|
|
|
276
|
|
|
$extraFeedTags_string = ''; |
|
277
|
|
|
if (!empty($extraFeedTags[$xml_format])) |
|
278
|
|
|
{ |
|
279
|
|
|
$indent = "\t" . ($xml_format !== 'atom' ? "\t" : ''); |
|
280
|
|
|
foreach ($extraFeedTags[$xml_format] as $extraTag) |
|
281
|
|
|
$extraFeedTags_string .= "\n" . $indent . $extraTag; |
|
282
|
|
|
} |
|
283
|
|
|
|
|
284
|
|
|
// This is an xml file.... |
|
285
|
|
|
ob_end_clean(); |
|
286
|
|
|
if (!empty($modSettings['enableCompressedOutput'])) |
|
287
|
|
|
@ob_start('ob_gzhandler'); |
|
|
|
|
|
|
288
|
|
|
else |
|
289
|
|
|
ob_start(); |
|
290
|
|
|
|
|
291
|
|
|
if ($xml_format == 'smf' || isset($_REQUEST['debug'])) |
|
292
|
|
|
header('Content-Type: text/xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
|
293
|
|
View Code Duplication |
elseif ($xml_format == 'rss' || $xml_format == 'rss2') |
|
294
|
|
|
header('Content-Type: application/rss+xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
|
295
|
|
View Code Duplication |
elseif ($xml_format == 'atom') |
|
296
|
|
|
header('Content-Type: application/atom+xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
|
297
|
|
|
elseif ($xml_format == 'rdf') |
|
298
|
|
|
header('Content-Type: ' . (isBrowser('ie') ? 'text/xml' : 'application/rdf+xml') . '; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
|
299
|
|
|
|
|
300
|
|
|
// First, output the xml header. |
|
301
|
|
|
echo '<?xml version="1.0" encoding="', $context['character_set'], '"?' . '>'; |
|
302
|
|
|
|
|
303
|
|
|
// Are we outputting an rss feed or one with more information? |
|
304
|
|
|
if ($xml_format == 'rss' || $xml_format == 'rss2') |
|
305
|
|
|
{ |
|
306
|
|
|
if ($xml_format == 'rss2') |
|
307
|
|
View Code Duplication |
foreach ($_REQUEST as $var => $val) |
|
308
|
|
|
if (in_array($var, array('action', 'sa', 'type', 'board', 'boards', 'c', 'u', 'limit'))) |
|
309
|
|
|
$url_parts[] = $var . '=' . (is_array($val) ? implode(',', $val) : $val); |
|
|
|
|
|
|
310
|
|
|
|
|
311
|
|
|
// Start with an RSS 2.0 header. |
|
312
|
|
|
echo ' |
|
313
|
|
|
<rss version=', $xml_format == 'rss2' ? '"2.0"' : '"0.92"', ' xml:lang="', strtr($txt['lang_locale'], '_', '-'), '"', $ns_string, '> |
|
314
|
|
|
<channel> |
|
315
|
|
|
<title>', $feed_meta['title'], '</title> |
|
316
|
|
|
<link>', $feed_meta['source'], '</link> |
|
317
|
|
|
<description>', $feed_meta['desc'], '</description>', |
|
318
|
|
|
!empty($feed_meta['icon']) ? ' |
|
319
|
|
|
<image> |
|
320
|
|
|
<url>' . $feed_meta['icon'] . '</url> |
|
321
|
|
|
<title>' . $feed_meta['title'] . '</title> |
|
322
|
|
|
<link>' . $feed_meta['source'] . '</link> |
|
323
|
|
|
</image>' : '', |
|
324
|
|
|
!empty($feed_meta['rights']) ? ' |
|
325
|
|
|
<copyright>' . $feed_meta['rights'] . '</copyright>' : '', |
|
326
|
|
|
!empty($feed_meta['language']) ? ' |
|
327
|
|
|
<language>' . $feed_meta['language'] . '</language>' : ''; |
|
328
|
|
|
|
|
329
|
|
|
// RSS2 calls for this. |
|
330
|
|
|
if ($xml_format == 'rss2') |
|
331
|
|
|
echo ' |
|
332
|
|
|
<atom:link rel="self" type="application/rss+xml" href="', $scripturl, !empty($url_parts) ? '?' . implode(';', $url_parts) : '', '" />'; |
|
333
|
|
|
|
|
334
|
|
|
echo $extraFeedTags_string; |
|
335
|
|
|
|
|
336
|
|
|
// Output all of the associative array, start indenting with 2 tabs, and name everything "item". |
|
337
|
|
|
dumpTags($xml_data, 2, null, $xml_format, $forceCdataKeys, $nsKeys); |
|
338
|
|
|
|
|
339
|
|
|
// Output the footer of the xml. |
|
340
|
|
|
echo ' |
|
341
|
|
|
</channel> |
|
342
|
|
|
</rss>'; |
|
343
|
|
|
} |
|
344
|
|
|
elseif ($xml_format == 'atom') |
|
345
|
|
|
{ |
|
346
|
|
View Code Duplication |
foreach ($_REQUEST as $var => $val) |
|
347
|
|
|
if (in_array($var, array('action', 'sa', 'type', 'board', 'boards', 'c', 'u', 'limit'))) |
|
348
|
|
|
$url_parts[] = $var . '=' . (is_array($val) ? implode(',', $val) : $val); |
|
|
|
|
|
|
349
|
|
|
|
|
350
|
|
|
echo ' |
|
351
|
|
|
<feed', $ns_string, !empty($feed_meta['language']) ? ' xml:lang="' . $feed_meta['language'] . '"' : '', '> |
|
352
|
|
|
<title>', $feed_meta['title'], '</title> |
|
353
|
|
|
<link rel="alternate" type="text/html" href="', $feed_meta['source'], '" /> |
|
354
|
|
|
<link rel="self" type="application/atom+xml" href="', $scripturl, !empty($url_parts) ? '?' . implode(';', $url_parts) : '', '" /> |
|
355
|
|
|
<updated>', gmstrftime('%Y-%m-%dT%H:%M:%SZ'), '</updated> |
|
356
|
|
|
<id>', $feed_meta['source'], '</id> |
|
357
|
|
|
<subtitle>', $feed_meta['desc'], '</subtitle> |
|
358
|
|
|
<generator uri="https://www.simplemachines.org" version="', strtr($forum_version, array('SMF' => '')), '">SMF</generator>', |
|
359
|
|
|
!empty($feed_meta['icon']) ? ' |
|
360
|
|
|
<icon>' . $feed_meta['icon'] . '</icon>' : '', |
|
361
|
|
|
!empty($feed_meta['author']) ? ' |
|
362
|
|
|
<author> |
|
363
|
|
|
<name>' . $feed_meta['author'] . '</name> |
|
364
|
|
|
</author>' : '', |
|
365
|
|
|
!empty($feed_meta['rights']) ? ' |
|
366
|
|
|
<rights>' . $feed_meta['rights'] . '</rights>' : ''; |
|
367
|
|
|
|
|
368
|
|
|
echo $extraFeedTags_string; |
|
369
|
|
|
|
|
370
|
|
|
dumpTags($xml_data, 1, null, $xml_format, $forceCdataKeys, $nsKeys); |
|
371
|
|
|
|
|
372
|
|
|
echo ' |
|
373
|
|
|
</feed>'; |
|
374
|
|
|
} |
|
375
|
|
|
elseif ($xml_format == 'rdf') |
|
376
|
|
|
{ |
|
377
|
|
|
echo ' |
|
378
|
|
|
<rdf:RDF', $ns_string, '> |
|
379
|
|
|
<channel rdf:about="', $scripturl, '"> |
|
380
|
|
|
<title>', $feed_meta['title'], '</title> |
|
381
|
|
|
<link>', $feed_meta['source'], '</link> |
|
382
|
|
|
<description>', $feed_meta['desc'], '</description>'; |
|
383
|
|
|
|
|
384
|
|
|
echo $extraFeedTags_string; |
|
385
|
|
|
|
|
386
|
|
|
echo ' |
|
387
|
|
|
<items> |
|
388
|
|
|
<rdf:Seq>'; |
|
389
|
|
|
|
|
390
|
|
|
foreach ($xml_data as $item) |
|
391
|
|
|
{ |
|
392
|
|
|
$link = array_filter($item['content'], function ($e) { return ($e['tag'] == 'link'); }); |
|
|
|
|
|
|
393
|
|
|
$link = array_pop($link); |
|
394
|
|
|
|
|
395
|
|
|
echo ' |
|
396
|
|
|
<rdf:li rdf:resource="', $link['content'], '" />'; |
|
397
|
|
|
} |
|
398
|
|
|
|
|
399
|
|
|
echo ' |
|
400
|
|
|
</rdf:Seq> |
|
401
|
|
|
</items> |
|
402
|
|
|
</channel> |
|
403
|
|
|
'; |
|
404
|
|
|
|
|
405
|
|
|
dumpTags($xml_data, 1, null, $xml_format, $forceCdataKeys, $nsKeys); |
|
406
|
|
|
|
|
407
|
|
|
echo ' |
|
408
|
|
|
</rdf:RDF>'; |
|
409
|
|
|
} |
|
410
|
|
|
// Otherwise, we're using our proprietary formats - they give more data, though. |
|
411
|
|
|
else |
|
412
|
|
|
{ |
|
413
|
|
|
echo ' |
|
414
|
|
|
<smf:xml-feed xml:lang="', strtr($txt['lang_locale'], '_', '-'), '"', $ns_string, '>'; |
|
415
|
|
|
|
|
416
|
|
|
// Hard to imagine anyone wanting to add these for the proprietary format, but just in case... |
|
417
|
|
|
echo $extraFeedTags_string; |
|
418
|
|
|
|
|
419
|
|
|
// Dump out that associative array. Indent properly.... and use the right names for the base elements. |
|
420
|
|
|
dumpTags($xml_data, 1, $subActions[$_GET['sa']][1], $xml_format, $forceCdataKeys, $nsKeys); |
|
421
|
|
|
|
|
422
|
|
|
echo ' |
|
423
|
|
|
</smf:xml-feed>'; |
|
424
|
|
|
} |
|
425
|
|
|
|
|
426
|
|
|
obExit(false); |
|
427
|
|
|
} |
|
428
|
|
|
|
|
429
|
|
|
/** |
|
430
|
|
|
* Called from dumpTags to convert data to xml |
|
431
|
|
|
* Finds urls for local site and sanitizes them |
|
432
|
|
|
* |
|
433
|
|
|
* @param string $val A string containing a possible URL |
|
434
|
|
|
* @return string $val The string with any possible URLs sanitized |
|
435
|
|
|
*/ |
|
436
|
|
|
function fix_possible_url($val) |
|
437
|
|
|
{ |
|
438
|
|
|
global $modSettings, $context, $scripturl; |
|
439
|
|
|
|
|
440
|
|
|
if (substr($val, 0, strlen($scripturl)) != $scripturl) |
|
441
|
|
|
return $val; |
|
442
|
|
|
|
|
443
|
|
|
call_integration_hook('integrate_fix_url', array(&$val)); |
|
444
|
|
|
|
|
445
|
|
|
if (empty($modSettings['queryless_urls']) || ($context['server']['is_cgi'] && ini_get('cgi.fix_pathinfo') == 0 && @get_cfg_var('cgi.fix_pathinfo') == 0) || (!$context['server']['is_apache'] && !$context['server']['is_lighttpd'])) |
|
446
|
|
|
return $val; |
|
447
|
|
|
|
|
448
|
|
|
$val = preg_replace_callback('~\b' . preg_quote($scripturl, '~') . '\?((?:board|topic)=[^#"]+)(#[^"]*)?$~', function($m) use ($scripturl) |
|
|
|
|
|
|
449
|
|
|
{ |
|
450
|
|
|
return $scripturl . '/' . strtr("$m[1]", '&;=', '//,') . '.html' . (isset($m[2]) ? $m[2] : ""); |
|
|
|
|
|
|
451
|
|
|
}, $val); |
|
452
|
|
|
return $val; |
|
453
|
|
|
} |
|
454
|
|
|
|
|
455
|
|
|
/** |
|
456
|
|
|
* Ensures supplied data is properly encapsulated in cdata xml tags |
|
457
|
|
|
* Called from getXmlProfile in News.php |
|
458
|
|
|
* |
|
459
|
|
|
* @param string $data XML data |
|
460
|
|
|
* @param string $ns A namespace prefix for the XML data elements (used by mods, maybe) |
|
461
|
|
|
* @param boolean $force If true, enclose the XML data in cdata tags no matter what (used by mods, maybe) |
|
462
|
|
|
* @return string The XML data enclosed in cdata tags when necessary |
|
463
|
|
|
*/ |
|
464
|
|
|
function cdata_parse($data, $ns = '', $force = false) |
|
|
|
|
|
|
465
|
|
|
{ |
|
466
|
|
|
global $smcFunc; |
|
467
|
|
|
|
|
468
|
|
|
// Do we even need to do this? |
|
469
|
|
|
if (strpbrk($data, '<>&') == false && $force !== true) |
|
|
|
|
|
|
470
|
|
|
return $data; |
|
471
|
|
|
|
|
472
|
|
|
$cdata = '<; $pos < $n; null) |
|
475
|
|
|
{ |
|
476
|
|
|
$positions = array( |
|
477
|
|
|
$smcFunc['strpos']($data, '&', $pos), |
|
478
|
|
|
$smcFunc['strpos']($data, ']', $pos), |
|
479
|
|
|
); |
|
480
|
|
|
if ($ns != '') |
|
481
|
|
|
$positions[] = $smcFunc['strpos']($data, '<', $pos); |
|
482
|
|
|
foreach ($positions as $k => $dummy) |
|
483
|
|
|
{ |
|
484
|
|
|
if ($dummy === false) |
|
485
|
|
|
unset($positions[$k]); |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
$old = $pos; |
|
489
|
|
|
$pos = empty($positions) ? $n : min($positions); |
|
490
|
|
|
|
|
491
|
|
|
if ($pos - $old > 0) |
|
492
|
|
|
$cdata .= $smcFunc['substr']($data, $old, $pos - $old); |
|
493
|
|
|
if ($pos >= $n) |
|
494
|
|
|
break; |
|
495
|
|
|
|
|
496
|
|
|
if ($smcFunc['substr']($data, $pos, 1) == '<') |
|
497
|
|
|
{ |
|
498
|
|
|
$pos2 = $smcFunc['strpos']($data, '>', $pos); |
|
499
|
|
|
if ($pos2 === false) |
|
500
|
|
|
$pos2 = $n; |
|
501
|
|
|
if ($smcFunc['substr']($data, $pos + 1, 1) == '/') |
|
502
|
|
|
$cdata .= ']]></' . $ns . ':' . $smcFunc['substr']($data, $pos + 2, $pos2 - $pos - 1) . '<![CDATA['; |
|
503
|
|
|
else |
|
504
|
|
|
$cdata .= ']]><' . $ns . ':' . $smcFunc['substr']($data, $pos + 1, $pos2 - $pos) . '< == ']') |
|
508
|
|
|
{ |
|
509
|
|
|
$cdata .= ']]>]< == '&') |
|
513
|
|
|
{ |
|
514
|
|
|
$pos2 = $smcFunc['strpos']($data, ';', $pos); |
|
515
|
|
|
if ($pos2 === false) |
|
516
|
|
|
$pos2 = $n; |
|
517
|
|
|
$ent = $smcFunc['substr']($data, $pos + 1, $pos2 - $pos - 1); |
|
518
|
|
|
|
|
519
|
|
|
if ($smcFunc['substr']($data, $pos + 1, 1) == '#') |
|
520
|
|
|
$cdata .= ']]>' . $smcFunc['substr']($data, $pos, $pos2 - $pos + 1) . '<![CDATA['; |
|
521
|
|
|
elseif (in_array($ent, array('amp', 'lt', 'gt', 'quot'))) |
|
522
|
|
|
$cdata .= ']]>' . $smcFunc['substr']($data, $pos, $pos2 - $pos + 1) . '<![CDATA['; |
|
523
|
|
|
|
|
524
|
|
|
$pos = $pos2 + 1; |
|
525
|
|
|
} |
|
526
|
|
|
} |
|
527
|
|
|
|
|
528
|
|
|
$cdata .= ']]>'; |
|
529
|
|
|
|
|
530
|
|
|
return strtr($cdata, array('<![CDATA[]]>' => '')); |
|
531
|
|
|
} |
|
532
|
|
|
|
|
533
|
|
|
/** |
|
534
|
|
|
* Formats data retrieved in other functions into xml format. |
|
535
|
|
|
* Additionally formats data based on the specific format passed. |
|
536
|
|
|
* This function is recursively called to handle sub arrays of data. |
|
537
|
|
|
* |
|
538
|
|
|
* @param array $data The array to output as xml data |
|
539
|
|
|
* @param int $i The amount of indentation to use. |
|
540
|
|
|
* @param string $xml_format The format to use ('atom', 'rss', 'rss2' or empty for plain XML) |
|
541
|
|
|
* @param array $forceCdataKeys A list of keys on which to force cdata wrapping (used by mods, maybe) |
|
542
|
|
|
* @param array $nsKeys Key-value pairs of namespace prefixes to pass to cdata_parse() (used by mods, maybe) |
|
543
|
|
|
*/ |
|
544
|
|
|
function dumpTags($data, $i, $tag = null, $xml_format = '', $forceCdataKeys = array(), $nsKeys = array()) |
|
545
|
|
|
{ |
|
546
|
|
|
// Wrap the values of these keys into CDATA tags |
|
547
|
|
|
$keysToCdata = array( |
|
548
|
|
|
'title', |
|
549
|
|
|
'name', |
|
550
|
|
|
'description', |
|
551
|
|
|
'summary', |
|
552
|
|
|
'subject', |
|
553
|
|
|
'body', |
|
554
|
|
|
'username', |
|
555
|
|
|
'signature', |
|
556
|
|
|
'position', |
|
557
|
|
|
'language', |
|
558
|
|
|
'gender', |
|
559
|
|
|
'blurb', |
|
560
|
|
|
); |
|
561
|
|
|
if ($xml_format != 'atom') |
|
562
|
|
|
$keysToCdata[] = 'category'; |
|
563
|
|
|
|
|
564
|
|
|
if (!empty($forceCdataKeys)) |
|
565
|
|
|
{ |
|
566
|
|
|
$keysToCdata = array_merge($keysToCdata, $forceCdataKeys); |
|
567
|
|
|
$keysToCdata = array_unique($keysToCdata); |
|
568
|
|
|
} |
|
569
|
|
|
|
|
570
|
|
|
// For every array in the data... |
|
571
|
|
|
foreach ($data as $element) |
|
572
|
|
|
{ |
|
573
|
|
|
// If a tag was passed, use it instead of the key. |
|
574
|
|
|
$key = isset($tag) ? $tag : (isset($element['tag']) ? $element['tag'] : null); |
|
575
|
|
|
$val = isset($element['content']) ? $element['content'] : null; |
|
576
|
|
|
$attrs = isset($element['attributes']) ? $element['attributes'] : null; |
|
577
|
|
|
|
|
578
|
|
|
// Skip it, it's been set to null. |
|
579
|
|
|
if ($key === null || ($val === null && $attrs === null)) |
|
580
|
|
|
continue; |
|
581
|
|
|
|
|
582
|
|
|
$forceCdata = in_array($key, $forceCdataKeys); |
|
583
|
|
|
$ns = !empty($nsKeys[$key]) ? $nsKeys[$key] : ''; |
|
584
|
|
|
|
|
585
|
|
|
// First let's indent! |
|
586
|
|
|
echo "\n", str_repeat("\t", $i); |
|
587
|
|
|
|
|
588
|
|
|
// Beginning tag. |
|
589
|
|
|
echo '<', $key; |
|
590
|
|
|
|
|
591
|
|
|
if (!empty($attrs)) |
|
592
|
|
|
{ |
|
593
|
|
|
foreach ($attrs as $attr_key => $attr_value) |
|
594
|
|
|
echo ' ', $attr_key, '="', fix_possible_url($attr_value), '"'; |
|
595
|
|
|
} |
|
596
|
|
|
|
|
597
|
|
|
// If it's empty, simply output an empty element. |
|
598
|
|
|
if (empty($val)) |
|
599
|
|
|
{ |
|
600
|
|
|
echo ' />'; |
|
601
|
|
|
} |
|
602
|
|
|
else |
|
603
|
|
|
{ |
|
604
|
|
|
echo '>'; |
|
605
|
|
|
|
|
606
|
|
|
// The element's value. |
|
607
|
|
|
if (is_array($val)) |
|
608
|
|
|
{ |
|
609
|
|
|
// An array. Dump it, and then indent the tag. |
|
610
|
|
|
dumpTags($val, $i + 1, null, $xml_format, $forceCdataKeys, $nsKeys); |
|
611
|
|
|
echo "\n", str_repeat("\t", $i); |
|
612
|
|
|
} |
|
613
|
|
|
// A string with returns in it.... show this as a multiline element. |
|
614
|
|
|
elseif (strpos($val, "\n") !== false) |
|
615
|
|
|
echo "\n", in_array($key, $keysToCdata) ? cdata_parse(fix_possible_url($val), $ns, $forceCdata) : fix_possible_url($val), "\n", str_repeat("\t", $i); |
|
616
|
|
|
// A simple string. |
|
617
|
|
|
else |
|
618
|
|
|
echo in_array($key, $keysToCdata) ? cdata_parse(fix_possible_url($val), $ns, $forceCdata) : fix_possible_url($val); |
|
619
|
|
|
|
|
620
|
|
|
// Ending tag. |
|
621
|
|
|
echo '</', $key, '>'; |
|
622
|
|
|
} |
|
623
|
|
|
} |
|
624
|
|
|
} |
|
625
|
|
|
|
|
626
|
|
|
/** |
|
627
|
|
|
* Retrieve the list of members from database. |
|
628
|
|
|
* The array will be generated to match the format. |
|
629
|
|
|
* @todo get the list of members from Subs-Members. |
|
|
|
|
|
|
630
|
|
|
* |
|
631
|
|
|
* @param string $xml_format The format to use. Can be 'atom', 'rdf', 'rss', 'rss2' or 'smf' |
|
632
|
|
|
* @return array An array of arrays of feed items. Each array has keys corresponding to the appropriate tags for the specified format. |
|
633
|
|
|
*/ |
|
634
|
|
|
function getXmlMembers($xml_format) |
|
635
|
|
|
{ |
|
636
|
|
|
global $scripturl, $smcFunc; |
|
637
|
|
|
|
|
638
|
|
|
if (!allowedTo('view_mlist')) |
|
639
|
|
|
return array(); |
|
640
|
|
|
|
|
641
|
|
|
// Find the most recent members. |
|
642
|
|
|
$request = $smcFunc['db_query']('', ' |
|
643
|
|
|
SELECT id_member, member_name, real_name, date_registered, last_login |
|
644
|
|
|
FROM {db_prefix}members |
|
645
|
|
|
ORDER BY id_member DESC |
|
646
|
|
|
LIMIT {int:limit}', |
|
647
|
|
|
array( |
|
648
|
|
|
'limit' => $_GET['limit'], |
|
649
|
|
|
) |
|
650
|
|
|
); |
|
651
|
|
|
$data = array(); |
|
652
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
653
|
|
|
{ |
|
654
|
|
|
// Create a GUID for each member using the tag URI scheme |
|
655
|
|
|
$guid = 'tag:' . parse_url($scripturl, PHP_URL_HOST) . ',' . gmdate('Y-m-d', $row['date_registered']) . ':member=' . $row['id_member']; |
|
656
|
|
|
|
|
657
|
|
|
// Make the data look rss-ish. |
|
658
|
|
|
if ($xml_format == 'rss' || $xml_format == 'rss2') |
|
659
|
|
|
$data[] = array( |
|
660
|
|
|
'tag' => 'item', |
|
661
|
|
|
'content' => array( |
|
662
|
|
|
array( |
|
663
|
|
|
'tag' => 'title', |
|
664
|
|
|
'content' => $row['real_name'], |
|
665
|
|
|
), |
|
666
|
|
|
array( |
|
667
|
|
|
'tag' => 'link', |
|
668
|
|
|
'content' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
669
|
|
|
), |
|
670
|
|
|
array( |
|
671
|
|
|
'tag' => 'comments', |
|
672
|
|
|
'content' => $scripturl . '?action=pm;sa=send;u=' . $row['id_member'], |
|
673
|
|
|
), |
|
674
|
|
|
array( |
|
675
|
|
|
'tag' => 'pubDate', |
|
676
|
|
|
'content' => gmdate('D, d M Y H:i:s \G\M\T', $row['date_registered']), |
|
677
|
|
|
), |
|
678
|
|
|
array( |
|
679
|
|
|
'tag' => 'guid', |
|
680
|
|
|
'content' => $guid, |
|
681
|
|
|
'attributes' => array( |
|
682
|
|
|
'isPermaLink' => 'false', |
|
683
|
|
|
), |
|
684
|
|
|
), |
|
685
|
|
|
), |
|
686
|
|
|
); |
|
687
|
|
|
elseif ($xml_format == 'rdf') |
|
688
|
|
|
$data[] = array( |
|
689
|
|
|
'tag' => 'item', |
|
690
|
|
|
'attributes' => array('rdf:about' => $scripturl . '?action=profile;u=' . $row['id_member']), |
|
691
|
|
|
'content' => array( |
|
692
|
|
|
array( |
|
693
|
|
|
'tag' => 'dc:format', |
|
694
|
|
|
'content' => 'text/html', |
|
695
|
|
|
), |
|
696
|
|
|
array( |
|
697
|
|
|
'tag' => 'title', |
|
698
|
|
|
'content' => $row['real_name'], |
|
699
|
|
|
), |
|
700
|
|
|
array( |
|
701
|
|
|
'tag' => 'link', |
|
702
|
|
|
'content' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
703
|
|
|
), |
|
704
|
|
|
), |
|
705
|
|
|
); |
|
706
|
|
|
elseif ($xml_format == 'atom') |
|
707
|
|
|
$data[] = array( |
|
708
|
|
|
'tag' => 'entry', |
|
709
|
|
|
'content' => array( |
|
710
|
|
|
array( |
|
711
|
|
|
'tag' => 'title', |
|
712
|
|
|
'content' => $row['real_name'], |
|
713
|
|
|
), |
|
714
|
|
|
array( |
|
715
|
|
|
'tag' => 'link', |
|
716
|
|
|
'attributes' => array( |
|
717
|
|
|
'rel' => 'alternate', |
|
718
|
|
|
'type' => 'text/html', |
|
719
|
|
|
'href' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
720
|
|
|
), |
|
721
|
|
|
), |
|
722
|
|
|
array( |
|
723
|
|
|
'tag' => 'published', |
|
724
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $row['date_registered']), |
|
725
|
|
|
), |
|
726
|
|
|
array( |
|
727
|
|
|
'tag' => 'updated', |
|
728
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $row['last_login']), |
|
729
|
|
|
), |
|
730
|
|
|
array( |
|
731
|
|
|
'tag' => 'id', |
|
732
|
|
|
'content' => $guid, |
|
733
|
|
|
), |
|
734
|
|
|
), |
|
735
|
|
|
); |
|
736
|
|
|
// More logical format for the data, but harder to apply. |
|
737
|
|
|
else |
|
738
|
|
|
$data[] = array( |
|
739
|
|
|
'tag' => 'member', |
|
740
|
|
|
'content' => array( |
|
741
|
|
|
array( |
|
742
|
|
|
'tag' => 'name', |
|
743
|
|
|
'content' => $row['real_name'], |
|
744
|
|
|
), |
|
745
|
|
|
array( |
|
746
|
|
|
'tag' => 'time', |
|
747
|
|
|
'content' => $smcFunc['htmlspecialchars'](strip_tags(timeformat($row['date_registered']))), |
|
748
|
|
|
), |
|
749
|
|
|
array( |
|
750
|
|
|
'tag' => 'id', |
|
751
|
|
|
'content' => $row['id_member'], |
|
752
|
|
|
), |
|
753
|
|
|
array( |
|
754
|
|
|
'tag' => 'link', |
|
755
|
|
|
'content' => $scripturl . '?action=profile;u=' . $row['id_member'], |
|
756
|
|
|
), |
|
757
|
|
|
), |
|
758
|
|
|
); |
|
759
|
|
|
} |
|
760
|
|
|
$smcFunc['db_free_result']($request); |
|
761
|
|
|
|
|
762
|
|
|
return $data; |
|
763
|
|
|
} |
|
764
|
|
|
|
|
765
|
|
|
/** |
|
766
|
|
|
* Get the latest topics information from a specific board, |
|
767
|
|
|
* to display later. |
|
768
|
|
|
* The returned array will be generated to match the xml_format. |
|
769
|
|
|
* @todo does not belong here |
|
|
|
|
|
|
770
|
|
|
* |
|
771
|
|
|
* @param string $xml_format The XML format. Can be 'atom', 'rdf', 'rss', 'rss2' or 'smf'. |
|
772
|
|
|
* @return array An array of arrays of topic data for the feed. Each array has keys corresponding to the tags for the specified format. |
|
773
|
|
|
*/ |
|
774
|
|
|
function getXmlNews($xml_format) |
|
775
|
|
|
{ |
|
776
|
|
|
global $scripturl, $modSettings, $board, $user_info; |
|
777
|
|
|
global $query_this_board, $smcFunc, $context, $txt; |
|
778
|
|
|
|
|
779
|
|
|
/* Find the latest posts that: |
|
780
|
|
|
- are the first post in their topic. |
|
781
|
|
|
- are on an any board OR in a specified board. |
|
782
|
|
|
- can be seen by this user. |
|
783
|
|
|
- are actually the latest posts. */ |
|
784
|
|
|
|
|
785
|
|
|
$done = false; |
|
786
|
|
|
$loops = 0; |
|
787
|
|
|
while (!$done) |
|
788
|
|
|
{ |
|
789
|
|
|
$optimize_msg = implode(' AND ', $context['optimize_msg']); |
|
790
|
|
|
$request = $smcFunc['db_query']('', ' |
|
791
|
|
|
SELECT |
|
792
|
|
|
m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, m.modified_time, |
|
793
|
|
|
m.icon, t.id_topic, t.id_board, t.num_replies, |
|
794
|
|
|
b.name AS bname, |
|
795
|
|
|
COALESCE(mem.id_member, 0) AS id_member, |
|
796
|
|
|
COALESCE(mem.email_address, m.poster_email) AS poster_email, |
|
797
|
|
|
COALESCE(mem.real_name, m.poster_name) AS poster_name |
|
798
|
|
|
FROM {db_prefix}topics AS t |
|
799
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
|
800
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) |
|
801
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
|
802
|
|
|
WHERE ' . $query_this_board . (empty($optimize_msg) ? '' : ' |
|
803
|
|
|
AND {raw:optimize_msg}') . (empty($board) ? '' : ' |
|
804
|
|
|
AND t.id_board = {int:current_board}') . ($modSettings['postmod_active'] ? ' |
|
805
|
|
|
AND t.approved = {int:is_approved}' : '') . ' |
|
806
|
|
|
ORDER BY t.id_first_msg DESC |
|
807
|
|
|
LIMIT {int:limit}', |
|
808
|
|
|
array( |
|
809
|
|
|
'current_board' => $board, |
|
810
|
|
|
'is_approved' => 1, |
|
811
|
|
|
'limit' => $_GET['limit'], |
|
812
|
|
|
'optimize_msg' => $optimize_msg, |
|
813
|
|
|
) |
|
814
|
|
|
); |
|
815
|
|
|
// If we don't have $_GET['limit'] results, try again with an unoptimized version covering all rows. |
|
816
|
|
|
if ($loops < 2 && $smcFunc['db_num_rows']($request) < $_GET['limit']) |
|
817
|
|
|
{ |
|
818
|
|
|
$smcFunc['db_free_result']($request); |
|
819
|
|
View Code Duplication |
if (empty($_REQUEST['boards']) && empty($board)) |
|
820
|
|
|
unset($context['optimize_msg']['lowest']); |
|
821
|
|
|
else |
|
822
|
|
|
$context['optimize_msg']['lowest'] = 'm.id_msg >= t.id_first_msg'; |
|
823
|
|
|
$context['optimize_msg']['highest'] = 'm.id_msg <= t.id_last_msg'; |
|
824
|
|
|
$loops++; |
|
825
|
|
|
} |
|
826
|
|
|
else |
|
827
|
|
|
$done = true; |
|
828
|
|
|
} |
|
829
|
|
|
$data = array(); |
|
830
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
|
|
|
|
|
831
|
|
|
{ |
|
832
|
|
|
// Limit the length of the message, if the option is set. |
|
833
|
|
View Code Duplication |
if (!empty($modSettings['xmlnews_maxlen']) && $smcFunc['strlen'](str_replace('<br>', "\n", $row['body'])) > $modSettings['xmlnews_maxlen']) |
|
834
|
|
|
$row['body'] = strtr($smcFunc['substr'](str_replace('<br>', "\n", $row['body']), 0, $modSettings['xmlnews_maxlen'] - 3), array("\n" => '<br>')) . '...'; |
|
835
|
|
|
|
|
836
|
|
|
$row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']); |
|
837
|
|
|
|
|
838
|
|
|
censorText($row['body']); |
|
839
|
|
|
censorText($row['subject']); |
|
840
|
|
|
|
|
841
|
|
|
// Do we want to include any attachments? |
|
842
|
|
View Code Duplication |
if (!empty($modSettings['attachmentEnable']) && !empty($modSettings['xmlnews_attachments']) && allowedTo('view_attachments', $row['id_board'])) |
|
843
|
|
|
{ |
|
844
|
|
|
$attach_request = $smcFunc['db_query']('', ' |
|
845
|
|
|
SELECT |
|
846
|
|
|
a.id_attach, a.filename, COALESCE(a.size, 0) AS filesize, a.mime_type, a.downloads, a.approved, m.id_topic AS topic |
|
847
|
|
|
FROM {db_prefix}attachments AS a |
|
848
|
|
|
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
849
|
|
|
WHERE a.attachment_type = {int:attachment_type} |
|
850
|
|
|
AND a.id_msg = {int:message_id}', |
|
851
|
|
|
array( |
|
852
|
|
|
'message_id' => $row['id_msg'], |
|
853
|
|
|
'attachment_type' => 0, |
|
854
|
|
|
'is_approved' => 1, |
|
855
|
|
|
) |
|
856
|
|
|
); |
|
857
|
|
|
$loaded_attachments = array(); |
|
858
|
|
|
while ($attach = $smcFunc['db_fetch_assoc']($attach_request)) |
|
859
|
|
|
{ |
|
860
|
|
|
// Include approved attachments only |
|
861
|
|
|
if ($attach['approved']) |
|
862
|
|
|
$loaded_attachments['attachment_' . $attach['id_attach']] = $attach; |
|
863
|
|
|
} |
|
864
|
|
|
$smcFunc['db_free_result']($attach_request); |
|
865
|
|
|
|
|
866
|
|
|
// Sort the attachments by size to make things easier below |
|
867
|
|
|
if (!empty($loaded_attachments)) |
|
868
|
|
|
{ |
|
869
|
|
|
uasort($loaded_attachments, function($a, $b) { |
|
|
|
|
|
|
870
|
|
|
if ($a['filesize'] == $b['filesize']) |
|
871
|
|
|
return 0; |
|
872
|
|
|
return ($a['filesize'] < $b['filesize']) ? -1 : 1; |
|
873
|
|
|
}); |
|
874
|
|
|
} |
|
875
|
|
|
else |
|
876
|
|
|
$loaded_attachments = null; |
|
877
|
|
|
} |
|
878
|
|
|
else |
|
879
|
|
|
$loaded_attachments = null; |
|
880
|
|
|
|
|
881
|
|
|
// Create a GUID for this topic using the tag URI scheme |
|
882
|
|
|
$guid = 'tag:' . parse_url($scripturl, PHP_URL_HOST) . ',' . gmdate('Y-m-d', $row['poster_time']) . ':topic=' . $row['id_topic']; |
|
883
|
|
|
|
|
884
|
|
|
// Being news, this actually makes sense in rss format. |
|
885
|
|
|
if ($xml_format == 'rss' || $xml_format == 'rss2') |
|
886
|
|
|
{ |
|
887
|
|
|
// Only one attachment allowed in RSS. |
|
888
|
|
View Code Duplication |
if ($loaded_attachments !== null) |
|
889
|
|
|
{ |
|
890
|
|
|
$attachment = array_pop($loaded_attachments); |
|
891
|
|
|
$enclosure = array( |
|
892
|
|
|
'url' => fix_possible_url($scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach']), |
|
893
|
|
|
'length' => $attachment['filesize'], |
|
894
|
|
|
'type' => $attachment['mime_type'], |
|
895
|
|
|
); |
|
896
|
|
|
} |
|
897
|
|
|
else |
|
898
|
|
|
$enclosure = null; |
|
899
|
|
|
|
|
900
|
|
|
$data[] = array( |
|
901
|
|
|
'tag' => 'item', |
|
902
|
|
|
'content' => array( |
|
903
|
|
|
array( |
|
904
|
|
|
'tag' => 'title', |
|
905
|
|
|
'content' => $row['subject'], |
|
906
|
|
|
), |
|
907
|
|
|
array( |
|
908
|
|
|
'tag' => 'link', |
|
909
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.0', |
|
910
|
|
|
), |
|
911
|
|
|
array( |
|
912
|
|
|
'tag' => 'description', |
|
913
|
|
|
'content' => $row['body'], |
|
914
|
|
|
), |
|
915
|
|
|
array( |
|
916
|
|
|
'tag' => 'author', |
|
917
|
|
|
'content' => (allowedTo('moderate_forum') || $row['id_member'] == $user_info['id']) ? $row['poster_email'] . ' (' . $row['poster_name'] . ')' : null, |
|
918
|
|
|
), |
|
919
|
|
|
array( |
|
920
|
|
|
'tag' => 'comments', |
|
921
|
|
|
'content' => $scripturl . '?action=post;topic=' . $row['id_topic'] . '.0', |
|
922
|
|
|
), |
|
923
|
|
|
array( |
|
924
|
|
|
'tag' => 'category', |
|
925
|
|
|
'content' => $row['bname'], |
|
926
|
|
|
), |
|
927
|
|
|
array( |
|
928
|
|
|
'tag' => 'pubDate', |
|
929
|
|
|
'content' => gmdate('D, d M Y H:i:s \G\M\T', $row['poster_time']), |
|
930
|
|
|
), |
|
931
|
|
|
array( |
|
932
|
|
|
'tag' => 'guid', |
|
933
|
|
|
'content' => $guid, |
|
934
|
|
|
'attributes' => array( |
|
935
|
|
|
'isPermaLink' => 'false', |
|
936
|
|
|
), |
|
937
|
|
|
), |
|
938
|
|
|
array( |
|
939
|
|
|
'tag' => 'enclosure', |
|
940
|
|
|
'attributes' => $enclosure, |
|
941
|
|
|
), |
|
942
|
|
|
), |
|
943
|
|
|
); |
|
944
|
|
|
} |
|
945
|
|
|
elseif ($xml_format == 'rdf') |
|
946
|
|
|
{ |
|
947
|
|
|
$data[] = array( |
|
948
|
|
|
'tag' => 'item', |
|
949
|
|
|
'attributes' => array('rdf:about' => $scripturl . '?topic=' . $row['id_topic'] . '.0'), |
|
950
|
|
|
'content' => array( |
|
951
|
|
|
array( |
|
952
|
|
|
'tag' => 'dc:format', |
|
953
|
|
|
'content' => 'text/html', |
|
954
|
|
|
), |
|
955
|
|
|
array( |
|
956
|
|
|
'tag' => 'title', |
|
957
|
|
|
'content' => $row['subject'], |
|
958
|
|
|
), |
|
959
|
|
|
array( |
|
960
|
|
|
'tag' => 'link', |
|
961
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.0', |
|
962
|
|
|
), |
|
963
|
|
|
array( |
|
964
|
|
|
'tag' => 'description', |
|
965
|
|
|
'content' => $row['body'], |
|
966
|
|
|
), |
|
967
|
|
|
), |
|
968
|
|
|
); |
|
969
|
|
|
} |
|
970
|
|
|
elseif ($xml_format == 'atom') |
|
971
|
|
|
{ |
|
972
|
|
|
// Only one attachment allowed |
|
973
|
|
View Code Duplication |
if (!empty($loaded_attachments)) |
|
974
|
|
|
{ |
|
975
|
|
|
$attachment = array_pop($loaded_attachments); |
|
976
|
|
|
$enclosure = array( |
|
977
|
|
|
'rel' => 'enclosure', |
|
978
|
|
|
'href' => fix_possible_url($scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach']), |
|
979
|
|
|
'length' => $attachment['filesize'], |
|
980
|
|
|
'type' => $attachment['mime_type'], |
|
981
|
|
|
); |
|
982
|
|
|
} |
|
983
|
|
|
else |
|
984
|
|
|
$enclosure = null; |
|
985
|
|
|
|
|
986
|
|
|
$data[] = array( |
|
987
|
|
|
'tag' => 'entry', |
|
988
|
|
|
'content' => array( |
|
989
|
|
|
array( |
|
990
|
|
|
'tag' => 'title', |
|
991
|
|
|
'content' => $row['subject'], |
|
992
|
|
|
), |
|
993
|
|
|
array( |
|
994
|
|
|
'tag' => 'link', |
|
995
|
|
|
'attributes' => array( |
|
996
|
|
|
'rel' => 'alternate', |
|
997
|
|
|
'type' => 'text/html', |
|
998
|
|
|
'href' => $scripturl . '?topic=' . $row['id_topic'] . '.0', |
|
999
|
|
|
), |
|
1000
|
|
|
), |
|
1001
|
|
|
array( |
|
1002
|
|
|
'tag' => 'summary', |
|
1003
|
|
|
'attributes' => array('type' => 'html'), |
|
1004
|
|
|
'content' => $row['body'], |
|
1005
|
|
|
), |
|
1006
|
|
|
array( |
|
1007
|
|
|
'tag' => 'category', |
|
1008
|
|
|
'attributes' => array('term' => $row['bname']), |
|
1009
|
|
|
), |
|
1010
|
|
|
array( |
|
1011
|
|
|
'tag' => 'author', |
|
1012
|
|
|
'content' => array( |
|
1013
|
|
|
array( |
|
1014
|
|
|
'tag' => 'name', |
|
1015
|
|
|
'content' => $row['poster_name'], |
|
1016
|
|
|
), |
|
1017
|
|
|
array( |
|
1018
|
|
|
'tag' => 'email', |
|
1019
|
|
|
'content' => (allowedTo('moderate_forum') || $row['id_member'] == $user_info['id']) ? $row['poster_email'] : null, |
|
1020
|
|
|
), |
|
1021
|
|
|
array( |
|
1022
|
|
|
'tag' => 'uri', |
|
1023
|
|
|
'content' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : null, |
|
1024
|
|
|
), |
|
1025
|
|
|
) |
|
1026
|
|
|
), |
|
1027
|
|
|
array( |
|
1028
|
|
|
'tag' => 'published', |
|
1029
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $row['poster_time']), |
|
1030
|
|
|
), |
|
1031
|
|
|
array( |
|
1032
|
|
|
'tag' => 'updated', |
|
1033
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', empty($row['modified_time']) ? $row['poster_time'] : $row['modified_time']), |
|
1034
|
|
|
), |
|
1035
|
|
|
array( |
|
1036
|
|
|
'tag' => 'id', |
|
1037
|
|
|
'content' => $guid, |
|
1038
|
|
|
), |
|
1039
|
|
|
array( |
|
1040
|
|
|
'tag' => 'link', |
|
1041
|
|
|
'attributes' => $enclosure, |
|
1042
|
|
|
), |
|
1043
|
|
|
), |
|
1044
|
|
|
); |
|
1045
|
|
|
} |
|
1046
|
|
|
// The biggest difference here is more information. |
|
1047
|
|
|
else |
|
1048
|
|
|
{ |
|
1049
|
|
|
$attachments = array(); |
|
1050
|
|
View Code Duplication |
if (!empty($loaded_attachments)) |
|
1051
|
|
|
{ |
|
1052
|
|
|
foreach ($loaded_attachments as $attachment) |
|
1053
|
|
|
{ |
|
1054
|
|
|
$attachments[] = array( |
|
1055
|
|
|
'tag' => 'attachment', |
|
1056
|
|
|
'content' => array( |
|
1057
|
|
|
array( |
|
1058
|
|
|
'tag' => 'id', |
|
1059
|
|
|
'content' => $attachment['id_attach'], |
|
1060
|
|
|
), |
|
1061
|
|
|
array( |
|
1062
|
|
|
'tag' => 'name', |
|
1063
|
|
|
'content' => preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', $smcFunc['htmlspecialchars']($attachment['filename'])), |
|
1064
|
|
|
), |
|
1065
|
|
|
array( |
|
1066
|
|
|
'tag' => 'downloads', |
|
1067
|
|
|
'content' => $attachment['downloads'], |
|
1068
|
|
|
), |
|
1069
|
|
|
array( |
|
1070
|
|
|
'tag' => 'size', |
|
1071
|
|
|
'content' => ($attachment['filesize'] < 1024000) ? round($attachment['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'] : round($attachment['filesize'] / 1024 / 1024, 2) . ' ' . $txt['megabyte'], |
|
1072
|
|
|
), |
|
1073
|
|
|
array( |
|
1074
|
|
|
'tag' => 'byte_size', |
|
1075
|
|
|
'content' => $attachment['filesize'], |
|
1076
|
|
|
), |
|
1077
|
|
|
array( |
|
1078
|
|
|
'tag' => 'link', |
|
1079
|
|
|
'content' => $scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach'], |
|
1080
|
|
|
), |
|
1081
|
|
|
) |
|
1082
|
|
|
); |
|
1083
|
|
|
} |
|
1084
|
|
|
} |
|
1085
|
|
|
else |
|
1086
|
|
|
$attachments = null; |
|
1087
|
|
|
|
|
1088
|
|
|
$data[] = array( |
|
1089
|
|
|
'tag' => 'article', |
|
1090
|
|
|
'content' => array( |
|
1091
|
|
|
array( |
|
1092
|
|
|
'tag' => 'time', |
|
1093
|
|
|
'content' => $smcFunc['htmlspecialchars'](strip_tags(timeformat($row['poster_time']))), |
|
1094
|
|
|
), |
|
1095
|
|
|
array( |
|
1096
|
|
|
'tag' => 'id', |
|
1097
|
|
|
'content' => $row['id_topic'], |
|
1098
|
|
|
), |
|
1099
|
|
|
array( |
|
1100
|
|
|
'tag' => 'subject', |
|
1101
|
|
|
'content' => $row['subject'], |
|
1102
|
|
|
), |
|
1103
|
|
|
array( |
|
1104
|
|
|
'tag' => 'body', |
|
1105
|
|
|
'content' => $row['body'], |
|
1106
|
|
|
), |
|
1107
|
|
|
array( |
|
1108
|
|
|
'tag' => 'poster', |
|
1109
|
|
|
'content' => array( |
|
1110
|
|
|
array( |
|
1111
|
|
|
'tag' => 'name', |
|
1112
|
|
|
'content' => $row['poster_name'], |
|
1113
|
|
|
), |
|
1114
|
|
|
array( |
|
1115
|
|
|
'tag' => 'id', |
|
1116
|
|
|
'content' => $row['id_member'], |
|
1117
|
|
|
), |
|
1118
|
|
|
array( |
|
1119
|
|
|
'tag' => 'link', |
|
1120
|
|
|
'content' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '', |
|
1121
|
|
|
), |
|
1122
|
|
|
) |
|
1123
|
|
|
), |
|
1124
|
|
|
array( |
|
1125
|
|
|
'tag' => 'topic', |
|
1126
|
|
|
'content' => $row['id_topic'], |
|
1127
|
|
|
), |
|
1128
|
|
|
array( |
|
1129
|
|
|
'tag' => 'board', |
|
1130
|
|
|
'content' => array( |
|
1131
|
|
|
array( |
|
1132
|
|
|
'tag' => 'name', |
|
1133
|
|
|
'content' => $row['bname'], |
|
1134
|
|
|
), |
|
1135
|
|
|
array( |
|
1136
|
|
|
'tag' => 'id', |
|
1137
|
|
|
'content' => $row['id_board'], |
|
1138
|
|
|
), |
|
1139
|
|
|
array( |
|
1140
|
|
|
'tag' => 'link', |
|
1141
|
|
|
'content' => $scripturl . '?board=' . $row['id_board'] . '.0', |
|
1142
|
|
|
), |
|
1143
|
|
|
), |
|
1144
|
|
|
), |
|
1145
|
|
|
array( |
|
1146
|
|
|
'tag' => 'link', |
|
1147
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.0', |
|
1148
|
|
|
), |
|
1149
|
|
|
array( |
|
1150
|
|
|
'tag' => 'attachments', |
|
1151
|
|
|
'content' => $attachments, |
|
1152
|
|
|
), |
|
1153
|
|
|
), |
|
1154
|
|
|
); |
|
1155
|
|
|
} |
|
1156
|
|
|
} |
|
1157
|
|
|
$smcFunc['db_free_result']($request); |
|
1158
|
|
|
|
|
1159
|
|
|
return $data; |
|
1160
|
|
|
} |
|
1161
|
|
|
|
|
1162
|
|
|
/** |
|
1163
|
|
|
* Get the recent topics to display. |
|
1164
|
|
|
* The returned array will be generated to match the xml_format. |
|
1165
|
|
|
* @todo does not belong here. |
|
|
|
|
|
|
1166
|
|
|
* |
|
1167
|
|
|
* @param string $xml_format The XML format. Can be 'atom', 'rdf', 'rss', 'rss2' or 'smf' |
|
1168
|
|
|
* @return array An array of arrays containing data for the feed. Each array has keys corresponding to the appropriate tags for the specified format. |
|
1169
|
|
|
*/ |
|
1170
|
|
|
function getXmlRecent($xml_format) |
|
1171
|
|
|
{ |
|
1172
|
|
|
global $scripturl, $modSettings, $board, $txt; |
|
1173
|
|
|
global $query_this_board, $smcFunc, $context, $user_info, $sourcedir; |
|
1174
|
|
|
|
|
1175
|
|
|
require_once($sourcedir . '/Subs-Attachments.php'); |
|
1176
|
|
|
|
|
1177
|
|
|
$done = false; |
|
1178
|
|
|
$loops = 0; |
|
1179
|
|
|
while (!$done) |
|
1180
|
|
|
{ |
|
1181
|
|
|
$optimize_msg = implode(' AND ', $context['optimize_msg']); |
|
1182
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1183
|
|
|
SELECT m.id_msg |
|
1184
|
|
|
FROM {db_prefix}messages AS m |
|
1185
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board) |
|
1186
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
|
1187
|
|
|
WHERE ' . $query_this_board . (empty($optimize_msg) ? '' : ' |
|
1188
|
|
|
AND {raw:optimize_msg}') . (empty($board) ? '' : ' |
|
1189
|
|
|
AND m.id_board = {int:current_board}') . ($modSettings['postmod_active'] ? ' |
|
1190
|
|
|
AND m.approved = {int:is_approved}' : '') . ' |
|
1191
|
|
|
ORDER BY m.id_msg DESC |
|
1192
|
|
|
LIMIT {int:limit}', |
|
1193
|
|
|
array( |
|
1194
|
|
|
'limit' => $_GET['limit'], |
|
1195
|
|
|
'current_board' => $board, |
|
1196
|
|
|
'is_approved' => 1, |
|
1197
|
|
|
'optimize_msg' => $optimize_msg, |
|
1198
|
|
|
) |
|
1199
|
|
|
); |
|
1200
|
|
|
// If we don't have $_GET['limit'] results, try again with an unoptimized version covering all rows. |
|
1201
|
|
|
if ($loops < 2 && $smcFunc['db_num_rows']($request) < $_GET['limit']) |
|
1202
|
|
|
{ |
|
1203
|
|
|
$smcFunc['db_free_result']($request); |
|
1204
|
|
View Code Duplication |
if (empty($_REQUEST['boards']) && empty($board)) |
|
1205
|
|
|
unset($context['optimize_msg']['lowest']); |
|
1206
|
|
|
else |
|
1207
|
|
|
$context['optimize_msg']['lowest'] = $loops ? 'm.id_msg >= t.id_first_msg' : 'm.id_msg >= (t.id_last_msg - t.id_first_msg) / 2'; |
|
1208
|
|
|
$loops++; |
|
1209
|
|
|
} |
|
1210
|
|
|
else |
|
1211
|
|
|
$done = true; |
|
1212
|
|
|
} |
|
1213
|
|
|
$messages = array(); |
|
1214
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
|
|
|
|
|
1215
|
|
|
$messages[] = $row['id_msg']; |
|
1216
|
|
|
$smcFunc['db_free_result']($request); |
|
1217
|
|
|
|
|
1218
|
|
|
if (empty($messages)) |
|
1219
|
|
|
return array(); |
|
1220
|
|
|
|
|
1221
|
|
|
// Find the most recent posts this user can see. |
|
1222
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1223
|
|
|
SELECT |
|
1224
|
|
|
m.smileys_enabled, m.poster_time, m.id_msg, m.subject, m.body, m.id_topic, t.id_board, |
|
1225
|
|
|
b.name AS bname, t.num_replies, m.id_member, m.icon, mf.id_member AS id_first_member, |
|
1226
|
|
|
COALESCE(mem.real_name, m.poster_name) AS poster_name, mf.subject AS first_subject, |
|
1227
|
|
|
COALESCE(memf.real_name, mf.poster_name) AS first_poster_name, |
|
1228
|
|
|
COALESCE(mem.email_address, m.poster_email) AS poster_email, m.modified_time |
|
1229
|
|
|
FROM {db_prefix}messages AS m |
|
1230
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
|
1231
|
|
|
INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) |
|
1232
|
|
|
INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board) |
|
1233
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
|
1234
|
|
|
LEFT JOIN {db_prefix}members AS memf ON (memf.id_member = mf.id_member) |
|
1235
|
|
|
WHERE m.id_msg IN ({array_int:message_list}) |
|
1236
|
|
|
' . (empty($board) ? '' : 'AND t.id_board = {int:current_board}') . ' |
|
1237
|
|
|
ORDER BY m.id_msg DESC |
|
1238
|
|
|
LIMIT {int:limit}', |
|
1239
|
|
|
array( |
|
1240
|
|
|
'limit' => $_GET['limit'], |
|
1241
|
|
|
'current_board' => $board, |
|
1242
|
|
|
'message_list' => $messages, |
|
1243
|
|
|
) |
|
1244
|
|
|
); |
|
1245
|
|
|
$data = array(); |
|
1246
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
1247
|
|
|
{ |
|
1248
|
|
|
// Limit the length of the message, if the option is set. |
|
1249
|
|
View Code Duplication |
if (!empty($modSettings['xmlnews_maxlen']) && $smcFunc['strlen'](str_replace('<br>', "\n", $row['body'])) > $modSettings['xmlnews_maxlen']) |
|
1250
|
|
|
$row['body'] = strtr($smcFunc['substr'](str_replace('<br>', "\n", $row['body']), 0, $modSettings['xmlnews_maxlen'] - 3), array("\n" => '<br>')) . '...'; |
|
1251
|
|
|
|
|
1252
|
|
|
$row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']); |
|
1253
|
|
|
|
|
1254
|
|
|
censorText($row['body']); |
|
1255
|
|
|
censorText($row['subject']); |
|
1256
|
|
|
|
|
1257
|
|
|
// Do we want to include any attachments? |
|
1258
|
|
View Code Duplication |
if (!empty($modSettings['attachmentEnable']) && !empty($modSettings['xmlnews_attachments']) && allowedTo('view_attachments', $row['id_board'])) |
|
1259
|
|
|
{ |
|
1260
|
|
|
$attach_request = $smcFunc['db_query']('', ' |
|
1261
|
|
|
SELECT |
|
1262
|
|
|
a.id_attach, a.filename, COALESCE(a.size, 0) AS filesize, a.mime_type, a.downloads, a.approved, m.id_topic AS topic |
|
1263
|
|
|
FROM {db_prefix}attachments AS a |
|
1264
|
|
|
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
1265
|
|
|
WHERE a.attachment_type = {int:attachment_type} |
|
1266
|
|
|
AND a.id_msg = {int:message_id}', |
|
1267
|
|
|
array( |
|
1268
|
|
|
'message_id' => $row['id_msg'], |
|
1269
|
|
|
'attachment_type' => 0, |
|
1270
|
|
|
'is_approved' => 1, |
|
1271
|
|
|
) |
|
1272
|
|
|
); |
|
1273
|
|
|
$loaded_attachments = array(); |
|
1274
|
|
|
while ($attach = $smcFunc['db_fetch_assoc']($attach_request)) |
|
1275
|
|
|
{ |
|
1276
|
|
|
// Include approved attachments only |
|
1277
|
|
|
if ($attach['approved']) |
|
1278
|
|
|
$loaded_attachments['attachment_' . $attach['id_attach']] = $attach; |
|
1279
|
|
|
} |
|
1280
|
|
|
$smcFunc['db_free_result']($attach_request); |
|
1281
|
|
|
|
|
1282
|
|
|
// Sort the attachments by size to make things easier below |
|
1283
|
|
|
if (!empty($loaded_attachments)) |
|
1284
|
|
|
{ |
|
1285
|
|
|
uasort($loaded_attachments, function($a, $b) { |
|
|
|
|
|
|
1286
|
|
|
if ($a['filesize'] == $b['filesize']) |
|
1287
|
|
|
return 0; |
|
1288
|
|
|
return ($a['filesize'] < $b['filesize']) ? -1 : 1; |
|
1289
|
|
|
}); |
|
1290
|
|
|
} |
|
1291
|
|
|
else |
|
1292
|
|
|
$loaded_attachments = null; |
|
1293
|
|
|
} |
|
1294
|
|
|
else |
|
1295
|
|
|
$loaded_attachments = null; |
|
1296
|
|
|
|
|
1297
|
|
|
// Create a GUID for this post using the tag URI scheme |
|
1298
|
|
|
$guid = 'tag:' . parse_url($scripturl, PHP_URL_HOST) . ',' . gmdate('Y-m-d', $row['poster_time']) . ':msg=' . $row['id_msg']; |
|
1299
|
|
|
|
|
1300
|
|
|
// Doesn't work as well as news, but it kinda does.. |
|
1301
|
|
|
if ($xml_format == 'rss' || $xml_format == 'rss2') |
|
1302
|
|
|
{ |
|
1303
|
|
|
// Only one attachment allowed in RSS. |
|
1304
|
|
View Code Duplication |
if ($loaded_attachments !== null) |
|
1305
|
|
|
{ |
|
1306
|
|
|
$attachment = array_pop($loaded_attachments); |
|
1307
|
|
|
$enclosure = array( |
|
1308
|
|
|
'url' => fix_possible_url($scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach']), |
|
1309
|
|
|
'length' => $attachment['filesize'], |
|
1310
|
|
|
'type' => $attachment['mime_type'], |
|
1311
|
|
|
); |
|
1312
|
|
|
} |
|
1313
|
|
|
else |
|
1314
|
|
|
$enclosure = null; |
|
1315
|
|
|
|
|
1316
|
|
|
$data[] = array( |
|
1317
|
|
|
'tag' => 'item', |
|
1318
|
|
|
'content' => array( |
|
1319
|
|
|
array( |
|
1320
|
|
|
'tag' => 'title', |
|
1321
|
|
|
'content' => $row['subject'], |
|
1322
|
|
|
), |
|
1323
|
|
|
array( |
|
1324
|
|
|
'tag' => 'link', |
|
1325
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], |
|
1326
|
|
|
), |
|
1327
|
|
|
array( |
|
1328
|
|
|
'tag' => 'description', |
|
1329
|
|
|
'content' => $row['body'], |
|
1330
|
|
|
), |
|
1331
|
|
|
array( |
|
1332
|
|
|
'tag' => 'author', |
|
1333
|
|
|
'content' => (allowedTo('moderate_forum') || (!empty($row['id_member']) && $row['id_member'] == $user_info['id'])) ? $row['poster_email'] : null, |
|
1334
|
|
|
), |
|
1335
|
|
|
array( |
|
1336
|
|
|
'tag' => 'category', |
|
1337
|
|
|
'content' => $row['bname'], |
|
1338
|
|
|
), |
|
1339
|
|
|
array( |
|
1340
|
|
|
'tag' => 'comments', |
|
1341
|
|
|
'content' => $scripturl . '?action=post;topic=' . $row['id_topic'] . '.0', |
|
1342
|
|
|
), |
|
1343
|
|
|
array( |
|
1344
|
|
|
'tag' => 'pubDate', |
|
1345
|
|
|
'content' => gmdate('D, d M Y H:i:s \G\M\T', $row['poster_time']), |
|
1346
|
|
|
), |
|
1347
|
|
|
array( |
|
1348
|
|
|
'tag' => 'guid', |
|
1349
|
|
|
'content' => $guid, |
|
1350
|
|
|
'attributes' => array( |
|
1351
|
|
|
'isPermaLink' => 'false', |
|
1352
|
|
|
), |
|
1353
|
|
|
), |
|
1354
|
|
|
array( |
|
1355
|
|
|
'tag' => 'enclosure', |
|
1356
|
|
|
'attributes' => $enclosure, |
|
1357
|
|
|
), |
|
1358
|
|
|
), |
|
1359
|
|
|
); |
|
1360
|
|
|
} |
|
1361
|
|
|
elseif ($xml_format == 'rdf') |
|
1362
|
|
|
{ |
|
1363
|
|
|
$data[] = array( |
|
1364
|
|
|
'tag' => 'item', |
|
1365
|
|
|
'attributes' => array('rdf:about' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']), |
|
1366
|
|
|
'content' => array( |
|
1367
|
|
|
array( |
|
1368
|
|
|
'tag' => 'dc:format', |
|
1369
|
|
|
'content' => 'text/html', |
|
1370
|
|
|
), |
|
1371
|
|
|
array( |
|
1372
|
|
|
'tag' => 'title', |
|
1373
|
|
|
'content' => $row['subject'], |
|
1374
|
|
|
), |
|
1375
|
|
|
array( |
|
1376
|
|
|
'tag' => 'link', |
|
1377
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], |
|
1378
|
|
|
), |
|
1379
|
|
|
array( |
|
1380
|
|
|
'tag' => 'description', |
|
1381
|
|
|
'content' => $row['body'], |
|
1382
|
|
|
), |
|
1383
|
|
|
), |
|
1384
|
|
|
); |
|
1385
|
|
|
} |
|
1386
|
|
|
elseif ($xml_format == 'atom') |
|
1387
|
|
|
{ |
|
1388
|
|
|
// Only one attachment allowed |
|
1389
|
|
View Code Duplication |
if (!empty($loaded_attachments)) |
|
1390
|
|
|
{ |
|
1391
|
|
|
$attachment = array_pop($loaded_attachments); |
|
1392
|
|
|
$enclosure = array( |
|
1393
|
|
|
'rel' => 'enclosure', |
|
1394
|
|
|
'href' => fix_possible_url($scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach']), |
|
1395
|
|
|
'length' => $attachment['filesize'], |
|
1396
|
|
|
'type' => $attachment['mime_type'], |
|
1397
|
|
|
); |
|
1398
|
|
|
} |
|
1399
|
|
|
else |
|
1400
|
|
|
$enclosure = null; |
|
1401
|
|
|
|
|
1402
|
|
|
$data[] = array( |
|
1403
|
|
|
'tag' => 'entry', |
|
1404
|
|
|
'content' => array( |
|
1405
|
|
|
array( |
|
1406
|
|
|
'tag' => 'title', |
|
1407
|
|
|
'content' => $row['subject'], |
|
1408
|
|
|
), |
|
1409
|
|
|
array( |
|
1410
|
|
|
'tag' => 'link', |
|
1411
|
|
|
'attributes' => array( |
|
1412
|
|
|
'rel' => 'alternate', |
|
1413
|
|
|
'type' => 'text/html', |
|
1414
|
|
|
'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], |
|
1415
|
|
|
), |
|
1416
|
|
|
), |
|
1417
|
|
|
array( |
|
1418
|
|
|
'tag' => 'summary', |
|
1419
|
|
|
'attributes' => array('type' => 'html'), |
|
1420
|
|
|
'content' => $row['body'], |
|
1421
|
|
|
), |
|
1422
|
|
|
array( |
|
1423
|
|
|
'tag' => 'category', |
|
1424
|
|
|
'attributes' => array('term' => $row['bname']), |
|
1425
|
|
|
), |
|
1426
|
|
|
array( |
|
1427
|
|
|
'tag' => 'author', |
|
1428
|
|
|
'content' => array( |
|
1429
|
|
|
array( |
|
1430
|
|
|
'tag' => 'name', |
|
1431
|
|
|
'content' => $row['poster_name'], |
|
1432
|
|
|
), |
|
1433
|
|
|
array( |
|
1434
|
|
|
'tag' => 'email', |
|
1435
|
|
|
'content' => (allowedTo('moderate_forum') || (!empty($row['id_member']) && $row['id_member'] == $user_info['id'])) ? $row['poster_email'] : null, |
|
1436
|
|
|
), |
|
1437
|
|
|
array( |
|
1438
|
|
|
'tag' => 'uri', |
|
1439
|
|
|
'content' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : null, |
|
1440
|
|
|
), |
|
1441
|
|
|
), |
|
1442
|
|
|
), |
|
1443
|
|
|
array( |
|
1444
|
|
|
'tag' => 'published', |
|
1445
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $row['poster_time']), |
|
1446
|
|
|
), |
|
1447
|
|
|
array( |
|
1448
|
|
|
'tag' => 'updated', |
|
1449
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', empty($row['modified_time']) ? $row['poster_time'] : $row['modified_time']), |
|
1450
|
|
|
), |
|
1451
|
|
|
array( |
|
1452
|
|
|
'tag' => 'id', |
|
1453
|
|
|
'content' => $guid, |
|
1454
|
|
|
), |
|
1455
|
|
|
array( |
|
1456
|
|
|
'tag' => 'link', |
|
1457
|
|
|
'attributes' => $enclosure, |
|
1458
|
|
|
), |
|
1459
|
|
|
), |
|
1460
|
|
|
); |
|
1461
|
|
|
} |
|
1462
|
|
|
// A lot of information here. Should be enough to please the rss-ers. |
|
1463
|
|
|
else |
|
1464
|
|
|
{ |
|
1465
|
|
|
$attachments = array(); |
|
1466
|
|
View Code Duplication |
if (!empty($loaded_attachments)) |
|
1467
|
|
|
{ |
|
1468
|
|
|
foreach ($loaded_attachments as $attachment) |
|
1469
|
|
|
{ |
|
1470
|
|
|
$attachments[] = array( |
|
1471
|
|
|
'tag' => 'attachment', |
|
1472
|
|
|
'content' => array( |
|
1473
|
|
|
array( |
|
1474
|
|
|
'tag' => 'id', |
|
1475
|
|
|
'content' => $attachment['id_attach'], |
|
1476
|
|
|
), |
|
1477
|
|
|
array( |
|
1478
|
|
|
'tag' => 'name', |
|
1479
|
|
|
'content' => preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', $smcFunc['htmlspecialchars']($attachment['filename'])), |
|
1480
|
|
|
), |
|
1481
|
|
|
array( |
|
1482
|
|
|
'tag' => 'downloads', |
|
1483
|
|
|
'content' => $attachment['downloads'], |
|
1484
|
|
|
), |
|
1485
|
|
|
array( |
|
1486
|
|
|
'tag' => 'size', |
|
1487
|
|
|
'content' => ($attachment['filesize'] < 1024000) ? round($attachment['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'] : round($attachment['filesize'] / 1024 / 1024, 2) . ' ' . $txt['megabyte'], |
|
1488
|
|
|
), |
|
1489
|
|
|
array( |
|
1490
|
|
|
'tag' => 'byte_size', |
|
1491
|
|
|
'content' => $attachment['filesize'], |
|
1492
|
|
|
), |
|
1493
|
|
|
array( |
|
1494
|
|
|
'tag' => 'link', |
|
1495
|
|
|
'content' => $scripturl . '?action=dlattach;topic=' . $attachment['topic'] . '.0;attach=' . $attachment['id_attach'], |
|
1496
|
|
|
), |
|
1497
|
|
|
) |
|
1498
|
|
|
); |
|
1499
|
|
|
} |
|
1500
|
|
|
} |
|
1501
|
|
|
else |
|
1502
|
|
|
$attachments = null; |
|
1503
|
|
|
|
|
1504
|
|
|
$data[] = array( |
|
1505
|
|
|
'tag' => 'recent-post', |
|
1506
|
|
|
'content' => array( |
|
1507
|
|
|
array( |
|
1508
|
|
|
'tag' => 'time', |
|
1509
|
|
|
'content' => $smcFunc['htmlspecialchars'](strip_tags(timeformat($row['poster_time']))), |
|
1510
|
|
|
), |
|
1511
|
|
|
array( |
|
1512
|
|
|
'tag' => 'id', |
|
1513
|
|
|
'content' => $row['id_msg'], |
|
1514
|
|
|
), |
|
1515
|
|
|
array( |
|
1516
|
|
|
'tag' => 'subject', |
|
1517
|
|
|
'content' => $row['subject'], |
|
1518
|
|
|
), |
|
1519
|
|
|
array( |
|
1520
|
|
|
'tag' => 'body', |
|
1521
|
|
|
'content' => $row['body'], |
|
1522
|
|
|
), |
|
1523
|
|
|
array( |
|
1524
|
|
|
'tag' => 'starter', |
|
1525
|
|
|
'content' => array( |
|
1526
|
|
|
array( |
|
1527
|
|
|
'tag' => 'name', |
|
1528
|
|
|
'content' => $row['first_poster_name'], |
|
1529
|
|
|
), |
|
1530
|
|
|
array( |
|
1531
|
|
|
'tag' => 'id', |
|
1532
|
|
|
'content' => $row['id_first_member'], |
|
1533
|
|
|
), |
|
1534
|
|
|
array( |
|
1535
|
|
|
'tag' => 'link', |
|
1536
|
|
|
'content' => !empty($row['id_first_member']) ? $scripturl . '?action=profile;u=' . $row['id_first_member'] : '', |
|
1537
|
|
|
), |
|
1538
|
|
|
), |
|
1539
|
|
|
), |
|
1540
|
|
|
array( |
|
1541
|
|
|
'tag' => 'poster', |
|
1542
|
|
|
'content' => array( |
|
1543
|
|
|
array( |
|
1544
|
|
|
'tag' => 'name', |
|
1545
|
|
|
'content' => $row['poster_name'], |
|
1546
|
|
|
), |
|
1547
|
|
|
array( |
|
1548
|
|
|
'tag' => 'id', |
|
1549
|
|
|
'content' => $row['id_member'], |
|
1550
|
|
|
), |
|
1551
|
|
|
array( |
|
1552
|
|
|
'tag' => 'link', |
|
1553
|
|
|
'content' => !empty($row['id_member']) ? $scripturl . '?action=profile;u=' . $row['id_member'] : '', |
|
1554
|
|
|
), |
|
1555
|
|
|
), |
|
1556
|
|
|
), |
|
1557
|
|
|
array( |
|
1558
|
|
|
'tag' => 'topic', |
|
1559
|
|
|
'content' => array( |
|
1560
|
|
|
array( |
|
1561
|
|
|
'tag' => 'subject', |
|
1562
|
|
|
'content' => $row['first_subject'], |
|
1563
|
|
|
), |
|
1564
|
|
|
array( |
|
1565
|
|
|
'tag' => 'id', |
|
1566
|
|
|
'content' => $row['id_topic'], |
|
1567
|
|
|
), |
|
1568
|
|
|
array( |
|
1569
|
|
|
'tag' => 'link', |
|
1570
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.new#new', |
|
1571
|
|
|
), |
|
1572
|
|
|
), |
|
1573
|
|
|
), |
|
1574
|
|
|
array( |
|
1575
|
|
|
'tag' => 'board', |
|
1576
|
|
|
'content' => array( |
|
1577
|
|
|
array( |
|
1578
|
|
|
'tag' => 'name', |
|
1579
|
|
|
'content' => $row['bname'], |
|
1580
|
|
|
), |
|
1581
|
|
|
array( |
|
1582
|
|
|
'tag' => 'id', |
|
1583
|
|
|
'content' => $row['id_board'], |
|
1584
|
|
|
), |
|
1585
|
|
|
array( |
|
1586
|
|
|
'tag' => 'link', |
|
1587
|
|
|
'content' => $scripturl . '?board=' . $row['id_board'] . '.0', |
|
1588
|
|
|
), |
|
1589
|
|
|
), |
|
1590
|
|
|
), |
|
1591
|
|
|
array( |
|
1592
|
|
|
'tag' => 'link', |
|
1593
|
|
|
'content' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'], |
|
1594
|
|
|
), |
|
1595
|
|
|
array( |
|
1596
|
|
|
'tag' => 'attachments', |
|
1597
|
|
|
'content' => $attachments, |
|
1598
|
|
|
), |
|
1599
|
|
|
), |
|
1600
|
|
|
); |
|
1601
|
|
|
} |
|
1602
|
|
|
} |
|
1603
|
|
|
$smcFunc['db_free_result']($request); |
|
1604
|
|
|
|
|
1605
|
|
|
return $data; |
|
1606
|
|
|
} |
|
1607
|
|
|
|
|
1608
|
|
|
/** |
|
1609
|
|
|
* Get the profile information for member into an array, |
|
1610
|
|
|
* which will be generated to match the xml_format. |
|
1611
|
|
|
* @todo refactor. |
|
|
|
|
|
|
1612
|
|
|
* |
|
1613
|
|
|
* @param string $xml_format The XML format. Can be 'atom', 'rdf', 'rss', 'rss2' or 'smf' |
|
1614
|
|
|
* @return array An array profile data |
|
1615
|
|
|
*/ |
|
1616
|
|
|
function getXmlProfile($xml_format) |
|
1617
|
|
|
{ |
|
1618
|
|
|
global $scripturl, $memberContext, $user_profile, $user_info; |
|
1619
|
|
|
|
|
1620
|
|
|
// You must input a valid user.... |
|
1621
|
|
|
if (empty($_GET['u']) || !loadMemberData((int) $_GET['u'])) |
|
1622
|
|
|
return array(); |
|
1623
|
|
|
|
|
1624
|
|
|
// Make sure the id is a number and not "I like trying to hack the database". |
|
1625
|
|
|
$_GET['u'] = (int) $_GET['u']; |
|
1626
|
|
|
// Load the member's contextual information! |
|
1627
|
|
|
if (!loadMemberContext($_GET['u']) || !allowedTo('profile_view')) |
|
1628
|
|
|
return array(); |
|
1629
|
|
|
|
|
1630
|
|
|
// Okay, I admit it, I'm lazy. Stupid $_GET['u'] is long and hard to type. |
|
1631
|
|
|
$profile = &$memberContext[$_GET['u']]; |
|
1632
|
|
|
|
|
1633
|
|
|
// Create a GUID for this member using the tag URI scheme |
|
1634
|
|
|
$guid = 'tag:' . parse_url($scripturl, PHP_URL_HOST) . ',' . gmdate('Y-m-d', $user_profile[$profile['id']]['date_registered']) . ':member=' . $profile['id']; |
|
1635
|
|
|
|
|
1636
|
|
|
if ($xml_format == 'rss' || $xml_format == 'rss2') |
|
1637
|
|
|
{ |
|
1638
|
|
|
$data[] = array( |
|
|
|
|
|
|
1639
|
|
|
'tag' => 'item', |
|
1640
|
|
|
'content' => array( |
|
1641
|
|
|
array( |
|
1642
|
|
|
'tag' => 'title', |
|
1643
|
|
|
'content' => $profile['name'], |
|
1644
|
|
|
), |
|
1645
|
|
|
array( |
|
1646
|
|
|
'tag' => 'link', |
|
1647
|
|
|
'content' => $scripturl . '?action=profile;u=' . $profile['id'], |
|
1648
|
|
|
), |
|
1649
|
|
|
array( |
|
1650
|
|
|
'tag' => 'description', |
|
1651
|
|
|
'content' => isset($profile['group']) ? $profile['group'] : $profile['post_group'], |
|
1652
|
|
|
), |
|
1653
|
|
|
array( |
|
1654
|
|
|
'tag' => 'comments', |
|
1655
|
|
|
'content' => $scripturl . '?action=pm;sa=send;u=' . $profile['id'], |
|
1656
|
|
|
), |
|
1657
|
|
|
array( |
|
1658
|
|
|
'tag' => 'pubDate', |
|
1659
|
|
|
'content' => gmdate('D, d M Y H:i:s \G\M\T', $user_profile[$profile['id']]['date_registered']), |
|
1660
|
|
|
), |
|
1661
|
|
|
array( |
|
1662
|
|
|
'tag' => 'guid', |
|
1663
|
|
|
'content' => $guid, |
|
1664
|
|
|
'attributes' => array( |
|
1665
|
|
|
'isPermaLink' => 'false', |
|
1666
|
|
|
), |
|
1667
|
|
|
), |
|
1668
|
|
|
) |
|
1669
|
|
|
); |
|
1670
|
|
|
} |
|
1671
|
|
|
elseif ($xml_format == 'rdf') |
|
1672
|
|
|
{ |
|
1673
|
|
|
$data[] = array( |
|
|
|
|
|
|
1674
|
|
|
'tag' => 'item', |
|
1675
|
|
|
'attributes' => array('rdf:about' => $scripturl . '?action=profile;u=' . $profile['id']), |
|
1676
|
|
|
'content' => array( |
|
1677
|
|
|
array( |
|
1678
|
|
|
'tag' => 'dc:format', |
|
1679
|
|
|
'content' => 'text/html', |
|
1680
|
|
|
), |
|
1681
|
|
|
array( |
|
1682
|
|
|
'tag' => 'title', |
|
1683
|
|
|
'content' => $profile['name'], |
|
1684
|
|
|
), |
|
1685
|
|
|
array( |
|
1686
|
|
|
'tag' => 'link', |
|
1687
|
|
|
'content' => $scripturl . '?action=profile;u=' . $profile['id'], |
|
1688
|
|
|
), |
|
1689
|
|
|
array( |
|
1690
|
|
|
'tag' => 'description', |
|
1691
|
|
|
'content' => isset($profile['group']) ? $profile['group'] : $profile['post_group'], |
|
1692
|
|
|
), |
|
1693
|
|
|
) |
|
1694
|
|
|
); |
|
1695
|
|
|
} |
|
1696
|
|
|
elseif ($xml_format == 'atom') |
|
1697
|
|
|
{ |
|
1698
|
|
|
$data[] = array( |
|
|
|
|
|
|
1699
|
|
|
'tag' => 'entry', |
|
1700
|
|
|
'content' => array( |
|
1701
|
|
|
array( |
|
1702
|
|
|
'tag' => 'title', |
|
1703
|
|
|
'content' => $profile['name'], |
|
1704
|
|
|
), |
|
1705
|
|
|
array( |
|
1706
|
|
|
'tag' => 'link', |
|
1707
|
|
|
'attributes' => array( |
|
1708
|
|
|
'rel' => 'alternate', |
|
1709
|
|
|
'type' => 'text/html', |
|
1710
|
|
|
'href' => $scripturl . '?action=profile;u=' . $profile['id'], |
|
1711
|
|
|
), |
|
1712
|
|
|
), |
|
1713
|
|
|
array( |
|
1714
|
|
|
'tag' => 'summary', |
|
1715
|
|
|
'attributes' => array('type' => 'html'), |
|
1716
|
|
|
'content' => isset($profile['group']) ? $profile['group'] : $profile['post_group'], |
|
1717
|
|
|
), |
|
1718
|
|
|
array( |
|
1719
|
|
|
'tag' => 'author', |
|
1720
|
|
|
'content' => array( |
|
1721
|
|
|
array( |
|
1722
|
|
|
'tag' => 'name', |
|
1723
|
|
|
'content' => $profile['name'], |
|
1724
|
|
|
), |
|
1725
|
|
|
array( |
|
1726
|
|
|
'tag' => 'email', |
|
1727
|
|
|
'content' => $profile['show_email'] ? $profile['email'] : null, |
|
1728
|
|
|
), |
|
1729
|
|
|
array( |
|
1730
|
|
|
'tag' => 'uri', |
|
1731
|
|
|
'content' => !empty($profile['website']['url']) ? $profile['website']['url'] : null, |
|
1732
|
|
|
), |
|
1733
|
|
|
), |
|
1734
|
|
|
), |
|
1735
|
|
|
array( |
|
1736
|
|
|
'tag' => 'published', |
|
1737
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user_profile[$profile['id']]['date_registered']), |
|
1738
|
|
|
), |
|
1739
|
|
|
array( |
|
1740
|
|
|
'tag' => 'updated', |
|
1741
|
|
|
'content' => gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user_profile[$profile['id']]['last_login']), |
|
1742
|
|
|
), |
|
1743
|
|
|
array( |
|
1744
|
|
|
'tag' => 'id', |
|
1745
|
|
|
'content' => $guid, |
|
1746
|
|
|
), |
|
1747
|
|
|
) |
|
1748
|
|
|
); |
|
1749
|
|
|
} |
|
1750
|
|
|
else |
|
1751
|
|
|
{ |
|
1752
|
|
|
$data = array( |
|
1753
|
|
|
array( |
|
1754
|
|
|
'tag' => 'username', |
|
1755
|
|
|
'content' => $user_info['is_admin'] || $user_info['id'] == $profile['id'] ? $profile['username'] : null, |
|
1756
|
|
|
), |
|
1757
|
|
|
array( |
|
1758
|
|
|
'tag' => 'name', |
|
1759
|
|
|
'content' => $profile['name'], |
|
1760
|
|
|
), |
|
1761
|
|
|
array( |
|
1762
|
|
|
'tag' => 'link', |
|
1763
|
|
|
'content' => $scripturl . '?action=profile;u=' . $profile['id'], |
|
1764
|
|
|
), |
|
1765
|
|
|
array( |
|
1766
|
|
|
'tag' => 'posts', |
|
1767
|
|
|
'content' => $profile['posts'], |
|
1768
|
|
|
), |
|
1769
|
|
|
array( |
|
1770
|
|
|
'tag' => 'post-group', |
|
1771
|
|
|
'content' => $profile['post_group'], |
|
1772
|
|
|
), |
|
1773
|
|
|
array( |
|
1774
|
|
|
'tag' => 'language', |
|
1775
|
|
|
'content' => $profile['language'], |
|
1776
|
|
|
), |
|
1777
|
|
|
array( |
|
1778
|
|
|
'tag' => 'last-login', |
|
1779
|
|
|
'content' => gmdate('D, d M Y H:i:s \G\M\T', $user_profile[$profile['id']]['last_login']), |
|
1780
|
|
|
), |
|
1781
|
|
|
array( |
|
1782
|
|
|
'tag' => 'registered', |
|
1783
|
|
|
'content' => gmdate('D, d M Y H:i:s \G\M\T', $user_profile[$profile['id']]['date_registered']), |
|
1784
|
|
|
), |
|
1785
|
|
|
array( |
|
1786
|
|
|
'tag' => 'gender', |
|
1787
|
|
|
'content' => !empty($profile['gender']['name']) ? $profile['gender']['name'] : null, |
|
1788
|
|
|
), |
|
1789
|
|
|
array( |
|
1790
|
|
|
'tag' => 'avatar', |
|
1791
|
|
|
'content' => !empty($profile['avatar']['url']) ? $profile['avatar']['url'] : null, |
|
1792
|
|
|
), |
|
1793
|
|
|
array( |
|
1794
|
|
|
'tag' => 'online', |
|
1795
|
|
|
'content' => !empty($profile['online']['is_online']) ? '' : null, |
|
1796
|
|
|
), |
|
1797
|
|
|
array( |
|
1798
|
|
|
'tag' => 'signature', |
|
1799
|
|
|
'content' => !empty($profile['signature']) ? $profile['signature'] : null, |
|
1800
|
|
|
), |
|
1801
|
|
|
array( |
|
1802
|
|
|
'tag' => 'blurb', |
|
1803
|
|
|
'content' => !empty($profile['blurb']) ? $profile['blurb'] : null, |
|
1804
|
|
|
), |
|
1805
|
|
|
array( |
|
1806
|
|
|
'tag' => 'title', |
|
1807
|
|
|
'content' => !empty($profile['title']) ? $profile['title'] : null, |
|
1808
|
|
|
), |
|
1809
|
|
|
array( |
|
1810
|
|
|
'tag' => 'position', |
|
1811
|
|
|
'content' => !empty($profile['group']) ? $profile['group'] : null, |
|
1812
|
|
|
), |
|
1813
|
|
|
array( |
|
1814
|
|
|
'tag' => 'email', |
|
1815
|
|
|
'content' => !empty($profile['show_email']) ? $profile['show_email'] : null, |
|
1816
|
|
|
), |
|
1817
|
|
|
array( |
|
1818
|
|
|
'tag' => 'website', |
|
1819
|
|
|
'content' => empty($profile['website']['url']) ? null : array( |
|
1820
|
|
|
array( |
|
1821
|
|
|
'tag' => 'title', |
|
1822
|
|
|
'content' => !empty($profile['website']['title']) ? $profile['website']['title'] : null, |
|
1823
|
|
|
), |
|
1824
|
|
|
array( |
|
1825
|
|
|
'tag' => 'link', |
|
1826
|
|
|
'content' => $profile['website']['url'], |
|
1827
|
|
|
), |
|
1828
|
|
|
), |
|
1829
|
|
|
), |
|
1830
|
|
|
); |
|
1831
|
|
|
|
|
1832
|
|
|
if (!empty($profile['birth_date']) && substr($profile['birth_date'], 0, 4) != '0000') |
|
1833
|
|
|
{ |
|
1834
|
|
|
list ($birth_year, $birth_month, $birth_day) = sscanf($profile['birth_date'], '%d-%d-%d'); |
|
1835
|
|
|
$datearray = getdate(forum_time()); |
|
1836
|
|
|
$age = $datearray['year'] - $birth_year - (($datearray['mon'] > $birth_month || ($datearray['mon'] == $birth_month && $datearray['mday'] >= $birth_day)) ? 0 : 1); |
|
1837
|
|
|
|
|
1838
|
|
|
$data[] = array( |
|
1839
|
|
|
'tag' => 'age', |
|
1840
|
|
|
'content' => $age, |
|
1841
|
|
|
); |
|
1842
|
|
|
|
|
1843
|
|
|
} |
|
1844
|
|
|
} |
|
1845
|
|
|
|
|
1846
|
|
|
// Save some memory. |
|
1847
|
|
|
unset($profile, $memberContext[$_GET['u']]); |
|
1848
|
|
|
|
|
1849
|
|
|
return $data; |
|
1850
|
|
|
} |
|
1851
|
|
|
|
|
1852
|
|
|
?> |
PHP provides two ways to mark string literals. Either with single quotes
'literal'or with double quotes"literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (
\') and the backslash (\\). Every other character is displayed as is.Double quoted string literals may contain other variables or more complex escape sequences.
will print an indented:
Single is ValueIf your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.
For more information on PHP string literals and available escape sequences see the PHP core documentation.