]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/MobileProfile/MobileProfilePlugin.php
Merge branch 'testing' of gitorious.org:statusnet/mainline
[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         if (file_exists(Theme::file('css/mp-screen.css'))) {
244             $action->cssLink('css/mp-screen.css', null, 'screen');
245         } else {
246             $action->cssLink('plugins/MobileProfile/mp-screen.css',null,'screen');
247         }
248
249         if (file_exists(Theme::file('css/mp-handheld.css'))) {
250             $action->cssLink('css/mp-handheld.css', null, 'handheld');
251         } else {
252             $action->cssLink('plugins/MobileProfile/mp-handheld.css',null,'handheld');
253         }
254
255         return false;
256     }
257
258
259     function onStartShowHeader($action)
260     {
261         if (!$this->serveMobile) {
262             return true;
263         }
264
265         $action->elementStart('div', array('id' => 'header'));
266         $this->_showLogo($action);
267         $this->_showPrimaryNav($action);
268         if (common_logged_in()) {
269             $action->showNoticeForm();
270         }
271         $action->elementEnd('div');
272
273         return false;
274     }
275
276
277     function _showLogo($action)
278     {
279         $action->elementStart('address', 'vcard');
280         $action->elementStart('a', array('class' => 'url home bookmark',
281                                        'href' => common_local_url('public')));
282         if (common_config('site', 'mobilelogo') || 
283             file_exists(Theme::file('logo.png')) || 
284             file_exists(Theme::file('mobilelogo.png'))) {
285
286             $action->element('img', array('class' => 'photo',
287                 'src' => (common_config('site', 'mobilelogo')) ? common_config('site', 'mobilelogo') : 
288                             ((file_exists(Theme::file('mobilelogo.png'))) ? (Theme::path('mobilelogo.png')) : Theme::path('logo.png')),
289                 'alt' => common_config('site', 'name')));
290         }
291         $action->element('span', array('class' => 'fn org'), common_config('site', 'name'));
292         $action->elementEnd('a');
293         $action->elementEnd('address');
294     }
295
296
297     function _showPrimaryNav($action)
298     {
299         $user    = common_current_user();
300         $connect = '';
301         if (common_config('xmpp', 'enabled')) {
302             $connect = 'imsettings';
303         } else if (common_config('sms', 'enabled')) {
304             $connect = 'smssettings';
305         } else if (common_config('twitter', 'enabled')) {
306             $connect = 'twittersettings';
307         }
308
309         $action->elementStart('ul', array('id' => 'site_nav_global_primary'));
310         if ($user) {
311             $action->menuItem(common_local_url('all', array('nickname' => $user->nickname)),
312                             _('Home'));
313             $action->menuItem(common_local_url('profilesettings'),
314                             _('Account'));
315             if ($connect) {
316                 $action->menuItem(common_local_url($connect),
317                                 _('Connect'));
318             }
319             if ($user->hasRight(Right::CONFIGURESITE)) {
320                 $action->menuItem(common_local_url('siteadminpanel'),
321                                 _('Admin'), _('Change site configuration'), false, 'nav_admin');
322             }
323             if (common_config('invite', 'enabled')) {
324                 $action->menuItem(common_local_url('invite'),
325                                 _('Invite'));
326             }
327             $action->menuItem(common_local_url('logout'),
328                             _('Logout'));
329         } else {
330             if (!common_config('site', 'closed')) {
331                 $action->menuItem(common_local_url('register'),
332                                 _('Register'));
333             }
334             $action->menuItem(common_local_url('login'),
335                             _('Login'));
336         }
337         if ($user || !common_config('site', 'private')) {
338             $action->menuItem(common_local_url('peoplesearch'),
339                             _('Search'));
340         }
341         $action->elementEnd('ul');
342     }
343
344
345     function onStartShowNoticeFormData($form)
346     {
347         if (!$this->serveMobile) {
348             return true;
349         }
350
351         $form->out->element('textarea', array('id' => 'notice_data-text',
352                                               'cols' => 15,
353                                               'rows' => 4,
354                                               'name' => 'status_textarea'),
355                             ($form->content) ? $form->content : '');
356
357         $contentLimit = Notice::maxContent();
358
359         if ($contentLimit > 0) {
360             $form->out->element('div', array('id' => 'notice_text-count'),
361                                 $contentLimit);
362         }
363
364         if (common_config('attachments', 'uploads')) {
365             if ($this->mobileFeatures['inputfiletype']) {
366                 $form->out->element('label', array('for' => 'notice_data-attach'), _('Attach'));
367                 $form->out->element('input', array('id' => 'notice_data-attach',
368                                                    'type' => 'file',
369                                                    'name' => 'attach',
370                                                    'title' => _('Attach a file')));
371                 $form->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota'));
372             }
373         }
374         if ($form->action) {
375             $form->out->hidden('notice_return-to', $form->action, 'returnto');
376         }
377         $form->out->hidden('notice_in-reply-to', $form->inreplyto, 'inreplyto');
378
379         return false;
380     }
381
382
383     function onStartShowAside($action)
384     {
385         if ($this->serveMobile) {
386             return false;
387         }
388     }
389
390
391     function onStartShowScripts($action)
392     {
393
394     }
395
396
397     function _common_path($relative, $ssl=false)
398     {
399         $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : '';
400
401         if (($ssl && (common_config('site', 'ssl') === 'sometimes'))
402             || common_config('site', 'ssl') === 'always') {
403             $proto = 'https';
404             if (is_string(common_config('site', 'sslserver')) &&
405                 mb_strlen(common_config('site', 'sslserver')) > 0) {
406                 $serverpart = common_config('site', 'sslserver');
407             } else {
408                 $serverpart = common_config('site', 'mobileserver');
409             }
410         } else {
411             $proto      = 'http';
412             $serverpart = common_config('site', 'mobileserver');
413         }
414
415         return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
416     }
417
418     function onPluginVersion(&$versions)
419     {
420         $versions[] = array('name' => 'MobileProfile',
421                             'version' => STATUSNET_VERSION,
422                             'author' => 'Sarven Capadisli',
423                             'homepage' => 'http://status.net/wiki/Plugin:MobileProfile',
424                             'rawdescription' =>
425                             _m('XHTML MobileProfile output for supporting user agents.'));
426         return true;
427     }
428 }