]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/MobileProfile/MobileProfilePlugin.php
60bb3b68fa3c968aa56c57571ca684c264d26976
[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             // @fixme $type is undefined, making this if case useless and spewing errors.
77             // What's the intent?
78             //if (strstr('application/vnd.wap.xhtml+xml', $type) !== false) {
79             //    $this->serveMobile = true;
80             //} else {
81                 // If they are a mobile device that supports WAP 2.0, 
82                 // serve them MP
83
84                 // XXX: Browser sniffing sucks
85
86                 // I really don't like going through this every page, 
87                 // perhaps use $_SESSION or cookies
88
89                 // May be better to group the devices in terms of 
90                 // low,mid,high-end
91
92                 // Or, detect the mobile devices based on their support for 
93                 // MP 1.0, 1.1, or 1.2 may be ideal. Possible?
94
95                 $this->mobiledevices = array(
96                     'alcatel',
97                     'android',
98                     'audiovox',
99                     'au-mic,',
100                     'avantgo',
101                     'blackberry',
102                     'blazer',
103                     'cldc-',
104                     'danger',
105                     'epoc',
106                     'ericsson',
107                     'ericy',
108                     'iphone',
109                     'ipaq',
110                     'ipod',
111                     'j2me',
112                     'lg',
113                     'midp-',
114                     'mobile',
115                     'mot',
116                     'netfront',
117                     'nitro',
118                     'nokia',
119                     'opera mini',
120                     'palm',
121                     'palmsource',
122                     'panasonic',
123                     'philips',
124                     'pocketpc',
125                     'portalmmm',
126                     'rover',
127                     'samsung',
128                     'sanyo',
129                     'series60',
130                     'sharp',
131                     'sie-',
132                     'smartphone',
133                     'sony',
134                     'symbian',
135                     'up.browser',
136                     'up.link',
137                     'up.link',
138                     'vodafone',
139                     'wap1',
140                     'wap2',
141                     'windows ce'
142                 );
143
144                 $blacklist = array(
145                     'ipad', // Larger screen handles the full theme fairly well.
146                 );
147
148                 $httpuseragent = strtolower($_SERVER['HTTP_USER_AGENT']);
149
150                 foreach ($blacklist as $md) {
151                     if (strstr($httpuseragent, $md) !== false) {
152                         $this->serveMobile = false;
153                         return true;
154                     }
155                 }
156
157                 foreach ($this->mobiledevices as $md) {
158                     if (strstr($httpuseragent, $md) !== false) {
159                         $this->setMobileFeatures($httpuseragent);
160
161                         $this->serveMobile = true;
162                         break;
163                     }
164                 }
165             //}
166
167             // If they are okay with MP, and the site has a mobile server, 
168             // redirect there
169             if ($this->serveMobile && 
170                 common_config('site', 'mobileserver') !== false &&
171                 (common_config('site', 'mobileserver') != 
172                     common_config('site', 'server'))) {
173
174                 // FIXME: Redirect to equivalent page on mobile site instead
175                 common_redirect($this->_common_path(''), 302);
176             }
177         }
178
179         if (!$this->serveMobile) {
180             return true;
181         }
182
183         // @fixme $type is undefined, making this if case useless and spewing errors.
184         // What's the intent?
185         //if (!$type) {
186             $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ?
187               $_SERVER['HTTP_ACCEPT'] : null;
188
189             $cp = common_accept_to_prefs($httpaccept);
190             $sp = common_accept_to_prefs(PAGE_TYPE_PREFS_MOBILEPROFILE);
191
192             $type = common_negotiate_type($cp, $sp);
193
194             if (!$type) {
195                 throw new ClientException(_('This page is not available in a '.
196                                             'media type you accept'), 406);
197             }
198         //}
199
200         header('Content-Type: '.$type);
201
202         $action->extraHeaders();
203         if (preg_match("/.*\/.*xml/", $type)) {
204             // Required for XML documents
205             $action->xw->startDocument('1.0', 'UTF-8');
206         }
207         $action->xw->writeDTD('html',
208                         '-//WAPFORUM//DTD XHTML Mobile 1.0//EN',
209                         $this->DTD);
210
211         $language = $action->getLanguage();
212
213         $action->elementStart('html', array('xmlns' => 'http://www.w3.org/1999/xhtml',
214                                             'xml:lang' => $language));
215
216         return false;
217     }
218
219
220     function setMobileFeatures($useragent)
221     {
222         $mobiledeviceInputFileType = array(
223             'nokia'
224         );
225
226         $this->mobileFeatures['inputfiletype'] = false;
227
228         foreach ($mobiledeviceInputFileType as $md) {
229             if (strstr($useragent, $md) !== false) {
230                 $this->mobileFeatures['inputfiletype'] = true;
231                 break;
232             }
233         }
234     }
235
236
237     function onStartShowHeadElements($action)
238     {
239         // @fixme nothing appears to set a serveMobile on any action,
240         // so this is useless and spews errors. Is this supposed to be
241         // checking $this?
242         //if (!$action->serveMobile) {
243         //    return true;
244         //}
245
246         $action->showTitle();
247         $action->showShortcutIcon();
248         $action->showStylesheets();
249         $action->showFeeds();
250         $action->showDescription();
251         $action->extraHead();
252     }
253
254
255     function onStartShowStatusNetStyles($action)
256     {
257         if (!$this->serveMobile) {
258             return true;
259         }
260
261         $action->cssLink('css/display.css');
262
263         if (file_exists(Theme::file('css/mp-screen.css'))) {
264             $action->cssLink('css/mp-screen.css', null, 'screen');
265         } else {
266             $action->cssLink('plugins/MobileProfile/mp-screen.css',null,'screen');
267         }
268
269         if (file_exists(Theme::file('css/mp-handheld.css'))) {
270             $action->cssLink('css/mp-handheld.css', null, 'handheld');
271         } else {
272             $action->cssLink('plugins/MobileProfile/mp-handheld.css',null,'handheld');
273         }
274
275         return false;
276     }
277
278
279     function onStartShowUAStyles($action) {
280         if (!$this->serveMobile) {
281             return true;
282         }
283
284         return false;
285     }
286
287     function onStartShowHeader($action)
288     {
289         if (!$this->serveMobile) {
290             return true;
291         }
292
293         $action->elementStart('div', array('id' => 'header'));
294         $this->_showLogo($action);
295         $this->_showPrimaryNav($action);
296         if (common_logged_in()) {
297             $action->showNoticeForm();
298         }
299         $action->elementEnd('div');
300
301         return false;
302     }
303
304
305     function _showLogo($action)
306     {
307         $action->elementStart('address', 'vcard');
308         $action->elementStart('a', array('class' => 'url home bookmark',
309                                        'href' => common_local_url('public')));
310         if (common_config('site', 'mobilelogo') || 
311             file_exists(Theme::file('logo.png')) || 
312             file_exists(Theme::file('mobilelogo.png'))) {
313
314             $action->element('img', array('class' => 'photo',
315                 'src' => (common_config('site', 'mobilelogo')) ? common_config('site', 'mobilelogo') : 
316                             ((file_exists(Theme::file('mobilelogo.png'))) ? (Theme::path('mobilelogo.png')) : Theme::path('logo.png')),
317                 'alt' => common_config('site', 'name')));
318         }
319         $action->element('span', array('class' => 'fn org'), common_config('site', 'name'));
320         $action->elementEnd('a');
321         $action->elementEnd('address');
322     }
323
324
325     function _showPrimaryNav($action)
326     {
327         $user    = common_current_user();
328         $action->elementStart('ul', array('id' => 'site_nav_global_primary'));
329         if ($user) {
330             $action->menuItem(common_local_url('all', array('nickname' => $user->nickname)),
331                             _('Home'));
332             $action->menuItem(common_local_url('profilesettings'),
333                             _('Account'));
334             $action->menuItem(common_local_url('oauthconnectionssettings'),
335                                 _('Connect'));
336             if ($user->hasRight(Right::CONFIGURESITE)) {
337                 $action->menuItem(common_local_url('siteadminpanel'),
338                                 _('Admin'), _('Change site configuration'), false, 'nav_admin');
339             }
340             if (common_config('invite', 'enabled')) {
341                 $action->menuItem(common_local_url('invite'),
342                                 _('Invite'));
343             }
344             $action->menuItem(common_local_url('logout'),
345                             _('Logout'));
346         } else {
347             if (!common_config('site', 'closed')) {
348                 $action->menuItem(common_local_url('register'),
349                                 _('Register'));
350             }
351             $action->menuItem(common_local_url('login'),
352                             _('Login'));
353         }
354         if ($user || !common_config('site', 'private')) {
355             $action->menuItem(common_local_url('peoplesearch'),
356                             _('Search'));
357         }
358         $action->elementEnd('ul');
359     }
360
361
362     function onStartShowNoticeFormData($form)
363     {
364         if (!$this->serveMobile) {
365             return true;
366         }
367
368         $form->out->element('textarea', array('id' => 'notice_data-text',
369                                               'cols' => 15,
370                                               'rows' => 4,
371                                               'name' => 'status_textarea'),
372                             ($form->content) ? $form->content : '');
373
374         $contentLimit = Notice::maxContent();
375
376         if ($contentLimit > 0) {
377             $form->out->element('div', array('id' => 'notice_text-count'),
378                                 $contentLimit);
379         }
380
381         if (common_config('attachments', 'uploads')) {
382             if ($this->mobileFeatures['inputfiletype']) {
383                 $form->out->element('label', array('for' => 'notice_data-attach'), _('Attach'));
384                 $form->out->element('input', array('id' => 'notice_data-attach',
385                                                    'type' => 'file',
386                                                    'name' => 'attach',
387                                                    'title' => _('Attach a file')));
388                 $form->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota'));
389             }
390         }
391         if ($form->action) {
392             $form->out->hidden('notice_return-to', $form->action, 'returnto');
393         }
394         $form->out->hidden('notice_in-reply-to', $form->inreplyto, 'inreplyto');
395
396         return false;
397     }
398
399
400     function onStartShowAside($action)
401     {
402         if ($this->serveMobile) {
403             return false;
404         }
405     }
406
407
408     function onStartShowScripts($action)
409     {
410
411     }
412
413
414     function _common_path($relative, $ssl=false)
415     {
416         $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : '';
417
418         if (($ssl && (common_config('site', 'ssl') === 'sometimes'))
419             || common_config('site', 'ssl') === 'always') {
420             $proto = 'https';
421             if (is_string(common_config('site', 'sslserver')) &&
422                 mb_strlen(common_config('site', 'sslserver')) > 0) {
423                 $serverpart = common_config('site', 'sslserver');
424             } else {
425                 $serverpart = common_config('site', 'mobileserver');
426             }
427         } else {
428             $proto      = 'http';
429             $serverpart = common_config('site', 'mobileserver');
430         }
431
432         return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
433     }
434
435     function onPluginVersion(&$versions)
436     {
437         $versions[] = array('name' => 'MobileProfile',
438                             'version' => STATUSNET_VERSION,
439                             'author' => 'Sarven Capadisli',
440                             'homepage' => 'http://status.net/wiki/Plugin:MobileProfile',
441                             'rawdescription' =>
442                             _m('XHTML MobileProfile output for supporting user agents.'));
443         return true;
444     }
445 }