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