]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/MobileProfile/MobileProfilePlugin.php
Merge branch 'testing' into 0.9.x
[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 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         $action->elementStart('ul', array('id' => 'site_nav_global_primary'));
311         if ($user) {
312             $action->menuItem(common_local_url('all', array('nickname' => $user->nickname)),
313                             _('Home'));
314             $action->menuItem(common_local_url('profilesettings'),
315                             _('Account'));
316             $action->menuItem(common_local_url('oauthconnectionssettings'),
317                                 _('Connect'));
318             if ($user->hasRight(Right::CONFIGURESITE)) {
319                 $action->menuItem(common_local_url('siteadminpanel'),
320                                 _('Admin'), _('Change site configuration'), false, 'nav_admin');
321             }
322             if (common_config('invite', 'enabled')) {
323                 $action->menuItem(common_local_url('invite'),
324                                 _('Invite'));
325             }
326             $action->menuItem(common_local_url('logout'),
327                             _('Logout'));
328         } else {
329             if (!common_config('site', 'closed')) {
330                 $action->menuItem(common_local_url('register'),
331                                 _('Register'));
332             }
333             $action->menuItem(common_local_url('login'),
334                             _('Login'));
335         }
336         if ($user || !common_config('site', 'private')) {
337             $action->menuItem(common_local_url('peoplesearch'),
338                             _('Search'));
339         }
340         $action->elementEnd('ul');
341     }
342
343
344     function onStartShowNoticeFormData($form)
345     {
346         if (!$this->serveMobile) {
347             return true;
348         }
349
350         $form->out->element('textarea', array('id' => 'notice_data-text',
351                                               'cols' => 15,
352                                               'rows' => 4,
353                                               'name' => 'status_textarea'),
354                             ($form->content) ? $form->content : '');
355
356         $contentLimit = Notice::maxContent();
357
358         if ($contentLimit > 0) {
359             $form->out->element('div', array('id' => 'notice_text-count'),
360                                 $contentLimit);
361         }
362
363         if (common_config('attachments', 'uploads')) {
364             if ($this->mobileFeatures['inputfiletype']) {
365                 $form->out->element('label', array('for' => 'notice_data-attach'), _('Attach'));
366                 $form->out->element('input', array('id' => 'notice_data-attach',
367                                                    'type' => 'file',
368                                                    'name' => 'attach',
369                                                    'title' => _('Attach a file')));
370                 $form->out->hidden('MAX_FILE_SIZE', common_config('attachments', 'file_quota'));
371             }
372         }
373         if ($form->action) {
374             $form->out->hidden('notice_return-to', $form->action, 'returnto');
375         }
376         $form->out->hidden('notice_in-reply-to', $form->inreplyto, 'inreplyto');
377
378         return false;
379     }
380
381
382     function onStartShowAside($action)
383     {
384         if ($this->serveMobile) {
385             return false;
386         }
387     }
388
389
390     function onStartShowScripts($action)
391     {
392
393     }
394
395
396     function _common_path($relative, $ssl=false)
397     {
398         $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : '';
399
400         if (($ssl && (common_config('site', 'ssl') === 'sometimes'))
401             || common_config('site', 'ssl') === 'always') {
402             $proto = 'https';
403             if (is_string(common_config('site', 'sslserver')) &&
404                 mb_strlen(common_config('site', 'sslserver')) > 0) {
405                 $serverpart = common_config('site', 'sslserver');
406             } else {
407                 $serverpart = common_config('site', 'mobileserver');
408             }
409         } else {
410             $proto      = 'http';
411             $serverpart = common_config('site', 'mobileserver');
412         }
413
414         return $proto.'://'.$serverpart.'/'.$pathpart.$relative;
415     }
416
417     function onPluginVersion(&$versions)
418     {
419         $versions[] = array('name' => 'MobileProfile',
420                             'version' => STATUSNET_VERSION,
421                             'author' => 'Sarven Capadisli',
422                             'homepage' => 'http://status.net/wiki/Plugin:MobileProfile',
423                             'rawdescription' =>
424                             _m('XHTML MobileProfile output for supporting user agents.'));
425         return true;
426     }
427 }