]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/MobileProfile/MobileProfilePlugin.php
Merge branch 'master' of gitorious.org:statusnet/mainline into testing
[quix0rs-gnu-social.git] / plugins / MobileProfile / MobileProfilePlugin.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * XHTML Mobile Profile plugin that uses WAP 2.0 Plugin
6  *
7  * PHP version 5
8  *
9  * LICENCE: This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Affero General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @category  Plugin
23  * @package   StatusNet
24  * @author    Sarven Capadisli <csarven@status.net>
25  * @copyright 2009 StatusNet, Inc.
26  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
27  * @link      http://status.net/
28  */
29
30 if (!defined('STATUSNET') && !defined('LACONICA')) {
31     exit(1);
32 }
33
34 define('PAGE_TYPE_PREFS_MOBILEPROFILE',
35        'application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html;q=0.9');
36
37 require_once INSTALLDIR.'/plugins/Mobile/WAP20Plugin.php';
38
39
40 /**
41  * Superclass for plugin to output XHTML Mobile Profile
42  *
43  * @category Plugin
44  * @package  StatusNet
45  * @author   Sarven Capadisli <csarven@status.net>
46  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
47  * @link     http://status.net/
48  */
49
50 class MobileProfilePlugin extends WAP20Plugin
51 {
52     public $DTD            = null;
53     public $serveMobile    = false;
54     public $mobileFeatures = array();
55
56     function __construct($DTD='http://www.wapforum.org/DTD/xhtml-mobile10.dtd')
57     {
58         $this->DTD = $DTD;
59
60         parent::__construct();
61     }
62
63
64     function onStartShowHTML($action)
65     {
66         // XXX: This should probably graduate to WAP20Plugin
67
68         // If they are on the mobile site, serve them MP
69         if ((common_config('site', 'mobileserver').'/'.
70              common_config('site', 'path').'/' == 
71             $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'])) {
72
73             $this->serveMobile = true;
74         } else {
75             // If they like the WAP 2.0 mimetype, serve them MP
76             if (strstr('application/vnd.wap.xhtml+xml', $type) !== false) {
77                 $this->serveMobile = true;
78             } else {
79                 // If they are a mobile device that supports WAP 2.0, 
80                 // serve them MP
81
82                 // XXX: Browser sniffing sucks
83
84                 // I really don't like going through this every page, 
85                 // perhaps use $_SESSION or cookies
86
87                 // May be better to group the devices in terms of 
88                 // low,mid,high-end
89
90                 // Or, detect the mobile devices based on their support for 
91                 // MP 1.0, 1.1, or 1.2 may be ideal. Possible?
92
93                 $this->mobiledevices = array(
94                     'alcatel',
95                     'android',
96                     'audiovox',
97                     'au-mic,',
98                     'avantgo',
99                     'blackberry',
100                     'blazer',
101                     'cldc-',
102                     'danger',
103                     'epoc',
104                     'ericsson',
105                     'ericy',
106                     'iphone',
107                     'ipaq',
108                     'ipod',
109                     'j2me',
110                     'lg',
111                     'midp-',
112                     'mobile',
113                     'mot',
114                     'netfront',
115                     'nitro',
116                     'nokia',
117                     'opera mini',
118                     'palm',
119                     'palmsource',
120                     'panasonic',
121                     'philips',
122                     'pocketpc',
123                     'portalmmm',
124                     'rover',
125                     'samsung',
126                     'sanyo',
127                     'series60',
128                     'sharp',
129                     'sie-',
130                     'smartphone',
131                     'sony',
132                     'symbian',
133                     'up.browser',
134                     'up.link',
135                     'up.link',
136                     'vodafone',
137                     'wap1',
138                     'wap2',
139                     'windows ce'
140                 );
141
142                 $httpuseragent = strtolower($_SERVER['HTTP_USER_AGENT']);
143
144                 foreach ($this->mobiledevices as $md) {
145                     if (strstr($httpuseragent, $md) !== false) {
146                         $this->setMobileFeatures($httpuseragent);
147
148                         $this->serveMobile = true;
149                         break;
150                     }
151                 }
152             }
153
154             // If they are okay with MP, and the site has a mobile server, 
155             // redirect there
156             if ($this->serveMobile && 
157                 common_config('site', 'mobileserver') !== false &&
158                 (common_config('site', 'mobileserver') != 
159                     common_config('site', 'server'))) {
160
161                 // FIXME: Redirect to equivalent page on mobile site instead
162                 common_redirect($this->_common_path(''), 302);
163             }
164         }
165
166         if (!$this->serveMobile) {
167             return true;
168         }
169
170         if (!$type) {
171             $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ?
172               $_SERVER['HTTP_ACCEPT'] : null;
173
174             $cp = common_accept_to_prefs($httpaccept);
175             $sp = common_accept_to_prefs(PAGE_TYPE_PREFS_MOBILEPROFILE);
176
177             $type = common_negotiate_type($cp, $sp);
178
179             if (!$type) {
180                 throw new ClientException(_('This page is not available in a '.
181                                             'media type you accept'), 406);
182             }
183         }
184
185         header('Content-Type: '.$type);
186
187         $action->extraHeaders();
188         if (preg_match("/.*\/.*xml/", $type)) {
189             // Required for XML documents
190             $action->xw->startDocument('1.0', 'UTF-8');
191         }
192         $action->xw->writeDTD('html',
193                         '-//WAPFORUM//DTD XHTML Mobile 1.0//EN',
194                         $this->DTD);
195
196         $language = $action->getLanguage();
197
198         $action->elementStart('html', array('xmlns' => 'http://www.w3.org/1999/xhtml',
199                                             'xml:lang' => $language));
200
201         return false;
202     }
203
204
205     function setMobileFeatures($useragent)
206     {
207         $mobiledeviceInputFileType = array(
208             'nokia'
209         );
210
211         $this->mobileFeatures['inputfiletype'] = false;
212
213         foreach ($mobiledeviceInputFileType as $md) {
214             if (strstr($useragent, $md) !== false) {
215                 $this->mobileFeatures['inputfiletype'] = true;
216                 break;
217             }
218         }
219     }
220
221
222     function onStartShowHeadElements($action)
223     {
224         if (!$action->serveMobile) {
225             return true;
226         }
227
228         $action->showTitle();
229         $action->showShortcutIcon();
230         $action->showStylesheets();
231         $action->showFeeds();
232         $action->showDescription();
233         $action->extraHead();
234     }
235
236
237     function onStartShowStatusNetStyles($action)
238     {
239         if (!$this->serveMobile) {
240             return true;
241         }
242
243         $action->cssLink('css/display.css');
244
245         if (file_exists(Theme::file('css/mp-screen.css'))) {
246             $action->cssLink('css/mp-screen.css', null, 'screen');
247         } else {
248             $action->cssLink('plugins/MobileProfile/mp-screen.css',null,'screen');
249         }
250
251         if (file_exists(Theme::file('css/mp-handheld.css'))) {
252             $action->cssLink('css/mp-handheld.css', null, 'handheld');
253         } else {
254             $action->cssLink('plugins/MobileProfile/mp-handheld.css',null,'handheld');
255         }
256
257         return false;
258     }
259
260
261     function onStartShowUAStyles($action) {
262         if (!$this->serveMobile) {
263             return true;
264         }
265
266         return false;
267     }
268
269     function onStartShowHeader($action)
270     {
271         if (!$this->serveMobile) {
272             return true;
273         }
274
275         $action->elementStart('div', array('id' => 'header'));
276         $this->_showLogo($action);
277         $this->_showPrimaryNav($action);
278         if (common_logged_in()) {
279             $action->showNoticeForm();
280         }
281         $action->elementEnd('div');
282
283         return false;
284     }
285
286
287     function _showLogo($action)
288     {
289         $action->elementStart('address', 'vcard');
290         $action->elementStart('a', array('class' => 'url home bookmark',
291                                        'href' => common_local_url('public')));
292         if (common_config('site', 'mobilelogo') || 
293             file_exists(Theme::file('logo.png')) || 
294             file_exists(Theme::file('mobilelogo.png'))) {
295
296             $action->element('img', array('class' => 'photo',
297                 'src' => (common_config('site', 'mobilelogo')) ? common_config('site', 'mobilelogo') : 
298                             ((file_exists(Theme::file('mobilelogo.png'))) ? (Theme::path('mobilelogo.png')) : Theme::path('logo.png')),
299                 'alt' => common_config('site', 'name')));
300         }
301         $action->element('span', array('class' => 'fn org'), common_config('site', 'name'));
302         $action->elementEnd('a');
303         $action->elementEnd('address');
304     }
305
306
307     function _showPrimaryNav($action)
308     {
309         $user    = common_current_user();
310         $connect = '';
311         if (common_config('xmpp', 'enabled')) {
312             $connect = 'imsettings';
313         } else if (common_config('sms', 'enabled')) {
314             $connect = 'smssettings';
315         } else if (common_config('twitter', 'enabled')) {
316             $connect = 'twittersettings';
317         }
318
319         $action->elementStart('ul', array('id' => 'site_nav_global_primary'));
320         if ($user) {
321             $action->menuItem(common_local_url('all', array('nickname' => $user->nickname)),
322                             _('Home'));
323             $action->menuItem(common_local_url('profilesettings'),
324                             _('Account'));
325             if ($connect) {
326                 $action->menuItem(common_local_url($connect),
327                                 _('Connect'));
328             }
329             if ($user->hasRight(Right::CONFIGURESITE)) {
330                 $action->menuItem(common_local_url('siteadminpanel'),
331                                 _('Admin'), _('Change site configuration'), false, 'nav_admin');
332             }
333             if (common_config('invite', 'enabled')) {
334                 $action->menuItem(common_local_url('invite'),
335                                 _('Invite'));
336             }
337             $action->menuItem(common_local_url('logout'),
338                             _('Logout'));
339         } else {
340             if (!common_config('site', 'closed')) {
341                 $action->menuItem(common_local_url('register'),
342                                 _('Register'));
343             }
344             $action->menuItem(common_local_url('login'),
345                             _('Login'));
346         }
347         if ($user || !common_config('site', 'private')) {
348             $action->menuItem(common_local_url('peoplesearch'),
349                             _('Search'));
350         }
351         $action->elementEnd('ul');
352     }
353
354
355     function onStartShowNoticeFormData($form)
356     {
357         if (!$this->serveMobile) {
358             return true;
359         }
360
361         $form->out->element('textarea', array('id' => 'notice_data-text',
362                                               'cols' => 15,
363                                               'rows' => 4,
364                                               'name' => 'status_textarea'),
365                             ($form->content) ? $form->content : '');
366
367         $contentLimit = Notice::maxContent();
368
369         if ($contentLimit > 0) {
370             $form->out->element('div', array('id' => 'notice_text-count'),
371                                 $contentLimit);
372         }
373
374         if (common_config('attachments', 'uploads')) {
375             if ($this->mobileFeatures['inputfiletype']) {
376                 $form->out->element('label', array('for' => 'notice_data-attach'), _('Attach'));
377                 $form->out->element('input', array('id' => 'notice_data-attach',
378                                                    'type' => 'file',
379                                                    'name' => 'attach',
380                                                    'title' => _('Attach a file')));
381                 $form->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota'));
382             }
383         }
384         if ($form->action) {
385             $form->out->hidden('notice_return-to', $form->action, 'returnto');
386         }
387         $form->out->hidden('notice_in-reply-to', $form->inreplyto, 'inreplyto');
388
389         return false;
390     }
391
392
393     function onStartShowAside($action)
394     {
395         if ($this->serveMobile) {
396             return false;
397         }
398     }
399
400
401     function onStartShowScripts($action)
402     {
403
404     }
405
406
407     function _common_path($relative, $ssl=false)
408     {
409         $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : '';
410
411         if (($ssl && (common_config('site', 'ssl') === 'sometimes'))
412             || common_config('site', 'ssl') === 'always') {
413             $proto = 'https';
414             if (is_string(common_config('site', 'sslserver')) &&
415                 mb_strlen(common_config('site', 'sslserver')) > 0) {
416                 $serverpart = common_config('site', 'sslserver');
417             } else {
418                 $serverpart = common_config('site', 'mobileserver');
419             }
420         } else {
421             $proto      = 'http';
422             $serverpart = common_config('site', 'mobileserver');
423         }
424
425         return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
426     }
427
428     function onPluginVersion(&$versions)
429     {
430         $versions[] = array('name' => 'MobileProfile',
431                             'version' => STATUSNET_VERSION,
432                             'author' => 'Sarven Capadisli',
433                             'homepage' => 'http://status.net/wiki/Plugin:MobileProfile',
434                             'rawdescription' =>
435                             _m('XHTML MobileProfile output for supporting user agents.'));
436         return true;
437     }
438 }