Project

General

Profile

Revision 229

View differences:

trunk/_extplorer.php
1
<?php
2
// ensure this file is being included by a parent file
3
if( !defined( '_JEXEC' ) && !defined( '_VALID_MOS' ) ) die( 'Restricted access' );
4
require_once(dirname(__FILE__).'/'.'admin.extplorer.php');
0 5

  
trunk/libraries/FTP.php
30 30
/**
31 31
 * Include PEAR.php to obtain the PEAR base class
32 32
 */
33
require_once 'PEAR.php';
33
require_once dirname(__FILE__).'/PEAR.php';
34 34

  
35 35
/**
36 36
 * Option to let the ls() method return only files.
trunk/libraries/Mobile_Detect.php
1
<?php
2
/**
3
 * Mobile Detect
4
 * $Id: Mobile_Detect.php 51 2012-08-03 02:16:06Z serbanghita@gmail.com $
5
 *
6
 * @author      Mobile_Detect v.1.0 Victor Stanciu <vic.stanciu@gmail.com>
7
 *              Mobile_Detect v.2.x Serban Ghita <serban.ghita@gmail.com>
8
 * 
9
 * @usage      require_once 'Mobile_Detect.php';
10
 *             $detect = new Mobile_Detect();
11
 *             $detect->isMobile() or $detect->isTablet()
12
 * 
13
 *             For more specific usage see the documentation navigate to:
14
 *             http://code.google.com/p/php-mobile-detect/wiki/Mobile_Detect
15
 * 
16
 * @license    http://www.opensource.org/licenses/mit-license.php The MIT License
17
 */
18

  
19
class Mobile_Detect {
20

  
21
    // External info.
22
    protected $userAgent = null;
23
    protected $httpHeaders;
24

  
25
    // Array holding all detection rules.
26
    protected $mobileDetectionRules;
27

  
28
    // List of mobile devices (phones)
29
    protected $phoneDevices = array(     
30
            'iPhone'        => '(iPhone.*Mobile|iPod|iTunes)',
31
            'BlackBerry'    => 'BlackBerry|rim[0-9]+',
32
            'HTC'           => 'HTC|HTC.*(6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT',
33
            'Nexus'         => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus',
34
            'Dell'          => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35',
35
            'Motorola'      => '\bDroid\b.*Build|DROIDX|HRI39|MOT\-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT909|XT910|XT912|XT928',
36
            'Samsung'       => 'Samsung|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9300 |GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-P6810|GT-P7100|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100',
37
            'Sony'          => 'E10i|SonyEricsson|SonyEricssonLT15iv',
38
            'Asus'          => 'Asus.*Galaxy',
39
            'Palm'          => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex.
40
	        'Vertu'         => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
41
            'GenericPhone'  => '(mmp|pocket|psp|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|wap|nokia|Series40|Series60|S60|SonyEricsson|N900|PPC;|MAUI.*WAP.*Browser|LG-P500)'
42
    );
43
    // List of tablet devices.
44
    protected $tabletDevices = array(
45
        'BlackBerryTablet'  => 'PlayBook|RIM Tablet',
46
        'iPad'              => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
47
        'Kindle'            => 'Kindle|Silk.*Accelerated',
48
        'SamsungTablet'     => 'SAMSUNG.*Tablet|Galaxy.*Tab|GT-P1000|GT-P1010|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P1000|GT-P3100|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7300|GT-P7320|GT-P7500|GT-P7510|GT-P7511',
49
        'HTCtablet'         => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
50
	    'MotorolaTablet'    => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
51
        'AsusTablet'        => 'Transformer|TF101',
52
        'NookTablet'        => 'NookColor|nook browser|BNTV250A|LogicPD Zoom2',
53
        'AcerTablet'        => 'Android.*\b(A100|A101|A200|A500|A501|A510|W500|W500P|W501|W501P)\b',
54
	    'YarvikTablet'      => 'Android.*(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468)',
55
        'MedionTablet'      => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
56
        'ArnovaTablet'      => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT',
57
        'GenericTablet'     => 'Tablet(?!.*PC)|ViewPad7|LG-V909|MID7015|BNTV250A|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b',
58
    );
59
    // List of mobile Operating Systems.
60
    protected $operatingSystems = array(
61
        'AndroidOS'         => '(android.*mobile|android(?!.*mobile))',
62
        'BlackBerryOS'      => '(blackberry|rim tablet os)',
63
        'PalmOS'            => '(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)',
64
        'SymbianOS'         => 'Symbian|SymbOS|Series60|Series40|\bS60\b',
65
        'WindowsMobileOS'   => 'IEMobile|Windows Phone|Windows CE.*(PPC|Smartphone)|MSIEMobile|Window Mobile|XBLWP7',
66
        'iOS'               => '(iphone|ipod|ipad)',
67
        'FlashLiteOS'       => '',
68
        'JavaOS'            => '',
69
        'NokiaOS'           => '',
70
        'webOS'             => '',
71
        'badaOS'            => '\bBada\b',
72
        'BREWOS'            => '',
73
    );
74
    // List of mobile User Agents.
75
    protected $userAgents = array(
76
      'Chrome'          => '\bCrMo\b|Chrome\/[.0-9]* Mobile',
77
      'Dolfin'          => '\bDolfin\b',
78
      'Opera'           => 'Opera.*Mini|Opera.*Mobi|Android.*Opera',
79
      'Skyfire'         => 'skyfire',
80
      'IE'              => 'IEMobile|MSIEMobile',
81
      'Firefox'         => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
82
      'Bolt'            => 'bolt',
83
      'TeaShark'        => 'teashark',
84
      'Blazer'          => 'Blazer',
85
      'Safari'          => 'Mobile.*Safari|Safari.*Mobile',
86
      'Midori'          => 'midori',
87
      'GenericBrowser'  => 'NokiaBrowser|OviBrowser|SEMC.*Browser'
88
    );
89
    // Utilities.
90
    protected $utilities = array(
91
        'WebKit'        => '(webkit)[ \/]([\w.]+)',
92
        'Bot'           => 'Googlebot|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
93
        'MobileBot'     => 'Googlebot-Mobile|YahooSeeker\/M1A1-R2D2',
94
    );
95
    
96
    function __construct(){
97

  
98
        $this->setHttpHeaders();
99
        $this->setUserAgent();
100

  
101
        $this->setMobileDetectionRules();
102

  
103
    }
104

  
105
    public function setHttpHeaders($httpHeaders = null){
106

  
107
        if(!empty($httpHeaders)){
108
            $this->httpHeaders = $httpHeaders;
109
        } else {
110
            foreach($_SERVER as $key => $value){
111
                if(substr($key,0,5)=='HTTP_'){
112
                    $this->httpHeaders[$key] = $value;
113
                }
114
            }
115
        }
116

  
117
    }
118

  
119
    public function setUserAgent($userAgent = null){
120

  
121
        if(!empty($userAgent)){
122
            $this->userAgent = $userAgent;
123
        } else {
124
            $this->userAgent    = isset($this->httpHeaders['HTTP_USER_AGENT']) ? $this->httpHeaders['HTTP_USER_AGENT'] : null;
125

  
126
            if(empty($this->userAgent)){
127
                $this->userAgent = isset($this->httpHeaders['HTTP_X_DEVICE_USER_AGENT']) ? $this->httpHeaders['HTTP_X_DEVICE_USER_AGENT'] : null;
128
            }
129
        }
130

  
131
    }
132

  
133
    /**
134
     * Method sets the mobile detection rules.
135
     *
136
     * This method is used for the magic methods $detect->is*()
137
     */
138
    public function setMobileDetectionRules(){
139
        // Merge all rules together.
140
        $this->mobileDetectionRules = array_merge(
141
            $this->phoneDevices,
142
            $this->tabletDevices,
143
            $this->operatingSystems,
144
            $this->userAgents
145
        );
146

  
147
    }
148

  
149
    /**
150
     * Method sets the mobile detection rules + utilities.
151
     * The reason this is separate is because utilities rules
152
     * don't necessary imply mobile.
153
     *
154
     * This method is used inside the new $detect->is('stuff') method.
155
     *
156
     * @return bool
157
     */
158
    public function setMobileDetectionRulesExtended(){
159

  
160

  
161
        // Merge all rules together.
162
        $this->mobileDetectionRules = array_merge(
163
            $this->phoneDevices,
164
            $this->tabletDevices,
165
            $this->operatingSystems,
166
            $this->userAgents,
167
            $this->utilities
168
        );
169

  
170
    }
171

  
172
    public function checkHttpHeadersForMobile(){
173

  
174
        if(
175
            isset($this->httpHeaders['HTTP_X_WAP_PROFILE'])             ||
176
            isset($this->httpHeaders['HTTP_X_WAP_CLIENTID'])            ||
177
            isset($this->httpHeaders['HTTP_WAP_CONNECTION'])            ||
178
            isset($this->httpHeaders['HTTP_PROFILE'])                   ||
179
            isset($this->httpHeaders['HTTP_X_OPERAMINI_PHONE_UA'])      || // Reported by Nokia devices (eg. C3)
180
            isset($this->httpHeaders['HTTP_X_NOKIA_IPADDRESS'])         ||
181
            isset($this->httpHeaders['HTTP_X_NOKIA_GATEWAY_ID'])        ||
182
            isset($this->httpHeaders['HTTP_X_ORANGE_ID'])               ||
183
            isset($this->httpHeaders['HTTP_X_VODAFONE_3GPDPCONTEXT'])   ||
184
            isset($this->httpHeaders['HTTP_X_HUAWEI_USERID'])           ||
185
            isset($this->httpHeaders['HTTP_UA_OS'])                     || // Reported by Windows Smartphones.
186
            isset($this->httpHeaders['HTTP_X_MOBILE_GATEWAY'])          || // Reported by Verizon, Vodafone proxy system.
187
            ( isset($this->httpHeaders['HTTP_UA_CPU']) &&
188
                    $this->httpHeaders['HTTP_UA_CPU'] == 'ARM'
189
            )                                                           || // Seen this on a HTC.
190
            isset($this->httpHeaders['HTTP_ACCEPT']) &&
191
                (strpos($this->httpHeaders['HTTP_ACCEPT'], 'text/vnd.wap.wml') !== false ||
192
                 strpos($this->httpHeaders['HTTP_ACCEPT'], 'application/vnd.wap.xhtml+xml') !== false)
193
        ){
194

  
195
            return true;
196

  
197
        }
198

  
199
        return false;
200

  
201
    }
202

  
203
    /**
204
     * @return array
205
     */
206
    public function getRules()
207
    {
208
        return $this->mobileDetectionRules;
209
    }
210
    
211
    /**
212
     * Magic overloading method.
213
     * 
214
     * @method boolean is[...]()
215
     * @param string $name
216
     * @param array $arguments
217
     * @return mixed 
218
     */
219
    public function __call($name, $arguments)
220
    {
221
                
222
        $key = substr($name, 2);
223
        return $this->matchUAAgainstKey($key);
224

  
225
    }
226

  
227
    private function matchDetectionRulesAgainstUA($userAgent = null){
228

  
229
        // Begin general search.
230
        foreach($this->getRules() as $_regex){
231
            if(empty($_regex)){ continue; }
232
            if( preg_match('/'.$_regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent)) ){
233
                return true;
234
            }
235
        }
236

  
237
        return false;
238

  
239
    }
240

  
241
    // Search for a certain key.
242
    private function matchUAAgainstKey($key, $userAgent = null){
243

  
244
        // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
245
        $key = strtolower($key);
246
        $_rules = array_change_key_case($this->getRules());
247

  
248
        if(array_key_exists($key, $_rules)){
249
            if(empty($_rules[$key])){ return null; }
250
            return (bool)preg_match('/'.$_rules[$key].'/is', (!empty($userAgent) ? $userAgent : $this->userAgent));
251
        }
252

  
253
        return false;
254

  
255
    }
256
        
257
    /**
258
    * Check if the device is mobile.
259
    * Returns true if any type of mobile device detected, including special ones
260
    * @return bool
261
    */
262
    public function isMobile($userAgent = null, $httpHeaders = null) {
263

  
264
        if($httpHeaders){ $this->setHttpHeaders($httpHeaders); }
265
        if($userAgent){ $this->setUserAgent($userAgent); }
266

  
267
        $this->setMobileDetectionRules();
268

  
269
        if ($this->checkHttpHeadersForMobile()) {
270
            return true;
271
        } else {
272
            return $this->matchDetectionRulesAgainstUA();
273
        }
274

  
275
    } 
276
    
277
    /**
278
    * Check if the device is a tablet.
279
    * Return true if any type of tablet device is detected.
280
    * @return boolean 
281
    */
282
    public function isTablet($userAgent = null, $httpHeaders = null) {
283

  
284
        foreach($this->tabletDevices as $_regex){
285
            if(preg_match('/'.$_regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent))){
286
                return true;
287
            }
288
        }
289

  
290
	    return false;
291

  
292
    }
293

  
294
    /**
295
     * This method checks for a certain property in the
296
     * userAgent.
297
     * @todo: The httpHeaders part is not yet used.
298
     *
299
     * @param $key
300
     * @param string $userAgent
301
     * @param string $httpHeaders
302
     * @return bool|int|null
303
     */
304
    public function is($key, $userAgent = null, $httpHeaders = null){
305

  
306
        $this->setHttpHeaders($httpHeaders);
307
        $this->setUserAgent($userAgent);
308

  
309
        $this->setMobileDetectionRulesExtended();
310

  
311
        return $this->matchUAAgainstKey($key);
312

  
313
    }
314
    
315
    
316
}
0 317

  
trunk/extplorer.xml
1
<?xml version="1.0" encoding="iso-8859-1" ?>
2
<mosinstall type="component">
3
<!-- Joomla! 1.0 Installer XML File 
1
<?xml version="1.0" encoding="utf-8"?>
2
<extension type="component" version="3.0" method="upgrade">
3
<!-- Joomla! 3.0 Installer XML File 
4 4
$Id: extplorer.php 164 2010-05-03 15:06:51Z soeren $ -->
5 5
    <name>eXtplorer</name>
6 6
    <creationDate>29.02.2012</creationDate>
......
42 42
						  UNIQUE KEY token (token),
43 43
						  KEY path (path),
44 44
						  KEY expires (expires)
45
						) TYPE=MyISAM
45
						) ENGINE=MyISAM
46 46
			</query>
47 47
			<query>CREATE TABLE IF NOT EXISTS `#__extwebdav_properties` (
48 48
						  path varchar(255) NOT NULL default '',
......
51 51
						  value text,
52 52
						  PRIMARY KEY ( `ns` ( 100 ) , `path` ( 100 ) , `name` ( 50 ) ),
53 53
						  KEY path (path)
54
						) TYPE=MyISAM
54
						) ENGINE=MyISAM
55 55
			</query>
56 56

  
57 57
	</queries>
......
353 353
			<filename>libraries/MIME/Parameter.php</filename>
354 354
			<filename>libraries/MIME/Type.php</filename>
355 355
			<filename>libraries/MIME/index.html</filename>
356
			<filename>libraries/Mobile_Detect.php</filename>			
356 357
			<filename>libraries/PEAR.php</filename>
357 358
			<filename>libraries/PasswordHash.php</filename>
358 359
			<filename>libraries/SSH2.php</filename>
......
511 512
			<filename>webdav_table.sql.php</filename>
512 513
		</files>
513 514
    </administration>
514
</mosinstall>
515
</extension>
trunk/scripts/codemirror/mode/markdown/index.html
6 6
    <script src="../../lib/codemirror.js"></script>
7 7
    <script src="../xml/xml.js"></script>
8 8
    <script src="markdown.js"></script>
9
    <link rel="stylesheet" href="markdown.css">
10 9
    <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
11 10
    <link rel="stylesheet" href="../../doc/docs.css">
12 11
  </head>
trunk/scripts/codemirror/mode/markdown/markdown.js
13 13
  ,   strong   = 'strong'
14 14
  ,   emstrong = 'emstrong';
15 15

  
16
  var hrRE = /^[*-=_]/
17
  ,   ulRE = /^[*-+]\s+/
18
  ,   olRE = /^[0-9]\.\s+/
16
  var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
17
  ,   ulRE = /^[*\-+]\s+/
18
  ,   olRE = /^[0-9]+\.\s+/
19 19
  ,   headerRE = /^(?:\={3,}|-{3,})$/
20
  ,   codeRE = /^(k:\t|\s{4,})/
21 20
  ,   textRE = /^[^\[*_\\<>`]+/;
22 21

  
23 22
  function switchInline(stream, state, f) {
......
33 32

  
34 33
  // Blocks
35 34

  
35
  function blankLine(state) {
36
    // Reset EM state
37
    state.em = false;
38
    // Reset STRONG state
39
    state.strong = false;
40
    return null;
41
  }
42

  
36 43
  function blockNormal(stream, state) {
37
    if (stream.match(codeRE)) {
44
    var match;
45
    if (state.indentationDiff >= 4) {
46
      state.indentation -= state.indentationDiff;
38 47
      stream.skipToEnd();
39 48
      return code;
40
    }
41
    
42
    if (stream.eatSpace()) {
49
    } else if (stream.eatSpace()) {
43 50
      return null;
44
    }
45
    
46
    if (stream.peek() === '#' || stream.match(headerRE)) {
47
      stream.skipToEnd();
48
      return header;
49
    }
50
    if (stream.eat('>')) {
51
    } else if (stream.peek() === '#' || stream.match(headerRE)) {
52
      state.header = true;
53
    } else if (stream.eat('>')) {
51 54
      state.indentation++;
52
      return quote;
53
    }
54
    if (stream.peek() === '[') {
55
      state.quote = true;
56
    } else if (stream.peek() === '[') {
55 57
      return switchInline(stream, state, footnoteLink);
56
    }
57
    if (hrRE.test(stream.peek())) {
58
      var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$');
59
      if (stream.match(re, true)) {
60
        return hr;
61
      }
62
    }
63
    
64
    var match;
65
    if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
58
    } else if (stream.match(hrRE, true)) {
59
      return hr;
60
    } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {
66 61
      state.indentation += match[0].length;
67 62
      return list;
68 63
    }
......
82 77

  
83 78
  // Inline
84 79
  function getType(state) {
85
    return state.strong ? (state.em ? emstrong : strong)
86
                        : (state.em ? em       : null);
80
    var styles = [];
81
    
82
    if (state.strong) { styles.push(state.em ? emstrong : strong); }
83
    else if (state.em) { styles.push(em); }
84
    
85
    if (state.header) { styles.push(header); }
86
    if (state.quote) { styles.push(quote); }
87

  
88
    return styles.length ? styles.join(' ') : null;
87 89
  }
88 90

  
89 91
  function handleText(stream, state) {
......
192 194
        inline: inlineNormal,
193 195
        text: handleText,
194 196
        em: false,
195
        strong: false
197
        strong: false,
198
        header: false,
199
        quote: false
196 200
      };
197 201
    },
198 202

  
......
207 211
        inline: s.inline,
208 212
        text: s.text,
209 213
        em: s.em,
210
        strong: s.strong
214
        strong: s.strong,
215
        header: s.header,
216
        quote: s.quote
211 217
      };
212 218
    },
213 219

  
214 220
    token: function(stream, state) {
215 221
      if (stream.sol()) {
222
        if (stream.match(/^\s*$/, true)) { return blankLine(state); }
223

  
224
        // Reset state.header
225
        state.header = false;
226
        // Reset state.quote
227
        state.quote = false;
228

  
216 229
        state.f = state.block;
217
        var previousIndentation = state.indentation
218
        ,   currentIndentation = 0;
219
        while (previousIndentation > 0) {
220
          if (stream.eat(' ')) {
221
            previousIndentation--;
222
            currentIndentation++;
223
          } else if (previousIndentation >= 4 && stream.eat('\t')) {
224
            previousIndentation -= 4;
225
            currentIndentation += 4;
226
          } else {
227
            break;
228
          }
229
        }
230
        state.indentation = currentIndentation;
231
        
232
        if (currentIndentation > 0) return null;
230
        var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, '    ').length;
231
        state.indentationDiff = indentation - state.indentation;
232
        state.indentation = indentation;
233
        if (indentation > 0) { return null; }
233 234
      }
234 235
      return state.f(stream, state);
235 236
    },
236 237

  
238
    blankLine: blankLine,
239

  
237 240
    getType: getType
238 241
  };
239 242

  
240
});
243
}, "xml");
241 244

  
242 245
CodeMirror.defineMIME("text/x-markdown", "markdown");
trunk/scripts/codemirror/mode/php/php.js
13 13
  }
14 14
  var phpConfig = {
15 15
    name: "clike",
16
    keywords: keywords("abstract and array as break case catch cfunction class clone const continue declare " +
17
                       "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " +
18
                       "final for foreach function global goto if implements interface instanceof namespace " +
19
                       "new or private protected public static switch throw try use var while xor return" +
20
                       "die echo empty exit eval include include_once isset list require require_once print unset"),
16
    keywords: keywords("abstract and array as break case catch class clone const continue declare default " +
17
                       "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
18
                       "for foreach function global goto if implements interface instanceof namespace " +
19
                       "new or private protected public static switch throw trait try use var while xor " +
20
                       "die echo empty exit eval include include_once isset list require require_once return " +
21
                       "print unset __halt_compiler self static parent"),
21 22
    blockKeywords: keywords("catch do else elseif for foreach if switch try while"),
22 23
    atoms: keywords("true false null TRUE FALSE NULL"),
23 24
    multiLineStrings: true,
......
35 36
        return false;
36 37
      },
37 38
      "#": function(stream, state) {
38
        stream.skipToEnd();
39
        while (!stream.eol() && !stream.match("?>", false)) stream.next();
39 40
        return "comment";
41
      },
42
      "/": function(stream, state) {
43
        if (stream.eat("/")) {
44
          while (!stream.eol() && !stream.match("?>", false)) stream.next();
45
          return "comment";
46
        }
47
        return false;
40 48
      }
41 49
    }
42 50
  };
......
48 56
    var phpMode = CodeMirror.getMode(config, phpConfig);
49 57

  
50 58
    function dispatch(stream, state) { // TODO open PHP inside text/css
59
      var isPHP = state.mode == "php";
60
      if (stream.sol() && state.pending != '"') state.pending = null;
51 61
      if (state.curMode == htmlMode) {
52
        var style = htmlMode.token(stream, state.curState);
53
        if (style == "meta" && /^<\?/.test(stream.current())) {
62
        if (stream.match(/^<\?\w*/)) {
54 63
          state.curMode = phpMode;
55 64
          state.curState = state.php;
56
          state.curClose = /^\?>/;
57
		  state.mode =  'php';
65
          state.curClose = "?>";
66
	  state.mode = "php";
67
          return "meta";
58 68
        }
59
        else if (style == "tag" && stream.current() == ">" && state.curState.context) {
69
        if (state.pending == '"') {
70
          while (!stream.eol() && stream.next() != '"') {}
71
          var style = "string";
72
        } else if (state.pending && stream.pos < state.pending.end) {
73
          stream.pos = state.pending.end;
74
          var style = state.pending.style;
75
        } else {
76
          var style = htmlMode.token(stream, state.curState);
77
        }
78
        state.pending = null;
79
        var cur = stream.current(), openPHP = cur.search(/<\?/);
80
        if (openPHP != -1) {
81
          if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
82
          else state.pending = {end: stream.pos, style: style};
83
          stream.backUp(cur.length - openPHP);
84
        } else if (style == "tag" && stream.current() == ">" && state.curState.context) {
60 85
          if (/^script$/i.test(state.curState.context.tagName)) {
61 86
            state.curMode = jsMode;
62 87
            state.curState = jsMode.startState(htmlMode.indent(state.curState, ""));
63 88
            state.curClose = /^<\/\s*script\s*>/i;
64
			state.mode =  'javascript';
89
	    state.mode = "javascript";
65 90
          }
66 91
          else if (/^style$/i.test(state.curState.context.tagName)) {
67 92
            state.curMode = cssMode;
68 93
            state.curState = cssMode.startState(htmlMode.indent(state.curState, ""));
69
            state.curClose =  /^<\/\s*style\s*>/i;
70
            state.mode =  'css';
94
            state.curClose = /^<\/\s*style\s*>/i;
95
            state.mode = "css";
71 96
          }
72 97
        }
73 98
        return style;
74
      }
75
      else if (stream.match(state.curClose, false)) {
99
      } else if ((!isPHP || state.php.tokenize == null) &&
100
                 stream.match(state.curClose, isPHP)) {
76 101
        state.curMode = htmlMode;
77 102
        state.curState = state.html;
78 103
        state.curClose = null;
79
		state.mode =  'html';
80
        return dispatch(stream, state);
104
	state.mode = "html";
105
        if (isPHP) return "meta";
106
        else return dispatch(stream, state);
107
      } else {
108
        return state.curMode.token(stream, state.curState);
81 109
      }
82
      else return state.curMode.token(stream, state.curState);
83 110
    }
84 111

  
85 112
    return {
......
87 114
        var html = htmlMode.startState();
88 115
        return {html: html,
89 116
                php: phpMode.startState(),
90
                curMode:	parserConfig.startOpen ? phpMode : htmlMode,
91
                curState:	parserConfig.startOpen ? phpMode.startState() : html,
92
                curClose:	parserConfig.startOpen ? /^\?>/ : null,
93
				mode:		parserConfig.startOpen ? 'php' : 'html'}
117
                curMode: parserConfig.startOpen ? phpMode : htmlMode,
118
                curState: parserConfig.startOpen ? phpMode.startState() : html,
119
                curClose: parserConfig.startOpen ? /^\?>/ : null,
120
		mode: parserConfig.startOpen ? "php" : "html",
121
                pending: null}
94 122
      },
95 123

  
96 124
      copyState: function(state) {
......
100 128
        else if (state.curState == php) cur = phpNew;
101 129
        else cur = CodeMirror.copyState(state.curMode, state.curState);
102 130
        return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
103
                curClose: state.curClose, mode: state.mode};
131
                curClose: state.curClose, mode: state.mode,
132
                pending: state.pending};
104 133
      },
105 134

  
106 135
      token: dispatch,
......
114 143

  
115 144
      electricChars: "/{}:"
116 145
    }
117
  });
146
  }, "xml", "clike", "javascript", "css");
118 147
  CodeMirror.defineMIME("application/x-httpd-php", "php");
119 148
  CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
120 149
  CodeMirror.defineMIME("text/x-php", phpConfig);
trunk/scripts/codemirror/mode/htmlmixed/htmlmixed.js
28 28
  function javascript(stream, state) {
29 29
    if (stream.match(/^<\/\s*script\s*>/i, false)) {
30 30
      state.token = html;
31
      state.curState = null;
31
      state.localState = null;
32 32
      state.mode = "html";
33 33
      return html(stream, state);
34 34
    }
......
73 73
    },
74 74

  
75 75
    compareStates: function(a, b) {
76
      if (a.mode != b.mode) return false;
77
      if (a.localState) return CodeMirror.Pass;
76 78
      return htmlMode.compareStates(a.htmlState, b.htmlState);
77 79
    },
78 80

  
79 81
    electricChars: "/{}:"
80 82
  }
81
});
83
}, "xml", "javascript", "css");
82 84

  
83 85
CodeMirror.defineMIME("text/html", "htmlmixed");
trunk/scripts/codemirror/mode/rpm/spec/spec.js
14 14
        return {
15 15
          controlFlow: false,
16 16
          macroParameters: false,
17
          section: false,
17
          section: false
18 18
        };
19 19
    },
20 20
    token: function (stream, state) {
trunk/scripts/codemirror/mode/perl/perl.js
324 324
		hex				:1,	// - convert a string to a hexadecimal number
325 325
		'import'			:1,	// - patch a module's namespace into your own
326 326
		index				:1,	// - find a substring within a string
327
		int				:1,	// - get the integer portion of a number
327
		'int'				:1,	// - get the integer portion of a number
328 328
		ioctl				:1,	// - system-dependent device control system call
329 329
		'join'				:1,	// - join a list into a string using a separator
330 330
		keys				:1,	// - retrieve list of indices from a hash
trunk/scripts/codemirror/mode/pascal/pascal.js
7 7
  var keywords = words("and array begin case const div do downto else end file for forward integer " +
8 8
                       "boolean char function goto if in label mod nil not of or packed procedure " +
9 9
                       "program record repeat set string then to type until var while with");
10
  var blockKeywords = words("case do else for if switch while struct then of");
11 10
  var atoms = {"null": true};
12 11

  
13 12
  var isOperatorChar = /[+\-*&%=<>!?|\/]/;
14
  var curPunc;
15 13

  
16 14
  function tokenBase(stream, state) {
17 15
    var ch = stream.next();
......
28 26
      return tokenComment(stream, state);
29 27
    }
30 28
    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
31
      curPunc = ch;
32 29
      return null
33 30
    }
34 31
    if (/\d/.test(ch)) {
......
47 44
    }
48 45
    stream.eatWhile(/[\w\$_]/);
49 46
    var cur = stream.current();
50
    if (keywords.propertyIsEnumerable(cur)) {
51
      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
52
      return "keyword";
53
    }
47
    if (keywords.propertyIsEnumerable(cur)) return "keyword";
54 48
    if (atoms.propertyIsEnumerable(cur)) return "atom";
55 49
    return "word";
56 50
  }
......
79 73
    return "comment";
80 74
  }
81 75

  
82
  function Context(indented, column, type, align, prev) {
83
    this.indented = indented;
84
    this.column = column;
85
    this.type = type;
86
    this.align = align;
87
    this.prev = prev;
88
  }
89
  function pushContext(state, col, type) {
90
    return state.context = new Context(state.indented, col, type, null, state.context);
91
  }
92
  function popContext(state) {
93
    var t = state.context.type;
94
    if (t == ")" || t == "]" )
95
      state.indented = state.context.indented;
96
    return state.context = state.context.prev;
97
  }
98

  
99 76
  // Interface
100 77

  
101 78
  return {
102 79
    startState: function(basecolumn) {
103
      return {
104
        tokenize: null,
105
        context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
106
        indented: 0,
107
        startOfLine: true
108
      };
80
      return {tokenize: null};
109 81
    },
110 82

  
111 83
    token: function(stream, state) {
112
      var ctx = state.context;
113
      if (stream.sol()) {
114
        if (ctx.align == null) ctx.align = false;
115
        state.indented = stream.indentation();
116
        state.startOfLine = true;
117
      }
118 84
      if (stream.eatSpace()) return null;
119
      curPunc = null;
120 85
      var style = (state.tokenize || tokenBase)(stream, state);
121 86
      if (style == "comment" || style == "meta") return style;
122
      if (ctx.align == null) ctx.align = true;
123

  
124
      if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
125
      else if (curPunc == "[") pushContext(state, stream.column(), "]");
126
      else if (curPunc == "(") pushContext(state, stream.column(), ")");
127
      else if (curPunc == ctx.type) popContext(state);
128
      else if ( ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
129
        pushContext(state, stream.column(), "statement");
130
      state.startOfLine = false;
131 87
      return style;
132 88
    },
133 89

  
trunk/scripts/codemirror/mode/go/go.js
4 4
  var keywords = {
5 5
    "break":true, "case":true, "chan":true, "const":true, "continue":true,
6 6
    "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
7
    "func":true, "go":true, "goto":true, "if":true, "import":true, "interface":true,
8
    "map":true, "package":true, "range":true, "return":true, "select":true,
9
    "struct":true, "switch":true, "type":true, "var":true, "bool":true, "byte":true,
10
    "complex64":true, "complex128":true, "float32":true, "float64":true,
11
    "int8":true, "int16":true, "int32":true, "int64":true, "string":true,
12
    "uint8":true, "uint16":true, "uint32":true, "uint64":true, "int":true,
13
    "uint":true, "uintptr":true
7
    "func":true, "go":true, "goto":true, "if":true, "import":true,
8
    "interface":true, "map":true, "package":true, "range":true, "return":true,
9
    "select":true, "struct":true, "switch":true, "type":true, "var":true,
10
    "bool":true, "byte":true, "complex64":true, "complex128":true,
11
    "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
12
    "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
13
    "uint64":true, "int":true, "uint":true, "uintptr":true
14 14
  };
15 15

  
16 16
  var atoms = {
17 17
    "true":true, "false":true, "iota":true, "nil":true, "append":true,
18
    "cap":true, "close":true, "complex":true, "copy":true, "imag":true, "len":true,
19
    "make":true, "new":true, "panic":true, "print":true, "println":true,
20
    "real":true, "recover":true
18
    "cap":true, "close":true, "complex":true, "copy":true, "imag":true,
19
    "len":true, "make":true, "new":true, "panic":true, "print":true,
20
    "println":true, "real":true, "recover":true
21 21
  };
22 22

  
23 23
  var blockKeywords = {
......
66 66
    stream.eatWhile(/[\w\$_]/);
67 67
    var cur = stream.current();
68 68
    if (keywords.propertyIsEnumerable(cur)) {
69
      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
69
      if (cur == "case" || cur == "default") curPunc = "case";
70 70
      return "keyword";
71 71
    }
72 72
    if (atoms.propertyIsEnumerable(cur)) return "atom";
......
133 133
        if (ctx.align == null) ctx.align = false;
134 134
        state.indented = stream.indentation();
135 135
        state.startOfLine = true;
136
        if (ctx.type == "case") ctx.type = "}";
136 137
      }
137 138
      if (stream.eatSpace()) return null;
138 139
      curPunc = null;
......
143 144
      if (curPunc == "{") pushContext(state, stream.column(), "}");
144 145
      else if (curPunc == "[") pushContext(state, stream.column(), "]");
145 146
      else if (curPunc == "(") pushContext(state, stream.column(), ")");
146
      else if (curPunc == "}") {
147
        while (ctx.type == "statement") ctx = popContext(state);
148
        if (ctx.type == "}") ctx = popContext(state);
149
        while (ctx.type == "statement") ctx = popContext(state);
150
      }
147
      else if (curPunc == "case") ctx.type = "case"
148
      else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state);
151 149
      else if (curPunc == ctx.type) popContext(state);
152
      else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
153
        pushContext(state, stream.column(), "statement");
154 150
      state.startOfLine = false;
155 151
      return style;
156 152
    },
......
158 154
    indent: function(state, textAfter) {
159 155
      if (state.tokenize != tokenBase && state.tokenize != null) return 0;
160 156
      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
161
      if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
157
      if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
158
        state.context.type = "}";
159
        return ctx.indented;
160
      }
162 161
      var closing = firstChar == ctx.type;
163
      if (ctx.type == "statement") return ctx.indented;
164
      else if (ctx.align) return ctx.column + (closing ? 0 : 1);
162
      if (ctx.align) return ctx.column + (closing ? 0 : 1);
165 163
      else return ctx.indented + (closing ? 0 : indentUnit);
166 164
    },
167 165

  
168
    electricChars: "{}"
166
    electricChars: "{}:"
169 167
  };
170 168
});
171 169

  
trunk/scripts/codemirror/mode/tiddlywiki/tiddlywiki.css
11 11
.cm-s-default span.cm-link-external {color: blue;}
12 12
.cm-s-default span.cm-brace {color: #170; font-weight: bold;}
13 13
.cm-s-default span.cm-macro {color: #9E3825;}
14
.cm-s-default span.cm-table {color: blue;}
14
.cm-s-default span.cm-table {color: blue; font-weight: bold;}
15 15
.cm-s-default span.cm-warning {color: red; font-weight: bold;}
16 16

  
17 17
.cm-s-default span.cm-underlined {text-decoration: underline;}
trunk/scripts/codemirror/mode/tiddlywiki/tiddlywiki.js
1 1
/***
2
 |''Name''|tiddlywiki.js|
3
 |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror2|
4
 |''Author''|PMario|
5
 |''Version''|0.1.6|
6
 |''Status''|''beta''|
7
 |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
8
 |''Documentation''|http://codemirror.tiddlyspace.com/|
9
 |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
10
 |''CoreVersion''|2.5.0|
11
 |''Requires''|codemirror.js|
12
 |''Keywords''|syntax highlighting color code mirror codemirror|
13
 ! Info
14
 CoreVersion parameter is needed for TiddlyWiki only!
15
 ***/
2
|''Name''|tiddlywiki.js|
3
|''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
4
|''Author''|PMario|
5
|''Version''|0.1.7|
6
|''Status''|''stable''|
7
|''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
8
|''Documentation''|http://codemirror.tiddlyspace.com/|
9
|''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
10
|''CoreVersion''|2.5.0|
11
|''Requires''|codemirror.js|
12
|''Keywords''|syntax highlighting color code mirror codemirror|
13
! Info
14
CoreVersion parameter is needed for TiddlyWiki only!
15
***/
16 16
//{{{
17 17
CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
18 18
	var indentUnit = config.indentUnit;
......
47 47
	}();
48 48

  
49 49
	var isSpaceName = /[\w_\-]/i,
50
		reHR = /^\-\-\-\-+$/,
50
		reHR = /^\-\-\-\-+$/,					// <hr>
51 51
		reWikiCommentStart = /^\/\*\*\*$/,		// /***
52 52
		reWikiCommentStop = /^\*\*\*\/$/,		// ***/
53 53
		reBlockQuote = /^<<<$/,
54 54

  
55
		reJsCodeStart = /^\/\/\{\{\{$/,			// //{{{
56
		reJsCodeStop = /^\/\/\}\}\}$/,			// //}}}
57
		reXmlCodeStart = /^<!--\{\{\{-->$/,
58
		reXmlCodeStop = /^<!--\}\}\}-->$/,
55
		reJsCodeStart = /^\/\/\{\{\{$/,			// //{{{ js block start
56
		reJsCodeStop = /^\/\/\}\}\}$/,			// //}}} js stop
57
		reXmlCodeStart = /^<!--\{\{\{-->$/,		// xml block start
58
		reXmlCodeStop = /^<!--\}\}\}-->$/,		// xml stop
59 59

  
60
		reCodeBlockStart = /^\{\{\{$/,
61
		reCodeBlockStop = /^\}\}\}$/,
60
		reCodeBlockStart = /^\{\{\{$/,			// {{{ TW text div block start
61
		reCodeBlockStop = /^\}\}\}$/,			// }}} TW text stop
62 62

  
63
		reCodeStart = /\{\{\{/,
63
		reCodeStart = /\{\{\{/,					// {{{ code span start
64 64
		reUntilCodeStop = /.*?\}\}\}/;
65 65

  
66 66
	function chain(stream, state, f) {
......
95 95
			
96 96
		state.block = false;	// indicates the start of a code block.
97 97

  
98
		ch = stream.peek(); // don't eat, to make match simpler
98
		ch = stream.peek(); 	// don't eat, to make matching simpler
99 99
		
100
		// check start of  blocks    
100
		// check start of  blocks
101 101
		if (sol && /[<\/\*{}\-]/.test(ch)) {
102 102
			if (stream.match(reCodeBlockStart)) {
103 103
				state.block = true;
......
116 116
				return ret('hr', 'hr');
117 117
			}
118 118
		} // sol
119
		var ch = stream.next();
119
		ch = stream.next();
120 120

  
121 121
		if (sol && /[\/\*!#;:>|]/.test(ch)) {
122 122
			if (ch == "!") { // tw header
......
131 131
				stream.eatWhile('#');
132 132
				return ret("list", "list");
133 133
			}
134
			if (ch == ";") { // tw list
134
			if (ch == ";") { // definition list, term
135 135
				stream.eatWhile(';');
136 136
				return ret("list", "list");
137 137
			}
138
			if (ch == ":") { // tw list
138
			if (ch == ":") { // definition list, description
139 139
				stream.eatWhile(':');
140 140
				return ret("list", "list");
141 141
			}
......
162 162
		if (ch == '"') {
163 163
			return ret('string', 'string');
164 164
		}
165
		if (ch == '~') {	// _no_ CamelCase indicator should be bold
166
			return ret('text', 'brace');
167
		}
165 168
		if (/[\[\]]/.test(ch)) { // check for [[..]]
166 169
			if (stream.peek() == ch) {
167 170
				stream.next();
......
189 192
				return chain(stream, state, twTokenUnderline);
190 193
			}
191 194
		}
192
		if (ch == "-") { // tw strikethrough TODO looks ugly .. different handling see below;
195
		// strikethrough and mdash handling
196
		if (ch == "-") {
193 197
			if (stream.eat("-")) {
194
				return chain(stream, state, twTokenStrike);
198
				// if strikethrough looks ugly, change CSS.
199
				if (stream.peek() != ' ')
200
					return chain(stream, state, twTokenStrike);
201
				// mdash
202
				if (stream.peek() == ' ')
203
					return ret('text', 'brace');
195 204
			}
196 205
		}
197 206
		if (ch == "'") { // tw bold
......
208 217
			return ret(ch);
209 218
		}
210 219

  
220
		// core macro handling
211 221
		stream.eatWhile(/[\w\$_]/);
212 222
		var word = stream.current(),
213 223
			known = textwords.propertyIsEnumerable(word) && textwords[word];
......
301 311
		return ret("text", "underlined");
302 312
	}
303 313

  
304
	// tw strike through text looks ugly 
305
	// TODO just strike through the first and last 2 chars if possible.
314
	// tw strike through text looks ugly
315
	// change CSS if needed
306 316
	function twTokenStrike(stream, state) {
307 317
		var maybeEnd = false,
308 318
			ch, nr;
trunk/scripts/codemirror/mode/tiddlywiki/index.html
16 16
!TiddlyWiki Formatting
17 17
* Rendered versions can be found at: http://www.tiddlywiki.com/#Reference
18 18

  
19
|!Option|!Syntax|!Output|
20
|bold font|{{{''bold''}}}|''bold''|
21
|italic type|{{{//italic//}}}|//italic//|
22
|underlined text|{{{__underlined__}}}|__underlined__|
23
|strikethrough text|{{{--strikethrough--}}}|--strikethrough--|
24
|superscript text|{{{^^super^^script}}}|^^super^^script|
25
|subscript text|{{{~~sub~~script}}}|~~sub~~script|
26
|highlighted text|{{{@@highlighted@@}}}|@@highlighted@@|
27
|preformatted text|<html><code>{{{preformatted}}}</code></html>|{{{preformatted}}}|
19
|!Option            | !Syntax            |
20
|bold font          | ''bold''           |
21
|italic type        | //italic//         |
22
|underlined text    | __underlined__     |
23
|strikethrough text | --strikethrough--  |
24
|superscript text   | super^^script^^    |
25
|subscript text     | sub~~script~~      |
26
|highlighted text   | @@highlighted@@    |
27
|preformatted text  | {{{preformatted}}} |
28 28

  
29 29
!Block Elements
30
!!Headings
31
{{{
32
!Heading 1
33
!!Heading 2
34
!!!Heading 3
35
!!!!Heading 4
36
!!!!!Heading 5
37
}}}
38 30
<<<
39

  
40 31
!Heading 1
41 32

  
42 33
!!Heading 2
......
49 40
<<<
50 41

  
51 42
!!Lists
52
{{{
53
* unordered list, level 1
54
** unordered list, level 2
55
*** unordered list, level 3
56

  
57
# ordered list, level 1
58
## ordered list, level 2
59
### unordered list, level 3
60

  
61
; definition list, term
62
: definition list, description
63
}}}
64 43
<<<
65 44
* unordered list, level 1
66 45
** unordered list, level 2
......
75 54
<<<
76 55

  
77 56
!!Blockquotes
78
{{{
79
> blockquote, level 1
80
>> blockquote, level 2
81
>>> blockquote, level 3
82

  
83 57
<<<
84
blockquote
85
<<<
86
}}}
87
<<<
88 58
> blockquote, level 1
89 59
>> blockquote, level 2
90 60
>>> blockquote, level 3
......
93 63
<<<
94 64

  
95 65
!!Preformatted Text
96
<html><pre>
97
{{{
98
preformatted (e.g. code)
99
}}}
100
</pre></html>
101 66
<<<
102 67
{{{
103 68
preformatted (e.g. code)
......
105 70
<<<
106 71

  
107 72
!!Code Sections
73
<<<
108 74
{{{
109 75
Text style code
110 76
}}}
......
116 82
<!--{{{-->
117 83
XML styled code. TiddlyWiki mixed mode should support highlighter switching in the future.
118 84
<!--}}}-->
85
<<<
119 86

  
120 87
!!Tables
121
{{{
88
<<<
122 89
|CssClass|k
123 90
|!heading column 1|!heading column 2|
124 91
|row 1, column 1|row 1, column 2|
......
128 95
|~| ... |
129 96
|CssProperty:value;...| ... |
130 97
|caption|c
131
}}}
98

  
132 99
''Annotation:''
133 100
* The {{{>}}} marker creates a "colspan", causing the current cell to merge with the one to the right.
134 101
* The {{{~}}} marker creates a "rowspan", causing the current cell to merge with the one above.
135 102
<<<
136
|CssClass|k
137
|!heading column 1|!heading column 2|
138
|row 1, column 1|row 1, column 2|
139
|row 2, column 1|row 2, column 2|
140
|>|COLSPAN|
141
|ROWSPAN| ... |
142
|~| ... |
143
|CssProperty:value;...| ... |
144
|caption|c
145
<<<
146 103
!!Images /% TODO %/
147 104
cf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]
148 105

  
trunk/scripts/codemirror/mode/htmlembedded/htmlembedded.js
61 61

  
62 62
    electricChars: "/{}:"
63 63
  }
64
});
64
}, "htmlmixed");
65 65

  
66 66
CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"});
67 67
CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
trunk/scripts/codemirror/mode/python/python.js
275 275
        if (current === 'pass' || current === 'return') {
276 276
            state.dedent += 1;
277 277
        }
278
        if (current === 'lambda') state.lambda = true;
278 279
        if ((current === ':' && !state.lambda && state.scopes[0].type == 'py')
279 280
            || indentInfo === 'indent') {
280 281
            indent(stream, state);
trunk/scripts/codemirror/mode/ruby/ruby.js
33 33
    var ch = stream.next();
34 34
    if (ch == "`" || ch == "'" || ch == '"' ||
35 35
        (ch == "/" && !stream.eol() && stream.peek() != " ")) {
36
      return chain(readQuoted(ch, "string", ch == '"'), stream, state);
36
      return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
37 37
    } else if (ch == "%") {
38 38
      var style, embed = false;
39 39
      if (stream.eat("s")) style = "atom";
trunk/scripts/codemirror/mode/stex/index.html
89 89
      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
90 90
    </script>
91 91

  
92
    <p><strong>MIME types defined:</strong> <code>text/stex</code>.</p>
92
    <p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>
93 93

  
94 94
  </body>
95 95
</html>
trunk/scripts/codemirror/mode/stex/stex.js
82 82
    }
83 83

  
84 84
    function normal(source, state) {
85
	if (source.match(/^\\[a-z]+/)) {
85
	if (source.match(/^\\[a-zA-Z@]+/)) {
86 86
	    var cmdName = source.current();
87 87
	    cmdName = cmdName.substr(1, cmdName.length-1);
88 88
	    var plug = plugins[cmdName];
......
95 95
	    return plug.style;
96 96
	}
97 97

  
98
        // escape characters 
99
        if (source.match(/^\\[$&%#{}_]/)) {
100
          return "tag";
101
        }
102

  
103
        // white space control characters
104
        if (source.match(/^\\[,;!\/]/)) {
105
          return "tag";
106
        }
107

  
98 108
	var ch = source.next();
99 109
	if (ch == "%") {
100
	    setState(state, inCComment);
110
            // special case: % at end of its own line; stay in same state
111
            if (!source.eol()) {
112
              setState(state, inCComment);
113
            }
101 114
	    return "comment";
102 115
	} 
103 116
	else if (ch=='}' || ch==']') {
trunk/scripts/codemirror/mode/smalltalk/smalltalk.js
27 27

  
28 28
	var next = function(stream, context, state) {
29 29
		var token = new Token(null, context, false);
30
		var char = stream.next();
30
		var aChar = stream.next();
31 31

  
32
		if (char === '"') {
32
		if (aChar === '"') {
33 33
			token = nextComment(stream, new Context(nextComment, context));
34 34

  
35
		} else if (char === '\'') {
35
		} else if (aChar === '\'') {
36 36
			token = nextString(stream, new Context(nextString, context));
37 37

  
38
		} else if (char === '#') {
38
		} else if (aChar === '#') {
39 39
			stream.eatWhile(/[^ .]/);
40 40
			token.name = 'string-2';
41 41

  
42
		} else if (char === '$') {
42
		} else if (aChar === '$') {
43 43
			stream.eatWhile(/[^ ]/);
44 44
			token.name = 'string-2';
45 45

  
46
		} else if (char === '|' && state.expectVariable) {
46
		} else if (aChar === '|' && state.expectVariable) {
47 47
			token.context = new Context(nextTemporaries, context);
48 48

  
49
		} else if (/[\[\]{}()]/.test(char)) {
49
		} else if (/[\[\]{}()]/.test(aChar)) {
50 50
			token.name = 'bracket';
51
			token.eos = /[\[{(]/.test(char);
51
			token.eos = /[\[{(]/.test(aChar);
52 52

  
53
			if (char === '[') {
53
			if (aChar === '[') {
54 54
				state.indentation++;
55
			} else if (char === ']') {
55
			} else if (aChar === ']') {
56 56
				state.indentation = Math.max(0, state.indentation - 1);
57 57
			}
58 58

  
59
		} else if (specialChars.test(char)) {
59
		} else if (specialChars.test(aChar)) {
60 60
			stream.eatWhile(specialChars);
61 61
			token.name = 'operator';
62
			token.eos = char !== ';'; // ; cascaded message expression
62
			token.eos = aChar !== ';'; // ; cascaded message expression
63 63

  
64
		} else if (/\d/.test(char)) {
64
		} else if (/\d/.test(aChar)) {
65 65
			stream.eatWhile(/[\w\d]/);
66 66
			token.name = 'number'
67 67

  
68
		} else if (/[\w_]/.test(char)) {
68
		} else if (/[\w_]/.test(aChar)) {
69 69
			stream.eatWhile(/[\w\d_]/);
70 70
			token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;
71 71

  
......
88 88

  
89 89
	var nextTemporaries = function(stream, context, state) {
90 90
		var token = new Token(null, context, false);
91
		var char = stream.next();
91
		var aChar = stream.next();
92 92

  
93
		if (char === '|') {
93
		if (aChar === '|') {
94 94
			token.context = context.parent;
95 95
			token.eos = true;
96 96

  
trunk/scripts/codemirror/mode/clike/clike.js
21 21
    }
22 22
    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
23 23
      curPunc = ch;
24
      return null
24
      return null;
25 25
    }
26 26
    if (/\d/.test(ch)) {
27 27
      stream.eatWhile(/[\w\.]/);
......
59 59
        escaped = !escaped && next == "\\";
60 60
      }
61 61
      if (end || !(escaped || multiLineStrings))
62
        state.tokenize = tokenBase;
62
        state.tokenize = null;
63 63
      return "string";
64 64
    };
65 65
  }
......
68 68
    var maybeEnd = false, ch;
69 69
    while (ch = stream.next()) {
70 70
      if (ch == "/" && maybeEnd) {
71
        state.tokenize = tokenBase;
71
        state.tokenize = null;
72 72
        break;
73 73
      }
74 74
      maybeEnd = (ch == "*");
trunk/scripts/codemirror/mode/clike/index.html
96 96
    <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
97 97
    (C code), <code>text/x-c++src</code> (C++
98 98
    code), <code>text/x-java</code> (Java
99
    code).</p>
99
    code), <code>text/x-csharp</code> (C#).</p>
100 100
  </body>
101 101
</html>
trunk/scripts/codemirror/mode/css/css.js
92 92
      var style = state.tokenize(stream, state);
93 93

  
94 94
      var context = state.stack[state.stack.length-1];
95
      if (type == "hash" && context == "rule") style = "atom";
95
      if (type == "hash" && context != "rule") style = "string-2";
96 96
      else if (style == "variable") {
97 97
        if (context == "rule") style = "number";
98 98
        else if (!context || context == "@media{") style = "tag";
trunk/scripts/codemirror/mode/xmlpure/index.html
54 54
    <p><b>@date</b>: August, 2011<br/> 
55 55
    <p><b>@github</b>: <a href='https://github.com/deebugger/CodeMirror2' target='blank'>https://github.com/deebugger/CodeMirror2</a></p>
56 56

  
57
    <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/xml</code>.</p>
58 57
  </body>
59 58
</html>
trunk/scripts/codemirror/mode/xml/xml.js
1 1
CodeMirror.defineMode("xml", function(config, parserConfig) {
2 2
  var indentUnit = config.indentUnit;
3 3
  var Kludges = parserConfig.htmlMode ? {
4
    autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
5
                      "meta": true, "col": true, "frame": true, "base": true, "area": true},
4
    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
5
                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
6
                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
7
                      'track': true, 'wbr': true},
8
    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
9
                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
10
                       'th': true, 'tr': true},
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff