diff --git a/.gitignore b/.gitignore
index 218ee79d0d..52dc0bdab1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
!.gitmodule
composer.phar
-/vendor/
+/data/vendor/
*.cache
*.log
/data/config/config.php
diff --git a/.travis.yml b/.travis.yml
index 7b7c7cedc1..a79b85d7de 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,24 +26,25 @@ before_script:
- if [[ $TRAVIS_PHP_VERSION == '5.3.3' ]]; then composer install --dev --no-interaction --prefer-source ; fi
- if [[ $TRAVIS_PHP_VERSION != '5.3.3' ]]; then composer install --dev --no-interaction ; fi
- sh -c "if [ '$DB' = 'mysql' ]; then sh ./eccube_install.sh mysql; fi"
- - sh -c "if [ '$DB' = 'pgsql' ]; then sh ./eccube_install.sh pgsql; fi"
+ - sh -c "if [ '$DB' = 'pgsql' ]; then sh ./eccube_install.sh appveyor; fi"
- cp tests/require.php.jenkins tests/require.php
- cat ./data/config/config.php
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- php -S localhost:8085 -t html/ &
- - php vendor/bin/codecept build
+ - php data/vendor/bin/codecept build
script:
- mkdir -p reports/coverage
- - php vendor/bin/phpunit -c phpunit.xml.dist
- - php vendor/bin/codecept run --env travis --steps
+ - php data/vendor/bin/phpunit -c phpunit.xml.dist
+ - php data/vendor/bin/codecept run --env travis --steps
after_script:
- - php vendor/bin/coveralls -v
+ - php data/vendor/bin/coveralls -v
+ - cat ./data/logs/error.log
# Cache folder, you can delete cache from Travis CI web interface
cache:
directories:
- - vendor
+ - data/vendor
- $HOME/.composer/cache vendor/
diff --git a/README.md b/README.md
index 2077f73050..f5ba39f4fd 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,46 @@
-# EC-CUBE 2.13系
+# EC-CUBE 2.13系 / 2.17系(開発中)
[![Build Status](https://travis-ci.org/EC-CUBE/eccube-2_13.svg)](https://travis-ci.org/EC-CUBE/eccube-2_13)
[![Coverage Status](https://coveralls.io/repos/EC-CUBE/eccube-2_13/badge.png)](https://coveralls.io/r/EC-CUBE/eccube-2_13)
-* * * * * * * * * * * * * * * * * * * *
+---
-===========
-
-### EC-CUBE Trac について
+## EC-CUBE Trac について
EC-CUBE 2.13系については、2014年10月以前に利用されていた、[EC-CUBE Trac](http://svn.ec-cube.net/open_trac/) と[SVN](http://svn.ec-cube.net/open/)がございますので、合わせてご参照ください。
-新規のご投稿やコミットはいただけませんが、GitHubにまだ移されていない不具合の情報や過去の経緯などが御確認いただけます。
+新規のご投稿やコミットはいただけませんが、GitHubに移されていない不具合の情報や過去の経緯などをご確認いただけます。
-EC-CUBE Trac にある議論の再開や不具合の修正についても、GitHubにIssueを起票しなおしていただいたり、Pull Requestをいただけますと幸いです。
+EC-CUBE Trac にある議論の再開や不具合の修正についても、GitHubにIssueを再作成していただいたり、Pull requestをいただけますと幸いです。
-### 開発協力
+## 開発協力
コードの提供・追加、修正・変更その他「EC-CUBE」への開発の御協力(以下「コミット」といいます)を行っていただく場合には、
[EC-CUBEのコピーライトポリシー](https://github.com/EC-CUBE/ec-cube/blob/50de4ac511ab5a5577c046b61754d98be96aa328/LICENSE.txt)をご理解いただき、ご了承いただく必要がございます。
-pull requestを送信する際は、EC-CUBEのコピーライトポリシーに同意したものとみなします。
+Pull requestを送信する際は、EC-CUBEのコピーライトポリシーに同意したものとみなします。
+
+## 開発方針
+
+本リポジトリでは、以下方針で開発を行っています。
+
+### 2.13系
+
+* 保守と不具合修正を行います。
+* 修正時は `master` に対してPull requestを作成してください。
+
+### 2.17系(開発中)
+
+* EC-CUBE 2.13系に対して、PHP7対応を行うバージョンです。
+* ブランチ `improve/php7` で開発を行っています。
+修正時は `improve/php7` に対してPull requestを作成してください。
+* 2.17系に関連するIssueについては、[マイルストーン 2.17.0](https://github.com/EC-CUBE/eccube-2_13/milestone/5)を参照してください。
+
+##### 2.17系 システム要件の変更
-### 開発方針
+動作にはPHP5.4以降が必要になります。
-本リポジトリでは、以下の対応を開発方針として定めます。
+##### 2.17系 インストールについて
-* EC-CUBE2.13系の保守
-* 不具合修正
+Composerを導入に伴い、clone後に`composer install`の実行が必要です。
-上記に含まれない新規機能開発や構造の変化を伴う修正等については、
-[EC-CUBE/ec-cube](https://github.com/EC-CUBE/ec-cube)にて開発を行っております。
+---
+上記に含まれない新規機能開発や構造の変化を伴う修正等については、[EC-CUBE/ec-cube](https://github.com/EC-CUBE/ec-cube)にて開発を行っております。
diff --git a/composer.json b/composer.json
index 64e7056f5e..8f5c1e9c29 100644
--- a/composer.json
+++ b/composer.json
@@ -13,6 +13,7 @@
"config": {
"disable-tls": true,
"secure-http": false,
+ "vendor-dir": "data/vendor",
"platform": {
"php": "5.4"
}
@@ -32,23 +33,18 @@
"pear-pear.php.net/PEAR" : "*",
"pear-pear.php.net/Archive_Tar" : "*",
"pear-pear.php.net/Mail" : "*",
- "pear-pear.php.net/Calendar" : "*",
"pear-pear.php.net/Cache_Lite" : "*",
"pear-pear.php.net/File_SearchReplace" : "*",
- "pear-pear.php.net/HTTP_Request" : "*",
"pear-pear.php.net/MDB2_Driver_mysqli" : "1.5.0b4",
"pear-pear.php.net/MDB2_Driver_pgsql" : "1.5.0b4",
"pear-pear.php.net/MDB2" : "2.5.0-beta5 as 2.5.0",
- "pear-pear.php.net/Net_SMTP" : "*",
- "pear-pear.php.net/Net_Socket" : "*",
- "pear-pear.php.net/Net_URL" : "*",
"pear-pear.php.net/Net_UserAgent_Mobile" : "*",
- "pear-pear.php.net/SOAP" : "*",
"pear-pear.php.net/Services_JSON" : "*",
"pear-pear.php.net/Text_Password" : "*",
"pear-pear.php.net/XML_Parser" : "*",
"pear-pear.php.net/XML_Serializer" : "*",
- "pear-pear.php.net/XML_Util" : "*"
+ "pear-pear.php.net/XML_Util" : "*",
+ "mobiledetect/mobiledetectlib": "^2.8"
},
"autoload": {
"classmap": [
diff --git a/composer.lock b/composer.lock
index 6fe5abb51f..5e40b68e48 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,52 +4,74 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "f426e51cd01ae4e2e02879aad4522883",
+ "content-hash": "c89ab5c445e872cee2577039bbb3a8cd",
"packages": [
{
- "name": "pear-pear.php.net/Archive_Tar",
- "version": "1.4.2",
+ "name": "mobiledetect/mobiledetectlib",
+ "version": "2.8.26",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/serbanghita/Mobile-Detect.git",
+ "reference": "a0ed86c9d7c04ae27fa6418b55e3beb04dfe3297"
+ },
"dist": {
- "type": "file",
- "url": "http://pear.php.net/get/Archive_Tar-1.4.2.tgz",
- "reference": null,
- "shasum": null
+ "type": "zip",
+ "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/a0ed86c9d7c04ae27fa6418b55e3beb04dfe3297",
+ "reference": "a0ed86c9d7c04ae27fa6418b55e3beb04dfe3297",
+ "shasum": ""
},
"require": {
- "php": ">=5.2.0.0"
+ "php": ">=5.0.0"
},
- "replace": {
- "pear-pear/archive_tar": "== 1.4.2.0"
+ "require-dev": {
+ "phpunit/phpunit": "*"
},
- "type": "pear-library",
+ "type": "library",
"autoload": {
"classmap": [
- ""
- ]
+ "Mobile_Detect.php"
+ ],
+ "psr-0": {
+ "Detection": "namespaced/"
+ }
},
- "include-path": [
- "/"
- ],
+ "notification-url": "https://packagist.org/downloads/",
"license": [
- "New BSD License"
+ "MIT"
],
- "description": "This class provides handling of tar files in PHP.\nIt supports creating, listing, extracting and adding to tar files.\nGzip support is available if PHP has the zlib extension built-in or\nloaded. Bz2 compression is also supported with the bz2 extension loaded."
+ "authors": [
+ {
+ "name": "Serban Ghita",
+ "email": "serbanghita@gmail.com",
+ "homepage": "http://mobiledetect.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.",
+ "homepage": "https://github.com/serbanghita/Mobile-Detect",
+ "keywords": [
+ "detect mobile devices",
+ "mobile",
+ "mobile detect",
+ "mobile detector",
+ "php mobile detect"
+ ],
+ "time": "2017-08-29T18:23:54+00:00"
},
{
- "name": "pear-pear.php.net/Cache_Lite",
- "version": "1.8.0",
+ "name": "pear-pear.php.net/Archive_Tar",
+ "version": "1.4.3",
"dist": {
"type": "file",
- "url": "http://pear.php.net/get/Cache_Lite-1.8.0.tgz",
+ "url": "http://pear.php.net/get/Archive_Tar-1.4.3.tgz",
"reference": null,
"shasum": null
},
"require": {
- "pear-pear.php.net/pear": ">=1.10.1.0",
- "php": ">=5.4.0.0"
+ "php": ">=5.2.0.0"
},
"replace": {
- "pear-pear/cache_lite": "== 1.8.0.0"
+ "pear-pear/archive_tar": "== 1.4.3.0"
},
"type": "pear-library",
"autoload": {
@@ -61,24 +83,25 @@
"/"
],
"license": [
- "lgpl"
+ "New BSD License"
],
- "description": "This package is a little cache system optimized for file containers. It is fast and safe (because it\n uses file locking and/or anti-corruption tests)."
+ "description": "This class provides handling of tar files in PHP.\nIt supports creating, listing, extracting and adding to tar files.\nGzip support is available if PHP has the zlib extension built-in or\nloaded. Bz2 compression is also supported with the bz2 extension loaded."
},
{
- "name": "pear-pear.php.net/Calendar",
- "version": "0.5.5",
+ "name": "pear-pear.php.net/Cache_Lite",
+ "version": "1.8.0",
"dist": {
"type": "file",
- "url": "http://pear.php.net/get/Calendar-0.5.5.tgz",
+ "url": "http://pear.php.net/get/Cache_Lite-1.8.0.tgz",
"reference": null,
"shasum": null
},
"require": {
- "php": ">=5.0.0.0"
+ "pear-pear.php.net/pear": ">=1.10.1.0",
+ "php": ">=5.4.0.0"
},
"replace": {
- "pear-pear/calendar": "== 0.5.5.0"
+ "pear-pear/cache_lite": "== 1.8.0.0"
},
"type": "pear-library",
"autoload": {
@@ -90,9 +113,9 @@
"/"
],
"license": [
- "BSD"
+ "lgpl"
],
- "description": "Calendar provides an API for building Calendar data structures. Using\nthe simple iterator and it's "query" API, a user interface can easily be\nbuilt on top of the calendar data structure, at the same time easily connecting it\nto some kind of underlying data store, where "event" information is\nbeing held.\n\nIt provides different calculation "engines" the default being based on\nUnix timestamps (offering fastest performance) with an alternative using PEAR::Date\nwhich extends the calendar past the limitations of Unix timestamps. Other engines\nshould be implementable for other types of calendar (e.g. a Chinese Calendar based\non lunar cycles)."
+ "description": "This package is a little cache system optimized for file containers. It is fast and safe (because it\n uses file locking and/or anti-corruption tests)."
},
{
"name": "pear-pear.php.net/Console_Getopt",
@@ -152,37 +175,6 @@
],
"description": "Provides various functions to perform replace\non files. Preg/Ereg regex supported along with faster, but more basic str_replace routine."
},
- {
- "name": "pear-pear.php.net/HTTP_Request",
- "version": "1.4.4",
- "dist": {
- "type": "file",
- "url": "http://pear.php.net/get/HTTP_Request-1.4.4.tgz",
- "reference": null,
- "shasum": null
- },
- "require": {
- "pear-pear.php.net/net_socket": ">=1.0.7.0",
- "pear-pear.php.net/net_url": ">=1.0.12.0",
- "php": ">=4.2.0.0"
- },
- "replace": {
- "pear-pear/http_request": "== 1.4.4.0"
- },
- "type": "pear-library",
- "autoload": {
- "classmap": [
- ""
- ]
- },
- "include-path": [
- "/"
- ],
- "license": [
- "BSD"
- ],
- "description": "Supports GET/POST/HEAD/TRACE/PUT/DELETE, Basic authentication, Proxy,\nProxy Authentication, SSL, file uploads etc."
- },
{
"name": "pear-pear.php.net/MDB2",
"version": "2.5.0b5",
@@ -317,94 +309,6 @@
],
"description": "PEAR's Mail package defines an interface for implementing mailers under the PEAR hierarchy. It also provides supporting functions useful to multiple mailer backends. Currently supported backends include: PHP's native mail() function, sendmail, and SMTP. This package also provides a RFC822 email address list validation utility class."
},
- {
- "name": "pear-pear.php.net/Net_SMTP",
- "version": "1.8.0",
- "dist": {
- "type": "file",
- "url": "http://pear.php.net/get/Net_SMTP-1.8.0.tgz",
- "reference": null,
- "shasum": null
- },
- "require": {
- "pear-pear.php.net/net_socket": ">=1.0.7.0",
- "php": ">=5.4.0.0"
- },
- "replace": {
- "pear-pear/net_smtp": "== 1.8.0.0"
- },
- "type": "pear-library",
- "autoload": {
- "classmap": [
- ""
- ]
- },
- "include-path": [
- "/"
- ],
- "license": [
- "PHP License"
- ],
- "description": "Provides an implementation of the SMTP protocol using PEAR's Net_Socket class."
- },
- {
- "name": "pear-pear.php.net/Net_Socket",
- "version": "1.2.2",
- "dist": {
- "type": "file",
- "url": "http://pear.php.net/get/Net_Socket-1.2.2.tgz",
- "reference": null,
- "shasum": null
- },
- "require": {
- "php": ">=5.4.0.0"
- },
- "replace": {
- "pear-pear/net_socket": "== 1.2.2.0"
- },
- "type": "pear-library",
- "autoload": {
- "classmap": [
- ""
- ]
- },
- "include-path": [
- "/"
- ],
- "license": [
- "BSD-2-Clause"
- ],
- "description": "Net_Socket is a class interface to TCP sockets. It provides blocking\n and non-blocking operation, with different reading and writing modes\n (byte-wise, block-wise, line-wise and special formats like network\n byte-order ip addresses)."
- },
- {
- "name": "pear-pear.php.net/Net_URL",
- "version": "1.0.15",
- "dist": {
- "type": "file",
- "url": "http://pear.php.net/get/Net_URL-1.0.15.tgz",
- "reference": null,
- "shasum": null
- },
- "require": {
- "php": ">=4.0.0.0"
- },
- "replace": {
- "pear-pear/net_url": "== 1.0.15.0"
- },
- "type": "pear-library",
- "autoload": {
- "classmap": [
- ""
- ]
- },
- "include-path": [
- "/"
- ],
- "license": [
- "BSD"
- ],
- "description": "Provides easy parsing of URLs and their constituent parts."
- },
{
"name": "pear-pear.php.net/Net_UserAgent_Mobile",
"version": "1.0.0",
@@ -438,10 +342,10 @@
},
{
"name": "pear-pear.php.net/PEAR",
- "version": "1.10.4",
+ "version": "1.10.5",
"dist": {
"type": "file",
- "url": "http://pear.php.net/get/PEAR-1.10.4.tgz",
+ "url": "http://pear.php.net/get/PEAR-1.10.5.tgz",
"reference": null,
"shasum": null
},
@@ -459,7 +363,7 @@
"pear-pear.php.net/pear_frontend_web": "<=0.4.0.0"
},
"replace": {
- "pear-pear/pear": "== 1.10.4.0"
+ "pear-pear/pear": "== 1.10.5.0"
},
"type": "pear-library",
"autoload": {
@@ -475,37 +379,6 @@
],
"description": "The PEAR package contains:\n * the PEAR installer, for creating, distributing\n and installing packages\n * the PEAR_Exception PHP5 error handling mechanism\n * the PEAR_ErrorStack advanced error handling mechanism\n * the PEAR_Error error handling mechanism\n * the OS_Guess class for retrieving info about the OS\n where PHP is running on\n * the System class for quick handling of common operations\n with files and directories\n * the PEAR base class\n Features in a nutshell:\n * full support for channels\n * pre-download dependency validation\n * new package.xml 2.0 format allows tremendous flexibility while maintaining BC\n * support for optional dependency groups and limited support for sub-packaging\n * robust dependency support\n * full dependency validation on uninstall\n * remote install for hosts with only ftp access - no more problems with\n restricted host installation\n * full support for mirroring\n * support for bundling several packages into a single tarball\n * support for static dependencies on a url-based package\n * support for custom file roles and installation tasks"
},
- {
- "name": "pear-pear.php.net/SOAP",
- "version": "0.13.0",
- "dist": {
- "type": "file",
- "url": "http://pear.php.net/get/SOAP-0.13.0.tgz",
- "reference": null,
- "shasum": null
- },
- "require": {
- "pear-pear.php.net/http_request": "*",
- "pear-pear.php.net/pear": "*",
- "php": ">=5.0.0.0"
- },
- "replace": {
- "pear-pear/soap": "== 0.13.0.0"
- },
- "type": "pear-library",
- "autoload": {
- "classmap": [
- ""
- ]
- },
- "include-path": [
- "/"
- ],
- "license": [
- "PHP License"
- ],
- "description": "Implementation of SOAP protocol and services"
- },
{
"name": "pear-pear.php.net/Services_JSON",
"version": "1.0.3",
@@ -658,10 +531,10 @@
},
{
"name": "pear-pear.php.net/XML_Util",
- "version": "1.4.2",
+ "version": "1.4.3",
"dist": {
"type": "file",
- "url": "http://pear.php.net/get/XML_Util-1.4.2.tgz",
+ "url": "http://pear.php.net/get/XML_Util-1.4.3.tgz",
"reference": null,
"shasum": null
},
@@ -670,7 +543,7 @@
"php": ">=5.4.0.0"
},
"replace": {
- "pear-pear/xml_util": "== 1.4.2.0"
+ "pear-pear/xml_util": "== 1.4.3.0"
},
"type": "pear-library",
"autoload": {
@@ -802,28 +675,28 @@
},
{
"name": "codeception/codeception",
- "version": "2.2.11",
+ "version": "2.3.5",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Codeception.git",
- "reference": "a8681b416921ae282ccca2c485d75a3ed6756080"
+ "reference": "e807cd458eb9f7ae7464f33ad835a2f54aa73194"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Codeception/Codeception/zipball/a8681b416921ae282ccca2c485d75a3ed6756080",
- "reference": "a8681b416921ae282ccca2c485d75a3ed6756080",
+ "url": "https://api.github.com/repos/Codeception/Codeception/zipball/e807cd458eb9f7ae7464f33ad835a2f54aa73194",
+ "reference": "e807cd458eb9f7ae7464f33ad835a2f54aa73194",
"shasum": ""
},
"require": {
"behat/gherkin": "~4.4.0",
"ext-json": "*",
"ext-mbstring": "*",
- "facebook/webdriver": ">=1.0.1 <2.0",
+ "facebook/webdriver": ">=1.1.3 <2.0",
"guzzlehttp/guzzle": ">=4.1.4 <7.0",
"guzzlehttp/psr7": "~1.0",
"php": ">=5.4.0 <8.0",
"phpunit/php-code-coverage": ">=2.2.4 <6.0",
- "phpunit/phpunit": ">4.8.20 <6.0",
+ "phpunit/phpunit": ">4.8.20 <7.0",
"phpunit/phpunit-mock-objects": ">2.3 <5.0",
"sebastian/comparator": ">1.1 <3.0",
"sebastian/diff": "^1.4",
@@ -848,6 +721,7 @@
"php-amqplib/php-amqplib": "~2.4",
"predis/predis": "^1.0",
"squizlabs/php_codesniffer": "~2.0",
+ "symfony/process": ">=2.7 <4.0",
"vlucas/phpdotenv": "^2.4.0"
},
"suggest": {
@@ -892,7 +766,7 @@
"functional testing",
"unit testing"
],
- "time": "2017-05-11T21:07:05+00:00"
+ "time": "2017-08-10T20:28:02+00:00"
},
{
"name": "doctrine/instantiator",
@@ -1310,16 +1184,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "2.0.4",
+ "version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
+ "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
- "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b",
+ "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b",
"shasum": ""
},
"require": {
@@ -1355,26 +1229,26 @@
"email": "mike.vanriel@naenius.com"
}
],
- "time": "2015-02-03T12:10:50+00:00"
+ "time": "2016-01-25T08:17:30+00:00"
},
{
"name": "phpspec/prophecy",
- "version": "v1.7.0",
+ "version": "v1.7.2",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "93d39f1f7f9326d746203c7c056f300f7f126073"
+ "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073",
- "reference": "93d39f1f7f9326d746203c7c056f300f7f126073",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6",
+ "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
"sebastian/comparator": "^1.1|^2.0",
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
},
@@ -1385,7 +1259,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.6.x-dev"
+ "dev-master": "1.7.x-dev"
}
},
"autoload": {
@@ -1418,7 +1292,7 @@
"spy",
"stub"
],
- "time": "2017-03-02T20:05:34+00:00"
+ "time": "2017-09-04T11:05:03+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -1670,16 +1544,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "4.8.35",
+ "version": "4.8.36",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87"
+ "reference": "46023de9a91eec7dfb06cc56cb4e260017298517"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87",
- "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517",
+ "reference": "46023de9a91eec7dfb06cc56cb4e260017298517",
"shasum": ""
},
"require": {
@@ -1738,7 +1612,7 @@
"testing",
"xunit"
],
- "time": "2017-02-06T05:18:07+00:00"
+ "time": "2017-06-21T08:07:12+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -2068,23 +1942,23 @@
},
{
"name": "sebastian/diff",
- "version": "1.4.1",
+ "version": "1.4.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
+ "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
+ "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^5.3.3 || ^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.8"
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
},
"type": "library",
"extra": {
@@ -2116,7 +1990,7 @@
"keywords": [
"diff"
],
- "time": "2015-12-08T07:14:41+00:00"
+ "time": "2017-05-22T07:24:03+00:00"
},
{
"name": "sebastian/environment",
@@ -2421,16 +2295,16 @@
},
{
"name": "symfony/browser-kit",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
- "reference": "4386755566fc8d29bddf89694663b0e96cb01e61"
+ "reference": "50cf5bfff540325d81ca2f2dc75ac2a5e446090d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/browser-kit/zipball/4386755566fc8d29bddf89694663b0e96cb01e61",
- "reference": "4386755566fc8d29bddf89694663b0e96cb01e61",
+ "url": "https://api.github.com/repos/symfony/browser-kit/zipball/50cf5bfff540325d81ca2f2dc75ac2a5e446090d",
+ "reference": "50cf5bfff540325d81ca2f2dc75ac2a5e446090d",
"shasum": ""
},
"require": {
@@ -2474,11 +2348,11 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
- "time": "2017-04-12T14:07:15+00:00"
+ "time": "2017-07-12T12:59:33+00:00"
},
{
"name": "symfony/config",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
@@ -2534,16 +2408,16 @@
},
{
"name": "symfony/console",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "2cfcbced8e39e2313ed4da8896fc8c59a56c0d7e"
+ "reference": "c0807a2ca978e64d8945d373a9221a5c35d1a253"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/2cfcbced8e39e2313ed4da8896fc8c59a56c0d7e",
- "reference": "2cfcbced8e39e2313ed4da8896fc8c59a56c0d7e",
+ "url": "https://api.github.com/repos/symfony/console/zipball/c0807a2ca978e64d8945d373a9221a5c35d1a253",
+ "reference": "c0807a2ca978e64d8945d373a9221a5c35d1a253",
"shasum": ""
},
"require": {
@@ -2591,11 +2465,11 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2017-04-26T01:38:53+00:00"
+ "time": "2017-08-27T14:29:03+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@@ -2648,16 +2522,16 @@
},
{
"name": "symfony/debug",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "344f50ce827413b3640bfcb1e37386a67d06ea1f"
+ "reference": "efc9656dcb227e1459905d5aa51e43dfec76e752"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/344f50ce827413b3640bfcb1e37386a67d06ea1f",
- "reference": "344f50ce827413b3640bfcb1e37386a67d06ea1f",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/efc9656dcb227e1459905d5aa51e43dfec76e752",
+ "reference": "efc9656dcb227e1459905d5aa51e43dfec76e752",
"shasum": ""
},
"require": {
@@ -2701,20 +2575,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2017-04-19T19:56:30+00:00"
+ "time": "2017-08-27T14:29:03+00:00"
},
{
"name": "symfony/dom-crawler",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "dd2fc76e011cb480b2d163c3b2deebd3de4471c8"
+ "reference": "2d902344b9902a0189408ab5d9e84fa4b233fcfc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/dd2fc76e011cb480b2d163c3b2deebd3de4471c8",
- "reference": "dd2fc76e011cb480b2d163c3b2deebd3de4471c8",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2d902344b9902a0189408ab5d9e84fa4b233fcfc",
+ "reference": "2d902344b9902a0189408ab5d9e84fa4b233fcfc",
"shasum": ""
},
"require": {
@@ -2757,20 +2631,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
- "time": "2017-04-12T14:07:15+00:00"
+ "time": "2017-08-15T13:30:53+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "7fc8e2b4118ff316550596357325dfd92a51f531"
+ "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7fc8e2b4118ff316550596357325dfd92a51f531",
- "reference": "7fc8e2b4118ff316550596357325dfd92a51f531",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1377400fd641d7d1935981546aaef780ecd5bf6d",
+ "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d",
"shasum": ""
},
"require": {
@@ -2817,20 +2691,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2017-04-26T16:56:54+00:00"
+ "time": "2017-06-02T07:47:27+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "dc40154e26a0116995e4f2f0c71cb9c2fe0775a3"
+ "reference": "714b1036010c354ae2b25d7f9ca27e14e265e9f2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/dc40154e26a0116995e4f2f0c71cb9c2fe0775a3",
- "reference": "dc40154e26a0116995e4f2f0c71cb9c2fe0775a3",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/714b1036010c354ae2b25d7f9ca27e14e265e9f2",
+ "reference": "714b1036010c354ae2b25d7f9ca27e14e265e9f2",
"shasum": ""
},
"require": {
@@ -2866,20 +2740,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2017-04-12T14:07:15+00:00"
+ "time": "2017-07-11T07:12:11+00:00"
},
{
"name": "symfony/finder",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "16d55394b31547e4a8494551b85c9b9915545347"
+ "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/16d55394b31547e4a8494551b85c9b9915545347",
- "reference": "16d55394b31547e4a8494551b85c9b9915545347",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/4f4e84811004e065a3bb5ceeb1d9aa592630f9ad",
+ "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad",
"shasum": ""
},
"require": {
@@ -2915,20 +2789,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-04-12T14:07:15+00:00"
+ "time": "2017-06-01T20:52:29+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.3.0",
+ "version": "v1.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4"
+ "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4",
- "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
+ "reference": "7c8fae0ac1d216eb54349e6a8baa57d515fe8803",
"shasum": ""
},
"require": {
@@ -2940,7 +2814,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.3-dev"
+ "dev-master": "1.5-dev"
}
},
"autoload": {
@@ -2974,11 +2848,11 @@
"portable",
"shim"
],
- "time": "2016-11-14T01:06:16+00:00"
+ "time": "2017-06-14T15:44:48+00:00"
},
{
"name": "symfony/stopwatch",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
@@ -3027,16 +2901,16 @@
},
{
"name": "symfony/yaml",
- "version": "v2.8.20",
+ "version": "v2.8.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "93ccdde79f4b079c7558da4656a3cb1c50c68e02"
+ "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/93ccdde79f4b079c7558da4656a3cb1c50c68e02",
- "reference": "93ccdde79f4b079c7558da4656a3cb1c50c68e02",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5",
+ "reference": "4c29dec8d489c4e37cf87ccd7166cd0b0e6a45c5",
"shasum": ""
},
"require": {
@@ -3072,7 +2946,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2017-05-01T14:31:55+00:00"
+ "time": "2017-06-01T20:52:29+00:00"
}
],
"aliases": [
diff --git a/data/Smarty/templates/admin/products/product_class.tpl b/data/Smarty/templates/admin/products/product_class.tpl
index caf1ba6ce8..fa1b9800e5 100644
--- a/data/Smarty/templates/admin/products/product_class.tpl
+++ b/data/Smarty/templates/admin/products/product_class.tpl
@@ -295,7 +295,7 @@
-
+
diff --git a/data/class/SC_Cache.php b/data/class/SC_Cache.php
index 2be0cf4f48..73d2171078 100644
--- a/data/class/SC_Cache.php
+++ b/data/class/SC_Cache.php
@@ -21,8 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-require DATA_REALDIR . 'module/Cache/Lite.php';
-
/**
* Cache controll using PEAR::Cache_Lite.
*/
diff --git a/data/class/SC_Product.php b/data/class/SC_Product.php
index c5ea95f79e..d8a4e57274 100644
--- a/data/class/SC_Product.php
+++ b/data/class/SC_Product.php
@@ -38,9 +38,9 @@ class SC_Product
public $classCategories = array();
public $stock_find;
/** 規格1クラス名 */
- public $className1 = '';
+ public $className1 = [];
/** 規格2クラス名 */
- public $className2 = '';
+ public $className2 = [];
/** 規格1が設定されている */
public $classCat1_find;
/** 規格2が設定されている */
@@ -404,10 +404,10 @@ public function getProductsClass($productClassId)
// 税込計算
if (!SC_Utils_Ex::isBlank($arrProduct['price01'])) {
- $arrProduct['price01_inctax'] = SC_Helper_TaxRule_Ex::sfCalcIncTax($arrProduct['price01'], $arrProduct['product_id'], $productClassId);
+ $arrProduct['price01_inctax'] = SC_Helper_TaxRule_Ex::sfCalcIncTax($arrProduct['price01'], $arrProduct['product_id'], $productClassId);
}
if (!SC_Utils_Ex::isBlank($arrProduct['price02'])) {
- $arrProduct['price02_inctax'] = SC_Helper_TaxRule_Ex::sfCalcIncTax($arrProduct['price02'], $arrProduct['product_id'], $productClassId);
+ $arrProduct['price02_inctax'] = SC_Helper_TaxRule_Ex::sfCalcIncTax($arrProduct['price02'], $arrProduct['product_id'], $productClassId);
}
return $arrProduct;
@@ -698,7 +698,8 @@ public function getProductDispConditions($tablename = null)
* @param bool $include_hidden
* @return array
*/
- public function getCategoryIds($product_id, $include_hidden = false) {
+ public function getCategoryIds($product_id, $include_hidden = false)
+ {
if ($this->isValidProductId($product_id, $include_hidden)) {
$objQuery =& SC_Query_Ex::getSingletonInstance();
$category_id = $objQuery->getCol('category_id', 'dtb_product_categories', 'product_id = ?', array($product_id));
@@ -718,7 +719,8 @@ public function getCategoryIds($product_id, $include_hidden = false) {
* @param bool $include_deleted
* @return bool
*/
- public function isValidProductId($product_id, $include_hidden = false, $include_deleted = false) {
+ public function isValidProductId($product_id, $include_hidden = false, $include_deleted = false)
+ {
$where = '';
if (!$include_hidden) {
$where .= 'status = 1';
diff --git a/data/class/SC_Query.php b/data/class/SC_Query.php
index c9d0988362..11833dc152 100644
--- a/data/class/SC_Query.php
+++ b/data/class/SC_Query.php
@@ -1040,7 +1040,7 @@ public function execute(&$sth, $arrVal = array())
// #1658 (SC_Query の各種メソッドでプレースホルダの数に誤りがあるとメモリリークが発生する) 対応
// TODO 現状は PEAR 内のバックトレースを抑制することで、メモリーリークの影響を小さくしている。
// 根本的には、そのバックトレースが、どこに居座っているかを特定して、対策すべき。
- $pear_property =& PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
+ $pear_property =& PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
$bak = $pear_property;
$pear_property = true;
diff --git a/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php b/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php
index 1616e4bdea..7e2c5c9d9b 100644
--- a/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php
+++ b/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php
@@ -70,7 +70,8 @@ public function sfChangeMySQL($sql)
$sql = $this->sfChangeTrunc($sql);
// ARRAY_TO_STRINGをGROUP_CONCATに変換する
$sql = $this->sfChangeArrayToString($sql);
-
+ // rank に引用符をつける
+ $sql = $this->sfChangeReservedWords($sql);
return $sql;
}
@@ -342,6 +343,15 @@ public function sfGetCreateIndexDefinition($table, $name, $definition)
return $definition;
}
+ /**
+ * 予約語に引用符を付与する.
+ */
+ public function sfChangeReservedWords($sql)
+ {
+ $changesql = preg_replace('/(^|[^\w])RANK([^\w]|$)/i', '$1`RANK`$2', $sql);
+ return $changesql;
+ }
+
/**
* 擬似表を表すSQL文(FROM 句)を取得する
*
@@ -360,7 +370,11 @@ public function getDummyFromClauseSql()
*/
public function initObjQuery(SC_Query &$objQuery)
{
- $objQuery->exec('SET SESSION storage_engine = InnoDB');
+ if ($objQuery->conn->getConnection()->server_version >= 50705) {
+ $objQuery->exec('SET SESSION default_storage_engine = InnoDB');
+ } else {
+ $objQuery->exec('SET SESSION storage_engine = InnoDB');
+ }
$objQuery->exec("SET SESSION sql_mode = 'ANSI'");
}
}
diff --git a/data/class/helper/SC_Helper_Customer.php b/data/class/helper/SC_Helper_Customer.php
index 8eee97d78b..ef905a8605 100644
--- a/data/class/helper/SC_Helper_Customer.php
+++ b/data/class/helper/SC_Helper_Customer.php
@@ -248,7 +248,7 @@ public function sfGetCustomerData($customer_id, $mask_flg = true)
// 誕生日を年月日に分ける
if (isset($arrForm['birth'])) {
$birth = explode(' ', $arrForm['birth']);
- list($arrForm['year'], $arrForm['month'], $arrForm['day']) = explode('-', $birth[0]);
+ list($arrForm['year'], $arrForm['month'], $arrForm['day']) = array_map("intval",explode('-', $birth[0]));
}
if ($mask_flg) {
diff --git a/data/class/pages/admin/basis/LC_Page_Admin_Basis_Tax.php b/data/class/pages/admin/basis/LC_Page_Admin_Basis_Tax.php
index b3656fbf2b..2cf5c6bd6d 100644
--- a/data/class/pages/admin/basis/LC_Page_Admin_Basis_Tax.php
+++ b/data/class/pages/admin/basis/LC_Page_Admin_Basis_Tax.php
@@ -151,11 +151,11 @@ public function action()
$TaxRule = $objTaxRule->getTaxRuleData($tax_rule_id);
$tmp = explode(" ", $TaxRule['apply_date']);
- $tmp_ymd = explode("-", $tmp[0]);
+ $tmp_ymd = array_map("intval",explode('-', $tmp[0]));
$TaxRule['apply_date_year'] = $tmp_ymd[0];
$TaxRule['apply_date_month'] = $tmp_ymd[1];
$TaxRule['apply_date_day'] = $tmp_ymd[2];
- $tmp_hm = explode(":", $tmp[1]);
+ $tmp_hm = array_map("intval",explode(":", $tmp[1]));
$TaxRule['apply_date_hour'] = $tmp_hm[0];
$TaxRule['apply_date_minutes'] = $tmp_hm[1];
diff --git a/data/class/pages/admin/contents/LC_Page_Admin_Contents.php b/data/class/pages/admin/contents/LC_Page_Admin_Contents.php
index fef419d505..5a44c4e5fe 100644
--- a/data/class/pages/admin/contents/LC_Page_Admin_Contents.php
+++ b/data/class/pages/admin/contents/LC_Page_Admin_Contents.php
@@ -240,7 +240,7 @@ public function checkLinkMethod($link_method)
*/
public function splitNewsDate($news_date)
{
- return explode('-', $news_date);
+ return array_map("intval",explode('-', $news_date));
}
/**
diff --git a/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php b/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php
index 139164e666..f423c4844f 100644
--- a/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php
+++ b/data/class/pages/admin/products/LC_Page_Admin_Products_ProductRank.php
@@ -150,18 +150,17 @@ public function lfRenumber($parent_category_id)
rank =
(
SELECT COUNT(*)
- FROM dtb_product_categories t_in
- WHERE t_in.category_id = dtb_product_categories.category_id
- AND (
- t_in.rank < dtb_product_categories.rank
- OR (
- t_in.rank = dtb_product_categories.rank
- AND t_in.product_id < dtb_product_categories.product_id
- )
+ FROM (SELECT product_id,rank FROM dtb_product_categories WHERE category_id = dtb_product_categories.category_id) t_in
+ WHERE
+ t_in.rank < dtb_product_categories.rank
+ OR (
+ t_in.rank = dtb_product_categories.rank
+ AND t_in.product_id < dtb_product_categories.product_id
)
) + 1
WHERE dtb_product_categories.category_id = ?
__EOS__;
+
$arrRet = $objQuery->query($sql, array($parent_category_id));
return $arrRet;
diff --git a/data/class/pages/admin/total/LC_Page_Admin_Total.php b/data/class/pages/admin/total/LC_Page_Admin_Total.php
index 66cf51dc9d..dd2da5f190 100644
--- a/data/class/pages/admin/total/LC_Page_Admin_Total.php
+++ b/data/class/pages/admin/total/LC_Page_Admin_Total.php
@@ -486,7 +486,7 @@ public function lfGetGraphPng($keyname)
/**
* @param string $col_date
*/
- public function lfGetWhereMember($col_date, $sdate, $edate, $type, $col_member = 'customer_id')
+ public function lfGetWhereMember($col_date, $sdate, $edate, $type = NULL, $col_member = 'customer_id')
{
$where = '';
// 取得日付の指定
diff --git a/data/module/Archive/Tar.php b/data/module/Archive/Tar.php
deleted file mode 100644
index 570b39c05f..0000000000
--- a/data/module/Archive/Tar.php
+++ /dev/null
@@ -1,2422 +0,0 @@
-
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category File_Formats
- * @package Archive_Tar
- * @author Vincent Blavet
- * @copyright 1997-2010 The Authors
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Archive_Tar
- */
-
-require_once 'PEAR.php';
-
-define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
-define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
-
-if (!function_exists('gzopen') && function_exists('gzopen64')) {
- function gzopen($filename, $mode, $use_include_path = 0)
- {
- gzopen64($filename, $mode, $use_include_path);
- }
-}
-
-if (!function_exists('gztell') && function_exists('gztell64')) {
- function gztell($zp)
- {
- gztell64($zp);
- }
-}
-
-if (!function_exists('gzseek') && function_exists('gzseek64')) {
- function gzseek($zp, $offset, $whence = SEEK_SET)
- {
- gzseek64($zp, $offset, $whence);
- }
-}
-
-/**
- * Creates a (compressed) Tar archive
- *
- * @package Archive_Tar
- * @author Vincent Blavet
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version $Revision$
- */
-class Archive_Tar extends PEAR
-{
- /**
- * @var string Name of the Tar
- */
- var $_tarname = '';
-
- /**
- * @var boolean if true, the Tar file will be gzipped
- */
- var $_compress = false;
-
- /**
- * @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2'
- */
- var $_compress_type = 'none';
-
- /**
- * @var string Explode separator
- */
- var $_separator = ' ';
-
- /**
- * @var file descriptor
- */
- var $_file = 0;
-
- /**
- * @var string Local Tar name of a remote Tar (http:// or ftp://)
- */
- var $_temp_tarname = '';
-
- /**
- * @var string regular expression for ignoring files or directories
- */
- var $_ignore_regexp = '';
-
- /**
- * @var object PEAR_Error object
- */
- var $error_object = null;
-
- // {{{ constructor
- /**
- * Archive_Tar Class constructor. This flavour of the constructor only
- * declare a new Archive_Tar object, identifying it by the name of the
- * tar file.
- * If the compress argument is set the tar will be read or created as a
- * gzip or bz2 compressed TAR file.
- *
- * @param string $p_tarname The name of the tar archive to create
- * @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This
- * parameter indicates if gzip, bz2 or lzma2 compression
- * is required. For compatibility reason the
- * boolean value 'true' means 'gz'.
- *
- * @access public
- */
- function Archive_Tar($p_tarname, $p_compress = null)
- {
- if (version_compare(PHP_VERSION, '5.0.0', '<')) {
- $this->PEAR();
- }
- $this->_compress = false;
- $this->_compress_type = 'none';
- if (($p_compress === null) || ($p_compress == '')) {
- if (@file_exists($p_tarname)) {
- if ($fp = @fopen($p_tarname, "rb")) {
- // look for gzip magic cookie
- $data = fread($fp, 2);
- fclose($fp);
- if ($data == "\37\213") {
- $this->_compress = true;
- $this->_compress_type = 'gz';
- // No sure it's enought for a magic code ....
- } elseif ($data == "BZ") {
- $this->_compress = true;
- $this->_compress_type = 'bz2';
- } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') {
- $this->_compress = true;
- $this->_compress_type = 'lzma2';
- }
- }
- } else {
- // probably a remote file or some file accessible
- // through a stream interface
- if (substr($p_tarname, -2) == 'gz') {
- $this->_compress = true;
- $this->_compress_type = 'gz';
- } elseif ((substr($p_tarname, -3) == 'bz2') ||
- (substr($p_tarname, -2) == 'bz')
- ) {
- $this->_compress = true;
- $this->_compress_type = 'bz2';
- } else {
- if (substr($p_tarname, -2) == 'xz') {
- $this->_compress = true;
- $this->_compress_type = 'lzma2';
- }
- }
- }
- } else {
- if (($p_compress === true) || ($p_compress == 'gz')) {
- $this->_compress = true;
- $this->_compress_type = 'gz';
- } else {
- if ($p_compress == 'bz2') {
- $this->_compress = true;
- $this->_compress_type = 'bz2';
- } else {
- if ($p_compress == 'lzma2') {
- $this->_compress = true;
- $this->_compress_type = 'lzma2';
- } else {
- $this->_error(
- "Unsupported compression type '$p_compress'\n" .
- "Supported types are 'gz', 'bz2' and 'lzma2'.\n"
- );
- return false;
- }
- }
- }
- }
- $this->_tarname = $p_tarname;
- if ($this->_compress) { // assert zlib or bz2 or xz extension support
- if ($this->_compress_type == 'gz') {
- $extname = 'zlib';
- } else {
- if ($this->_compress_type == 'bz2') {
- $extname = 'bz2';
- } else {
- if ($this->_compress_type == 'lzma2') {
- $extname = 'xz';
- }
- }
- }
-
- if (!extension_loaded($extname)) {
- PEAR::loadExtension($extname);
- }
- if (!extension_loaded($extname)) {
- $this->_error(
- "The extension '$extname' couldn't be found.\n" .
- "Please make sure your version of PHP was built " .
- "with '$extname' support.\n"
- );
- return false;
- }
- }
- }
-
- // }}}
-
- // {{{ destructor
- function _Archive_Tar()
- {
- $this->_close();
- // ----- Look for a local copy to delete
- if ($this->_temp_tarname != '') {
- @unlink($this->_temp_tarname);
- }
- $this->_PEAR();
- }
-
- // }}}
-
- // {{{ PHP5-compatible destructor
- function __destruct()
- {
- $this->_Archive_Tar();
- }
-
- // }}}
-
- // {{{ create()
- /**
- * This method creates the archive file and add the files / directories
- * that are listed in $p_filelist.
- * If a file with the same name exist and is writable, it is replaced
- * by the new tar.
- * The method return false and a PEAR error text.
- * The $p_filelist parameter can be an array of string, each string
- * representing a filename or a directory name with their path if
- * needed. It can also be a single string with names separated by a
- * single blank.
- * For each directory added in the archive, the files and
- * sub-directories are also added.
- * See also createModify() method for more details.
- *
- * @param array $p_filelist An array of filenames and directory names, or a
- * single string with names separated by a single
- * blank space.
- *
- * @return true on success, false on error.
- * @see createModify()
- * @access public
- */
- function create($p_filelist)
- {
- return $this->createModify($p_filelist, '', '');
- }
-
- // }}}
-
- // {{{ add()
- /**
- * This method add the files / directories that are listed in $p_filelist in
- * the archive. If the archive does not exist it is created.
- * The method return false and a PEAR error text.
- * The files and directories listed are only added at the end of the archive,
- * even if a file with the same name is already archived.
- * See also createModify() method for more details.
- *
- * @param array $p_filelist An array of filenames and directory names, or a
- * single string with names separated by a single
- * blank space.
- *
- * @return true on success, false on error.
- * @see createModify()
- * @access public
- */
- function add($p_filelist)
- {
- return $this->addModify($p_filelist, '', '');
- }
-
- // }}}
-
- // {{{ extract()
- function extract($p_path = '', $p_preserve = false)
- {
- return $this->extractModify($p_path, '', $p_preserve);
- }
-
- // }}}
-
- // {{{ listContent()
- function listContent()
- {
- $v_list_detail = array();
-
- if ($this->_openRead()) {
- if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
- unset($v_list_detail);
- $v_list_detail = 0;
- }
- $this->_close();
- }
-
- return $v_list_detail;
- }
-
- // }}}
-
- // {{{ createModify()
- /**
- * This method creates the archive file and add the files / directories
- * that are listed in $p_filelist.
- * If the file already exists and is writable, it is replaced by the
- * new tar. It is a create and not an add. If the file exists and is
- * read-only or is a directory it is not replaced. The method return
- * false and a PEAR error text.
- * The $p_filelist parameter can be an array of string, each string
- * representing a filename or a directory name with their path if
- * needed. It can also be a single string with names separated by a
- * single blank.
- * The path indicated in $p_remove_dir will be removed from the
- * memorized path of each file / directory listed when this path
- * exists. By default nothing is removed (empty path '')
- * The path indicated in $p_add_dir will be added at the beginning of
- * the memorized path of each file / directory listed. However it can
- * be set to empty ''. The adding of a path is done after the removing
- * of path.
- * The path add/remove ability enables the user to prepare an archive
- * for extraction in a different path than the origin files are.
- * See also addModify() method for file adding properties.
- *
- * @param array $p_filelist An array of filenames and directory names,
- * or a single string with names separated by
- * a single blank space.
- * @param string $p_add_dir A string which contains a path to be added
- * to the memorized path of each element in
- * the list.
- * @param string $p_remove_dir A string which contains a path to be
- * removed from the memorized path of each
- * element in the list, when relevant.
- *
- * @return boolean true on success, false on error.
- * @access public
- * @see addModify()
- */
- function createModify($p_filelist, $p_add_dir, $p_remove_dir = '')
- {
- $v_result = true;
-
- if (!$this->_openWrite()) {
- return false;
- }
-
- if ($p_filelist != '') {
- if (is_array($p_filelist)) {
- $v_list = $p_filelist;
- } elseif (is_string($p_filelist)) {
- $v_list = explode($this->_separator, $p_filelist);
- } else {
- $this->_cleanFile();
- $this->_error('Invalid file list');
- return false;
- }
-
- $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
- }
-
- if ($v_result) {
- $this->_writeFooter();
- $this->_close();
- } else {
- $this->_cleanFile();
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ addModify()
- /**
- * This method add the files / directories listed in $p_filelist at the
- * end of the existing archive. If the archive does not yet exists it
- * is created.
- * The $p_filelist parameter can be an array of string, each string
- * representing a filename or a directory name with their path if
- * needed. It can also be a single string with names separated by a
- * single blank.
- * The path indicated in $p_remove_dir will be removed from the
- * memorized path of each file / directory listed when this path
- * exists. By default nothing is removed (empty path '')
- * The path indicated in $p_add_dir will be added at the beginning of
- * the memorized path of each file / directory listed. However it can
- * be set to empty ''. The adding of a path is done after the removing
- * of path.
- * The path add/remove ability enables the user to prepare an archive
- * for extraction in a different path than the origin files are.
- * If a file/dir is already in the archive it will only be added at the
- * end of the archive. There is no update of the existing archived
- * file/dir. However while extracting the archive, the last file will
- * replace the first one. This results in a none optimization of the
- * archive size.
- * If a file/dir does not exist the file/dir is ignored. However an
- * error text is send to PEAR error.
- * If a file/dir is not readable the file/dir is ignored. However an
- * error text is send to PEAR error.
- *
- * @param array $p_filelist An array of filenames and directory
- * names, or a single string with names
- * separated by a single blank space.
- * @param string $p_add_dir A string which contains a path to be
- * added to the memorized path of each
- * element in the list.
- * @param string $p_remove_dir A string which contains a path to be
- * removed from the memorized path of
- * each element in the list, when
- * relevant.
- *
- * @return true on success, false on error.
- * @access public
- */
- function addModify($p_filelist, $p_add_dir, $p_remove_dir = '')
- {
- $v_result = true;
-
- if (!$this->_isArchive()) {
- $v_result = $this->createModify(
- $p_filelist,
- $p_add_dir,
- $p_remove_dir
- );
- } else {
- if (is_array($p_filelist)) {
- $v_list = $p_filelist;
- } elseif (is_string($p_filelist)) {
- $v_list = explode($this->_separator, $p_filelist);
- } else {
- $this->_error('Invalid file list');
- return false;
- }
-
- $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ addString()
- /**
- * This method add a single string as a file at the
- * end of the existing archive. If the archive does not yet exists it
- * is created.
- *
- * @param string $p_filename A string which contains the full
- * filename path that will be associated
- * with the string.
- * @param string $p_string The content of the file added in
- * the archive.
- * @param int $p_datetime A custom date/time (unix timestamp)
- * for the file (optional).
- * @param array $p_params An array of optional params:
- * stamp => the datetime (replaces
- * datetime above if it exists)
- * mode => the permissions on the
- * file (600 by default)
- * type => is this a link? See the
- * tar specification for details.
- * (default = regular file)
- * uid => the user ID of the file
- * (default = 0 = root)
- * gid => the group ID of the file
- * (default = 0 = root)
- *
- * @return true on success, false on error.
- * @access public
- */
- function addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
- {
- $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
- $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
- $p_type = @$p_params["type"] ? $p_params["type"] : "";
- $p_uid = @$p_params["uid"] ? $p_params["uid"] : "";
- $p_gid = @$p_params["gid"] ? $p_params["gid"] : "";
- $v_result = true;
-
- if (!$this->_isArchive()) {
- if (!$this->_openWrite()) {
- return false;
- }
- $this->_close();
- }
-
- if (!$this->_openAppend()) {
- return false;
- }
-
- // Need to check the get back to the temporary file ? ....
- $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params);
-
- $this->_writeFooter();
-
- $this->_close();
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ extractModify()
- /**
- * This method extract all the content of the archive in the directory
- * indicated by $p_path. When relevant the memorized path of the
- * files/dir can be modified by removing the $p_remove_path path at the
- * beginning of the file/dir path.
- * While extracting a file, if the directory path does not exists it is
- * created.
- * While extracting a file, if the file already exists it is replaced
- * without looking for last modification date.
- * While extracting a file, if the file already exists and is write
- * protected, the extraction is aborted.
- * While extracting a file, if a directory with the same name already
- * exists, the extraction is aborted.
- * While extracting a directory, if a file with the same name already
- * exists, the extraction is aborted.
- * While extracting a file/directory if the destination directory exist
- * and is write protected, or does not exist but can not be created,
- * the extraction is aborted.
- * If after extraction an extracted file does not show the correct
- * stored file size, the extraction is aborted.
- * When the extraction is aborted, a PEAR error text is set and false
- * is returned. However the result can be a partial extraction that may
- * need to be manually cleaned.
- *
- * @param string $p_path The path of the directory where the
- * files/dir need to by extracted.
- * @param string $p_remove_path Part of the memorized path that can be
- * removed if present at the beginning of
- * the file/dir path.
- * @param boolean $p_preserve Preserve user/group ownership of files
- *
- * @return boolean true on success, false on error.
- * @access public
- * @see extractList()
- */
- function extractModify($p_path, $p_remove_path, $p_preserve = false)
- {
- $v_result = true;
- $v_list_detail = array();
-
- if ($v_result = $this->_openRead()) {
- $v_result = $this->_extractList(
- $p_path,
- $v_list_detail,
- "complete",
- 0,
- $p_remove_path,
- $p_preserve
- );
- $this->_close();
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ extractInString()
- /**
- * This method extract from the archive one file identified by $p_filename.
- * The return value is a string with the file content, or NULL on error.
- *
- * @param string $p_filename The path of the file to extract in a string.
- *
- * @return a string with the file content or NULL.
- * @access public
- */
- function extractInString($p_filename)
- {
- if ($this->_openRead()) {
- $v_result = $this->_extractInString($p_filename);
- $this->_close();
- } else {
- $v_result = null;
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ extractList()
- /**
- * This method extract from the archive only the files indicated in the
- * $p_filelist. These files are extracted in the current directory or
- * in the directory indicated by the optional $p_path parameter.
- * If indicated the $p_remove_path can be used in the same way as it is
- * used in extractModify() method.
- *
- * @param array $p_filelist An array of filenames and directory names,
- * or a single string with names separated
- * by a single blank space.
- * @param string $p_path The path of the directory where the
- * files/dir need to by extracted.
- * @param string $p_remove_path Part of the memorized path that can be
- * removed if present at the beginning of
- * the file/dir path.
- * @param boolean $p_preserve Preserve user/group ownership of files
- *
- * @return true on success, false on error.
- * @access public
- * @see extractModify()
- */
- function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false)
- {
- $v_result = true;
- $v_list_detail = array();
-
- if (is_array($p_filelist)) {
- $v_list = $p_filelist;
- } elseif (is_string($p_filelist)) {
- $v_list = explode($this->_separator, $p_filelist);
- } else {
- $this->_error('Invalid string list');
- return false;
- }
-
- if ($v_result = $this->_openRead()) {
- $v_result = $this->_extractList(
- $p_path,
- $v_list_detail,
- "partial",
- $v_list,
- $p_remove_path,
- $p_preserve
- );
- $this->_close();
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ setAttribute()
- /**
- * This method set specific attributes of the archive. It uses a variable
- * list of parameters, in the format attribute code + attribute values :
- * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
- *
- * @param mixed $argv variable list of attributes and values
- *
- * @return true on success, false on error.
- * @access public
- */
- function setAttribute()
- {
- $v_result = true;
-
- // ----- Get the number of variable list of arguments
- if (($v_size = func_num_args()) == 0) {
- return true;
- }
-
- // ----- Get the arguments
- $v_att_list = & func_get_args();
-
- // ----- Read the attributes
- $i = 0;
- while ($i < $v_size) {
-
- // ----- Look for next option
- switch ($v_att_list[$i]) {
- // ----- Look for options that request a string value
- case ARCHIVE_TAR_ATT_SEPARATOR :
- // ----- Check the number of parameters
- if (($i + 1) >= $v_size) {
- $this->_error(
- 'Invalid number of parameters for '
- . 'attribute ARCHIVE_TAR_ATT_SEPARATOR'
- );
- return false;
- }
-
- // ----- Get the value
- $this->_separator = $v_att_list[$i + 1];
- $i++;
- break;
-
- default :
- $this->_error('Unknow attribute code ' . $v_att_list[$i] . '');
- return false;
- }
-
- // ----- Next attribute
- $i++;
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ setIgnoreRegexp()
- /**
- * This method sets the regular expression for ignoring files and directories
- * at import, for example:
- * $arch->setIgnoreRegexp("#CVS|\.svn#");
- *
- * @param string $regexp regular expression defining which files or directories to ignore
- *
- * @access public
- */
- function setIgnoreRegexp($regexp)
- {
- $this->_ignore_regexp = $regexp;
- }
-
- // }}}
-
- // {{{ setIgnoreList()
- /**
- * This method sets the regular expression for ignoring all files and directories
- * matching the filenames in the array list at import, for example:
- * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
- *
- * @param array $list a list of file or directory names to ignore
- *
- * @access public
- */
- function setIgnoreList($list)
- {
- $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
- $regexp = '#/' . join('$|/', $list) . '#';
- $this->setIgnoreRegexp($regexp);
- }
-
- // }}}
-
- // {{{ _error()
- function _error($p_message)
- {
- $this->error_object = & $this->raiseError($p_message);
- }
-
- // }}}
-
- // {{{ _warning()
- function _warning($p_message)
- {
- $this->error_object = & $this->raiseError($p_message);
- }
-
- // }}}
-
- // {{{ _isArchive()
- function _isArchive($p_filename = null)
- {
- if ($p_filename == null) {
- $p_filename = $this->_tarname;
- }
- clearstatcache();
- return @is_file($p_filename) && !@is_link($p_filename);
- }
-
- // }}}
-
- // {{{ _openWrite()
- function _openWrite()
- {
- if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
- $this->_file = @gzopen($this->_tarname, "wb9");
- } else {
- if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
- $this->_file = @bzopen($this->_tarname, "w");
- } else {
- if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
- $this->_file = @xzopen($this->_tarname, 'w');
- } else {
- if ($this->_compress_type == 'none') {
- $this->_file = @fopen($this->_tarname, "wb");
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- return false;
- }
- }
- }
- }
-
- if ($this->_file == 0) {
- $this->_error(
- 'Unable to open in write mode \''
- . $this->_tarname . '\''
- );
- return false;
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _openRead()
- function _openRead()
- {
- if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
-
- // ----- Look if a local copy need to be done
- if ($this->_temp_tarname == '') {
- $this->_temp_tarname = uniqid('tar') . '.tmp';
- if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
- $this->_error(
- 'Unable to open in read mode \''
- . $this->_tarname . '\''
- );
- $this->_temp_tarname = '';
- return false;
- }
- if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
- $this->_error(
- 'Unable to open in write mode \''
- . $this->_temp_tarname . '\''
- );
- $this->_temp_tarname = '';
- return false;
- }
- while ($v_data = @fread($v_file_from, 1024)) {
- @fwrite($v_file_to, $v_data);
- }
- @fclose($v_file_from);
- @fclose($v_file_to);
- }
-
- // ----- File to open if the local copy
- $v_filename = $this->_temp_tarname;
-
- } else // ----- File to open if the normal Tar file
- {
- $v_filename = $this->_tarname;
- }
-
- if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
- $this->_file = @gzopen($v_filename, "rb");
- } else {
- if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
- $this->_file = @bzopen($v_filename, "r");
- } else {
- if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
- $this->_file = @xzopen($v_filename, "r");
- } else {
- if ($this->_compress_type == 'none') {
- $this->_file = @fopen($v_filename, "rb");
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- return false;
- }
- }
- }
- }
-
- if ($this->_file == 0) {
- $this->_error('Unable to open in read mode \'' . $v_filename . '\'');
- return false;
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _openReadWrite()
- function _openReadWrite()
- {
- if ($this->_compress_type == 'gz') {
- $this->_file = @gzopen($this->_tarname, "r+b");
- } else {
- if ($this->_compress_type == 'bz2') {
- $this->_error(
- 'Unable to open bz2 in read/write mode \''
- . $this->_tarname . '\' (limitation of bz2 extension)'
- );
- return false;
- } else {
- if ($this->_compress_type == 'lzma2') {
- $this->_error(
- 'Unable to open lzma2 in read/write mode \''
- . $this->_tarname . '\' (limitation of lzma2 extension)'
- );
- return false;
- } else {
- if ($this->_compress_type == 'none') {
- $this->_file = @fopen($this->_tarname, "r+b");
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- return false;
- }
- }
- }
- }
-
- if ($this->_file == 0) {
- $this->_error(
- 'Unable to open in read/write mode \''
- . $this->_tarname . '\''
- );
- return false;
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _close()
- function _close()
- {
- //if (isset($this->_file)) {
- if (is_resource($this->_file)) {
- if ($this->_compress_type == 'gz') {
- @gzclose($this->_file);
- } else {
- if ($this->_compress_type == 'bz2') {
- @bzclose($this->_file);
- } else {
- if ($this->_compress_type == 'lzma2') {
- @xzclose($this->_file);
- } else {
- if ($this->_compress_type == 'none') {
- @fclose($this->_file);
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- }
- }
- }
- }
-
- $this->_file = 0;
- }
-
- // ----- Look if a local copy need to be erase
- // Note that it might be interesting to keep the url for a time : ToDo
- if ($this->_temp_tarname != '') {
- @unlink($this->_temp_tarname);
- $this->_temp_tarname = '';
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _cleanFile()
- function _cleanFile()
- {
- $this->_close();
-
- // ----- Look for a local copy
- if ($this->_temp_tarname != '') {
- // ----- Remove the local copy but not the remote tarname
- @unlink($this->_temp_tarname);
- $this->_temp_tarname = '';
- } else {
- // ----- Remove the local tarname file
- @unlink($this->_tarname);
- }
- $this->_tarname = '';
-
- return true;
- }
-
- // }}}
-
- // {{{ _writeBlock()
- function _writeBlock($p_binary_data, $p_len = null)
- {
- if (is_resource($this->_file)) {
- if ($p_len === null) {
- if ($this->_compress_type == 'gz') {
- @gzputs($this->_file, $p_binary_data);
- } else {
- if ($this->_compress_type == 'bz2') {
- @bzwrite($this->_file, $p_binary_data);
- } else {
- if ($this->_compress_type == 'lzma2') {
- @xzwrite($this->_file, $p_binary_data);
- } else {
- if ($this->_compress_type == 'none') {
- @fputs($this->_file, $p_binary_data);
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- }
- }
- }
- }
- } else {
- if ($this->_compress_type == 'gz') {
- @gzputs($this->_file, $p_binary_data, $p_len);
- } else {
- if ($this->_compress_type == 'bz2') {
- @bzwrite($this->_file, $p_binary_data, $p_len);
- } else {
- if ($this->_compress_type == 'lzma2') {
- @xzwrite($this->_file, $p_binary_data, $p_len);
- } else {
- if ($this->_compress_type == 'none') {
- @fputs($this->_file, $p_binary_data, $p_len);
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- }
- }
- }
- }
-
- }
- }
- return true;
- }
-
- // }}}
-
- // {{{ _readBlock()
- function _readBlock()
- {
- $v_block = null;
- if (is_resource($this->_file)) {
- if ($this->_compress_type == 'gz') {
- $v_block = @gzread($this->_file, 512);
- } else {
- if ($this->_compress_type == 'bz2') {
- $v_block = @bzread($this->_file, 512);
- } else {
- if ($this->_compress_type == 'lzma2') {
- $v_block = @xzread($this->_file, 512);
- } else {
- if ($this->_compress_type == 'none') {
- $v_block = @fread($this->_file, 512);
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- }
- }
- }
- }
- }
- return $v_block;
- }
-
- // }}}
-
- // {{{ _jumpBlock()
- function _jumpBlock($p_len = null)
- {
- if (is_resource($this->_file)) {
- if ($p_len === null) {
- $p_len = 1;
- }
-
- if ($this->_compress_type == 'gz') {
- @gzseek($this->_file, gztell($this->_file) + ($p_len * 512));
- } else {
- if ($this->_compress_type == 'bz2') {
- // ----- Replace missing bztell() and bzseek()
- for ($i = 0; $i < $p_len; $i++) {
- $this->_readBlock();
- }
- } else {
- if ($this->_compress_type == 'lzma2') {
- // ----- Replace missing xztell() and xzseek()
- for ($i = 0; $i < $p_len; $i++) {
- $this->_readBlock();
- }
- } else {
- if ($this->_compress_type == 'none') {
- @fseek($this->_file, $p_len * 512, SEEK_CUR);
- } else {
- $this->_error(
- 'Unknown or missing compression type ('
- . $this->_compress_type . ')'
- );
- }
- }
- }
- }
-
- }
- return true;
- }
-
- // }}}
-
- // {{{ _writeFooter()
- function _writeFooter()
- {
- if (is_resource($this->_file)) {
- // ----- Write the last 0 filled block for end of archive
- $v_binary_data = pack('a1024', '');
- $this->_writeBlock($v_binary_data);
- }
- return true;
- }
-
- // }}}
-
- // {{{ _addList()
- function _addList($p_list, $p_add_dir, $p_remove_dir)
- {
- $v_result = true;
- $v_header = array();
-
- // ----- Remove potential windows directory separator
- $p_add_dir = $this->_translateWinPath($p_add_dir);
- $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
-
- if (!$this->_file) {
- $this->_error('Invalid file descriptor');
- return false;
- }
-
- if (sizeof($p_list) == 0) {
- return true;
- }
-
- foreach ($p_list as $v_filename) {
- if (!$v_result) {
- break;
- }
-
- // ----- Skip the current tar name
- if ($v_filename == $this->_tarname) {
- continue;
- }
-
- if ($v_filename == '') {
- continue;
- }
-
- // ----- ignore files and directories matching the ignore regular expression
- if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) {
- $this->_warning("File '$v_filename' ignored");
- continue;
- }
-
- if (!file_exists($v_filename) && !is_link($v_filename)) {
- $this->_warning("File '$v_filename' does not exist");
- continue;
- }
-
- // ----- Add the file or directory header
- if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) {
- return false;
- }
-
- if (@is_dir($v_filename) && !@is_link($v_filename)) {
- if (!($p_hdir = opendir($v_filename))) {
- $this->_warning("Directory '$v_filename' can not be read");
- continue;
- }
- while (false !== ($p_hitem = readdir($p_hdir))) {
- if (($p_hitem != '.') && ($p_hitem != '..')) {
- if ($v_filename != ".") {
- $p_temp_list[0] = $v_filename . '/' . $p_hitem;
- } else {
- $p_temp_list[0] = $p_hitem;
- }
-
- $v_result = $this->_addList(
- $p_temp_list,
- $p_add_dir,
- $p_remove_dir
- );
- }
- }
-
- unset($p_temp_list);
- unset($p_hdir);
- unset($p_hitem);
- }
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ _addFile()
- function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null)
- {
- if (!$this->_file) {
- $this->_error('Invalid file descriptor');
- return false;
- }
-
- if ($p_filename == '') {
- $this->_error('Invalid file name');
- return false;
- }
-
- if (is_null($v_stored_filename)) {
- // ----- Calculate the stored filename
- $p_filename = $this->_translateWinPath($p_filename, false);;
- $v_stored_filename = $p_filename;
-
- if (strcmp($p_filename, $p_remove_dir) == 0) {
- return true;
- }
-
- if ($p_remove_dir != '') {
- if (substr($p_remove_dir, -1) != '/') {
- $p_remove_dir .= '/';
- }
-
- if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) {
- $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
- }
- }
-
- $v_stored_filename = $this->_translateWinPath($v_stored_filename);
- if ($p_add_dir != '') {
- if (substr($p_add_dir, -1) == '/') {
- $v_stored_filename = $p_add_dir . $v_stored_filename;
- } else {
- $v_stored_filename = $p_add_dir . '/' . $v_stored_filename;
- }
- }
-
- $v_stored_filename = $this->_pathReduction($v_stored_filename);
- }
-
- if ($this->_isArchive($p_filename)) {
- if (($v_file = @fopen($p_filename, "rb")) == 0) {
- $this->_warning(
- "Unable to open file '" . $p_filename
- . "' in binary read mode"
- );
- return true;
- }
-
- if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
- return false;
- }
-
- while (($v_buffer = fread($v_file, 512)) != '') {
- $v_binary_data = pack("a512", "$v_buffer");
- $this->_writeBlock($v_binary_data);
- }
-
- fclose($v_file);
-
- } else {
- // ----- Only header for dir
- if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
- return false;
- }
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _addString()
- function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
- {
- $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
- $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
- $p_type = @$p_params["type"] ? $p_params["type"] : "";
- $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0;
- $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0;
- if (!$this->_file) {
- $this->_error('Invalid file descriptor');
- return false;
- }
-
- if ($p_filename == '') {
- $this->_error('Invalid file name');
- return false;
- }
-
- // ----- Calculate the stored filename
- $p_filename = $this->_translateWinPath($p_filename, false);;
-
- // ----- If datetime is not specified, set current time
- if ($p_datetime === false) {
- $p_datetime = time();
- }
-
- if (!$this->_writeHeaderBlock(
- $p_filename,
- strlen($p_string),
- $p_stamp,
- $p_mode,
- $p_type,
- $p_uid,
- $p_gid
- )
- ) {
- return false;
- }
-
- $i = 0;
- while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') {
- $v_binary_data = pack("a512", $v_buffer);
- $this->_writeBlock($v_binary_data);
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _writeHeader()
- function _writeHeader($p_filename, $p_stored_filename)
- {
- if ($p_stored_filename == '') {
- $p_stored_filename = $p_filename;
- }
- $v_reduce_filename = $this->_pathReduction($p_stored_filename);
-
- if (strlen($v_reduce_filename) > 99) {
- if (!$this->_writeLongHeader($v_reduce_filename)) {
- return false;
- }
- }
-
- $v_info = lstat($p_filename);
- $v_uid = sprintf("%07s", DecOct($v_info[4]));
- $v_gid = sprintf("%07s", DecOct($v_info[5]));
- $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
-
- $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
-
- $v_linkname = '';
-
- if (@is_link($p_filename)) {
- $v_typeflag = '2';
- $v_linkname = readlink($p_filename);
- $v_size = sprintf("%011s", DecOct(0));
- } elseif (@is_dir($p_filename)) {
- $v_typeflag = "5";
- $v_size = sprintf("%011s", DecOct(0));
- } else {
- $v_typeflag = '0';
- clearstatcache();
- $v_size = sprintf("%011s", DecOct($v_info['size']));
- }
-
- $v_magic = 'ustar ';
-
- $v_version = ' ';
-
- if (function_exists('posix_getpwuid')) {
- $userinfo = posix_getpwuid($v_info[4]);
- $groupinfo = posix_getgrgid($v_info[5]);
-
- $v_uname = $userinfo['name'];
- $v_gname = $groupinfo['name'];
- } else {
- $v_uname = '';
- $v_gname = '';
- }
-
- $v_devmajor = '';
-
- $v_devminor = '';
-
- $v_prefix = '';
-
- $v_binary_data_first = pack(
- "a100a8a8a8a12a12",
- $v_reduce_filename,
- $v_perms,
- $v_uid,
- $v_gid,
- $v_size,
- $v_mtime
- );
- $v_binary_data_last = pack(
- "a1a100a6a2a32a32a8a8a155a12",
- $v_typeflag,
- $v_linkname,
- $v_magic,
- $v_version,
- $v_uname,
- $v_gname,
- $v_devmajor,
- $v_devminor,
- $v_prefix,
- ''
- );
-
- // ----- Calculate the checksum
- $v_checksum = 0;
- // ..... First part of the header
- for ($i = 0; $i < 148; $i++) {
- $v_checksum += ord(substr($v_binary_data_first, $i, 1));
- }
- // ..... Ignore the checksum value and replace it by ' ' (space)
- for ($i = 148; $i < 156; $i++) {
- $v_checksum += ord(' ');
- }
- // ..... Last part of the header
- for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
- $v_checksum += ord(substr($v_binary_data_last, $j, 1));
- }
-
- // ----- Write the first 148 bytes of the header in the archive
- $this->_writeBlock($v_binary_data_first, 148);
-
- // ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
- $v_binary_data = pack("a8", $v_checksum);
- $this->_writeBlock($v_binary_data, 8);
-
- // ----- Write the last 356 bytes of the header in the archive
- $this->_writeBlock($v_binary_data_last, 356);
-
- return true;
- }
-
- // }}}
-
- // {{{ _writeHeaderBlock()
- function _writeHeaderBlock(
- $p_filename,
- $p_size,
- $p_mtime = 0,
- $p_perms = 0,
- $p_type = '',
- $p_uid = 0,
- $p_gid = 0
- ) {
- $p_filename = $this->_pathReduction($p_filename);
-
- if (strlen($p_filename) > 99) {
- if (!$this->_writeLongHeader($p_filename)) {
- return false;
- }
- }
-
- if ($p_type == "5") {
- $v_size = sprintf("%011s", DecOct(0));
- } else {
- $v_size = sprintf("%011s", DecOct($p_size));
- }
-
- $v_uid = sprintf("%07s", DecOct($p_uid));
- $v_gid = sprintf("%07s", DecOct($p_gid));
- $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
-
- $v_mtime = sprintf("%11s", DecOct($p_mtime));
-
- $v_linkname = '';
-
- $v_magic = 'ustar ';
-
- $v_version = ' ';
-
- if (function_exists('posix_getpwuid')) {
- $userinfo = posix_getpwuid($p_uid);
- $groupinfo = posix_getgrgid($p_gid);
-
- $v_uname = $userinfo['name'];
- $v_gname = $groupinfo['name'];
- } else {
- $v_uname = '';
- $v_gname = '';
- }
-
- $v_devmajor = '';
-
- $v_devminor = '';
-
- $v_prefix = '';
-
- $v_binary_data_first = pack(
- "a100a8a8a8a12A12",
- $p_filename,
- $v_perms,
- $v_uid,
- $v_gid,
- $v_size,
- $v_mtime
- );
- $v_binary_data_last = pack(
- "a1a100a6a2a32a32a8a8a155a12",
- $p_type,
- $v_linkname,
- $v_magic,
- $v_version,
- $v_uname,
- $v_gname,
- $v_devmajor,
- $v_devminor,
- $v_prefix,
- ''
- );
-
- // ----- Calculate the checksum
- $v_checksum = 0;
- // ..... First part of the header
- for ($i = 0; $i < 148; $i++) {
- $v_checksum += ord(substr($v_binary_data_first, $i, 1));
- }
- // ..... Ignore the checksum value and replace it by ' ' (space)
- for ($i = 148; $i < 156; $i++) {
- $v_checksum += ord(' ');
- }
- // ..... Last part of the header
- for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
- $v_checksum += ord(substr($v_binary_data_last, $j, 1));
- }
-
- // ----- Write the first 148 bytes of the header in the archive
- $this->_writeBlock($v_binary_data_first, 148);
-
- // ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
- $v_binary_data = pack("a8", $v_checksum);
- $this->_writeBlock($v_binary_data, 8);
-
- // ----- Write the last 356 bytes of the header in the archive
- $this->_writeBlock($v_binary_data_last, 356);
-
- return true;
- }
-
- // }}}
-
- // {{{ _writeLongHeader()
- function _writeLongHeader($p_filename)
- {
- $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
-
- $v_typeflag = 'L';
-
- $v_linkname = '';
-
- $v_magic = '';
-
- $v_version = '';
-
- $v_uname = '';
-
- $v_gname = '';
-
- $v_devmajor = '';
-
- $v_devminor = '';
-
- $v_prefix = '';
-
- $v_binary_data_first = pack(
- "a100a8a8a8a12a12",
- '././@LongLink',
- 0,
- 0,
- 0,
- $v_size,
- 0
- );
- $v_binary_data_last = pack(
- "a1a100a6a2a32a32a8a8a155a12",
- $v_typeflag,
- $v_linkname,
- $v_magic,
- $v_version,
- $v_uname,
- $v_gname,
- $v_devmajor,
- $v_devminor,
- $v_prefix,
- ''
- );
-
- // ----- Calculate the checksum
- $v_checksum = 0;
- // ..... First part of the header
- for ($i = 0; $i < 148; $i++) {
- $v_checksum += ord(substr($v_binary_data_first, $i, 1));
- }
- // ..... Ignore the checksum value and replace it by ' ' (space)
- for ($i = 148; $i < 156; $i++) {
- $v_checksum += ord(' ');
- }
- // ..... Last part of the header
- for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
- $v_checksum += ord(substr($v_binary_data_last, $j, 1));
- }
-
- // ----- Write the first 148 bytes of the header in the archive
- $this->_writeBlock($v_binary_data_first, 148);
-
- // ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
- $v_binary_data = pack("a8", $v_checksum);
- $this->_writeBlock($v_binary_data, 8);
-
- // ----- Write the last 356 bytes of the header in the archive
- $this->_writeBlock($v_binary_data_last, 356);
-
- // ----- Write the filename as content of the block
- $i = 0;
- while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') {
- $v_binary_data = pack("a512", "$v_buffer");
- $this->_writeBlock($v_binary_data);
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _readHeader()
- function _readHeader($v_binary_data, &$v_header)
- {
- if (strlen($v_binary_data) == 0) {
- $v_header['filename'] = '';
- return true;
- }
-
- if (strlen($v_binary_data) != 512) {
- $v_header['filename'] = '';
- $this->_error('Invalid block size : ' . strlen($v_binary_data));
- return false;
- }
-
- if (!is_array($v_header)) {
- $v_header = array();
- }
- // ----- Calculate the checksum
- $v_checksum = 0;
- // ..... First part of the header
- for ($i = 0; $i < 148; $i++) {
- $v_checksum += ord(substr($v_binary_data, $i, 1));
- }
- // ..... Ignore the checksum value and replace it by ' ' (space)
- for ($i = 148; $i < 156; $i++) {
- $v_checksum += ord(' ');
- }
- // ..... Last part of the header
- for ($i = 156; $i < 512; $i++) {
- $v_checksum += ord(substr($v_binary_data, $i, 1));
- }
-
- if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
- $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
- "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
- "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
- } else {
- $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
- "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
- "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
- }
- $v_data = unpack($fmt, $v_binary_data);
-
- if (strlen($v_data["prefix"]) > 0) {
- $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
- }
-
- // ----- Extract the checksum
- $v_header['checksum'] = OctDec(trim($v_data['checksum']));
- if ($v_header['checksum'] != $v_checksum) {
- $v_header['filename'] = '';
-
- // ----- Look for last block (empty block)
- if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
- return true;
- }
-
- $this->_error(
- 'Invalid checksum for file "' . $v_data['filename']
- . '" : ' . $v_checksum . ' calculated, '
- . $v_header['checksum'] . ' expected'
- );
- return false;
- }
-
- // ----- Extract the properties
- $v_header['filename'] = $v_data['filename'];
- if ($this->_maliciousFilename($v_header['filename'])) {
- $this->_error(
- 'Malicious .tar detected, file "' . $v_header['filename'] .
- '" will not install in desired directory tree'
- );
- return false;
- }
- $v_header['mode'] = OctDec(trim($v_data['mode']));
- $v_header['uid'] = OctDec(trim($v_data['uid']));
- $v_header['gid'] = OctDec(trim($v_data['gid']));
- $v_header['size'] = OctDec(trim($v_data['size']));
- $v_header['mtime'] = OctDec(trim($v_data['mtime']));
- if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
- $v_header['size'] = 0;
- }
- $v_header['link'] = trim($v_data['link']);
- /* ----- All these fields are removed form the header because
- they do not carry interesting info
- $v_header[magic] = trim($v_data[magic]);
- $v_header[version] = trim($v_data[version]);
- $v_header[uname] = trim($v_data[uname]);
- $v_header[gname] = trim($v_data[gname]);
- $v_header[devmajor] = trim($v_data[devmajor]);
- $v_header[devminor] = trim($v_data[devminor]);
- */
-
- return true;
- }
-
- // }}}
-
- // {{{ _maliciousFilename()
- /**
- * Detect and report a malicious file name
- *
- * @param string $file
- *
- * @return bool
- * @access private
- */
- function _maliciousFilename($file)
- {
- if (strpos($file, '/../') !== false) {
- return true;
- }
- if (strpos($file, '../') === 0) {
- return true;
- }
- return false;
- }
-
- // }}}
-
- // {{{ _readLongHeader()
- function _readLongHeader(&$v_header)
- {
- $v_filename = '';
- $n = floor($v_header['size'] / 512);
- for ($i = 0; $i < $n; $i++) {
- $v_content = $this->_readBlock();
- $v_filename .= $v_content;
- }
- if (($v_header['size'] % 512) != 0) {
- $v_content = $this->_readBlock();
- $v_filename .= trim($v_content);
- }
-
- // ----- Read the next header
- $v_binary_data = $this->_readBlock();
-
- if (!$this->_readHeader($v_binary_data, $v_header)) {
- return false;
- }
-
- $v_filename = trim($v_filename);
- $v_header['filename'] = $v_filename;
- if ($this->_maliciousFilename($v_filename)) {
- $this->_error(
- 'Malicious .tar detected, file "' . $v_filename .
- '" will not install in desired directory tree'
- );
- return false;
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _extractInString()
- /**
- * This method extract from the archive one file identified by $p_filename.
- * The return value is a string with the file content, or null on error.
- *
- * @param string $p_filename The path of the file to extract in a string.
- *
- * @return a string with the file content or null.
- * @access private
- */
- function _extractInString($p_filename)
- {
- $v_result_str = "";
-
- While (strlen($v_binary_data = $this->_readBlock()) != 0) {
- if (!$this->_readHeader($v_binary_data, $v_header)) {
- return null;
- }
-
- if ($v_header['filename'] == '') {
- continue;
- }
-
- // ----- Look for long filename
- if ($v_header['typeflag'] == 'L') {
- if (!$this->_readLongHeader($v_header)) {
- return null;
- }
- }
-
- if ($v_header['filename'] == $p_filename) {
- if ($v_header['typeflag'] == "5") {
- $this->_error(
- 'Unable to extract in string a directory '
- . 'entry {' . $v_header['filename'] . '}'
- );
- return null;
- } else {
- $n = floor($v_header['size'] / 512);
- for ($i = 0; $i < $n; $i++) {
- $v_result_str .= $this->_readBlock();
- }
- if (($v_header['size'] % 512) != 0) {
- $v_content = $this->_readBlock();
- $v_result_str .= substr(
- $v_content,
- 0,
- ($v_header['size'] % 512)
- );
- }
- return $v_result_str;
- }
- } else {
- $this->_jumpBlock(ceil(($v_header['size'] / 512)));
- }
- }
-
- return null;
- }
-
- // }}}
-
- // {{{ _extractList()
- function _extractList(
- $p_path,
- &$p_list_detail,
- $p_mode,
- $p_file_list,
- $p_remove_path,
- $p_preserve = false
- ) {
- $v_result = true;
- $v_nb = 0;
- $v_extract_all = true;
- $v_listing = false;
-
- $p_path = $this->_translateWinPath($p_path, false);
- if ($p_path == '' || (substr($p_path, 0, 1) != '/'
- && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))
- ) {
- $p_path = "./" . $p_path;
- }
- $p_remove_path = $this->_translateWinPath($p_remove_path);
-
- // ----- Look for path to remove format (should end by /)
- if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) {
- $p_remove_path .= '/';
- }
- $p_remove_path_size = strlen($p_remove_path);
-
- switch ($p_mode) {
- case "complete" :
- $v_extract_all = true;
- $v_listing = false;
- break;
- case "partial" :
- $v_extract_all = false;
- $v_listing = false;
- break;
- case "list" :
- $v_extract_all = false;
- $v_listing = true;
- break;
- default :
- $this->_error('Invalid extract mode (' . $p_mode . ')');
- return false;
- }
-
- clearstatcache();
-
- while (strlen($v_binary_data = $this->_readBlock()) != 0) {
- $v_extract_file = false;
- $v_extraction_stopped = 0;
-
- if (!$this->_readHeader($v_binary_data, $v_header)) {
- return false;
- }
-
- if ($v_header['filename'] == '') {
- continue;
- }
-
- // ----- Look for long filename
- if ($v_header['typeflag'] == 'L') {
- if (!$this->_readLongHeader($v_header)) {
- return false;
- }
- }
-
- // ignore extended / pax headers
- if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') {
- $this->_jumpBlock(ceil(($v_header['size'] / 512)));
- continue;
- }
-
- if ((!$v_extract_all) && (is_array($p_file_list))) {
- // ----- By default no unzip if the file is not found
- $v_extract_file = false;
-
- for ($i = 0; $i < sizeof($p_file_list); $i++) {
- // ----- Look if it is a directory
- if (substr($p_file_list[$i], -1) == '/') {
- // ----- Look if the directory is in the filename path
- if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
- && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
- == $p_file_list[$i])
- ) {
- $v_extract_file = true;
- break;
- }
- } // ----- It is a file, so compare the file names
- elseif ($p_file_list[$i] == $v_header['filename']) {
- $v_extract_file = true;
- break;
- }
- }
- } else {
- $v_extract_file = true;
- }
-
- // ----- Look if this file need to be extracted
- if (($v_extract_file) && (!$v_listing)) {
- if (($p_remove_path != '')
- && (substr($v_header['filename'] . '/', 0, $p_remove_path_size)
- == $p_remove_path)
- ) {
- $v_header['filename'] = substr(
- $v_header['filename'],
- $p_remove_path_size
- );
- if ($v_header['filename'] == '') {
- continue;
- }
- }
- if (($p_path != './') && ($p_path != '/')) {
- while (substr($p_path, -1) == '/') {
- $p_path = substr($p_path, 0, strlen($p_path) - 1);
- }
-
- if (substr($v_header['filename'], 0, 1) == '/') {
- $v_header['filename'] = $p_path . $v_header['filename'];
- } else {
- $v_header['filename'] = $p_path . '/' . $v_header['filename'];
- }
- }
- if (file_exists($v_header['filename'])) {
- if ((@is_dir($v_header['filename']))
- && ($v_header['typeflag'] == '')
- ) {
- $this->_error(
- 'File ' . $v_header['filename']
- . ' already exists as a directory'
- );
- return false;
- }
- if (($this->_isArchive($v_header['filename']))
- && ($v_header['typeflag'] == "5")
- ) {
- $this->_error(
- 'Directory ' . $v_header['filename']
- . ' already exists as a file'
- );
- return false;
- }
- if (!is_writeable($v_header['filename'])) {
- $this->_error(
- 'File ' . $v_header['filename']
- . ' already exists and is write protected'
- );
- return false;
- }
- if (filemtime($v_header['filename']) > $v_header['mtime']) {
- // To be completed : An error or silent no replace ?
- }
- } // ----- Check the directory availability and create it if necessary
- elseif (($v_result
- = $this->_dirCheck(
- ($v_header['typeflag'] == "5"
- ? $v_header['filename']
- : dirname($v_header['filename']))
- )) != 1
- ) {
- $this->_error('Unable to create path for ' . $v_header['filename']);
- return false;
- }
-
- if ($v_extract_file) {
- if ($v_header['typeflag'] == "5") {
- if (!@file_exists($v_header['filename'])) {
- if (!@mkdir($v_header['filename'], 0777)) {
- $this->_error(
- 'Unable to create directory {'
- . $v_header['filename'] . '}'
- );
- return false;
- }
- }
- } elseif ($v_header['typeflag'] == "2") {
- if (@file_exists($v_header['filename'])) {
- @unlink($v_header['filename']);
- }
- if (!@symlink($v_header['link'], $v_header['filename'])) {
- $this->_error(
- 'Unable to extract symbolic link {'
- . $v_header['filename'] . '}'
- );
- return false;
- }
- } else {
- if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
- $this->_error(
- 'Error while opening {' . $v_header['filename']
- . '} in write binary mode'
- );
- return false;
- } else {
- $n = floor($v_header['size'] / 512);
- for ($i = 0; $i < $n; $i++) {
- $v_content = $this->_readBlock();
- fwrite($v_dest_file, $v_content, 512);
- }
- if (($v_header['size'] % 512) != 0) {
- $v_content = $this->_readBlock();
- fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
- }
-
- @fclose($v_dest_file);
-
- if ($p_preserve) {
- @chown($v_header['filename'], $v_header['uid']);
- @chgrp($v_header['filename'], $v_header['gid']);
- }
-
- // ----- Change the file mode, mtime
- @touch($v_header['filename'], $v_header['mtime']);
- if ($v_header['mode'] & 0111) {
- // make file executable, obey umask
- $mode = fileperms($v_header['filename']) | (~umask() & 0111);
- @chmod($v_header['filename'], $mode);
- }
- }
-
- // ----- Check the file size
- clearstatcache();
- if (!is_file($v_header['filename'])) {
- $this->_error(
- 'Extracted file ' . $v_header['filename']
- . 'does not exist. Archive may be corrupted.'
- );
- return false;
- }
-
- $filesize = filesize($v_header['filename']);
- if ($filesize != $v_header['size']) {
- $this->_error(
- 'Extracted file ' . $v_header['filename']
- . ' does not have the correct file size \''
- . $filesize
- . '\' (' . $v_header['size']
- . ' expected). Archive may be corrupted.'
- );
- return false;
- }
- }
- } else {
- $this->_jumpBlock(ceil(($v_header['size'] / 512)));
- }
- } else {
- $this->_jumpBlock(ceil(($v_header['size'] / 512)));
- }
-
- /* TBC : Seems to be unused ...
- if ($this->_compress)
- $v_end_of_file = @gzeof($this->_file);
- else
- $v_end_of_file = @feof($this->_file);
- */
-
- if ($v_listing || $v_extract_file || $v_extraction_stopped) {
- // ----- Log extracted files
- if (($v_file_dir = dirname($v_header['filename']))
- == $v_header['filename']
- ) {
- $v_file_dir = '';
- }
- if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) {
- $v_file_dir = '/';
- }
-
- $p_list_detail[$v_nb++] = $v_header;
- if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
- return true;
- }
- }
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _openAppend()
- function _openAppend()
- {
- if (filesize($this->_tarname) == 0) {
- return $this->_openWrite();
- }
-
- if ($this->_compress) {
- $this->_close();
-
- if (!@rename($this->_tarname, $this->_tarname . ".tmp")) {
- $this->_error(
- 'Error while renaming \'' . $this->_tarname
- . '\' to temporary file \'' . $this->_tarname
- . '.tmp\''
- );
- return false;
- }
-
- if ($this->_compress_type == 'gz') {
- $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb");
- } elseif ($this->_compress_type == 'bz2') {
- $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r");
- } elseif ($this->_compress_type == 'lzma2') {
- $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r");
- }
-
-
- if ($v_temp_tar == 0) {
- $this->_error(
- 'Unable to open file \'' . $this->_tarname
- . '.tmp\' in binary read mode'
- );
- @rename($this->_tarname . ".tmp", $this->_tarname);
- return false;
- }
-
- if (!$this->_openWrite()) {
- @rename($this->_tarname . ".tmp", $this->_tarname);
- return false;
- }
-
- if ($this->_compress_type == 'gz') {
- $end_blocks = 0;
-
- while (!@gzeof($v_temp_tar)) {
- $v_buffer = @gzread($v_temp_tar, 512);
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
- $end_blocks++;
- // do not copy end blocks, we will re-make them
- // after appending
- continue;
- } elseif ($end_blocks > 0) {
- for ($i = 0; $i < $end_blocks; $i++) {
- $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
- }
- $end_blocks = 0;
- }
- $v_binary_data = pack("a512", $v_buffer);
- $this->_writeBlock($v_binary_data);
- }
-
- @gzclose($v_temp_tar);
- } elseif ($this->_compress_type == 'bz2') {
- $end_blocks = 0;
-
- while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
- $end_blocks++;
- // do not copy end blocks, we will re-make them
- // after appending
- continue;
- } elseif ($end_blocks > 0) {
- for ($i = 0; $i < $end_blocks; $i++) {
- $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
- }
- $end_blocks = 0;
- }
- $v_binary_data = pack("a512", $v_buffer);
- $this->_writeBlock($v_binary_data);
- }
-
- @bzclose($v_temp_tar);
- } elseif ($this->_compress_type == 'lzma2') {
- $end_blocks = 0;
-
- while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) {
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
- $end_blocks++;
- // do not copy end blocks, we will re-make them
- // after appending
- continue;
- } elseif ($end_blocks > 0) {
- for ($i = 0; $i < $end_blocks; $i++) {
- $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
- }
- $end_blocks = 0;
- }
- $v_binary_data = pack("a512", $v_buffer);
- $this->_writeBlock($v_binary_data);
- }
-
- @xzclose($v_temp_tar);
- }
-
- if (!@unlink($this->_tarname . ".tmp")) {
- $this->_error(
- 'Error while deleting temporary file \''
- . $this->_tarname . '.tmp\''
- );
- }
-
- } else {
- // ----- For not compressed tar, just add files before the last
- // one or two 512 bytes block
- if (!$this->_openReadWrite()) {
- return false;
- }
-
- clearstatcache();
- $v_size = filesize($this->_tarname);
-
- // We might have zero, one or two end blocks.
- // The standard is two, but we should try to handle
- // other cases.
- fseek($this->_file, $v_size - 1024);
- if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
- fseek($this->_file, $v_size - 1024);
- } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
- fseek($this->_file, $v_size - 512);
- }
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _append()
- function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '')
- {
- if (!$this->_openAppend()) {
- return false;
- }
-
- if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) {
- $this->_writeFooter();
- }
-
- $this->_close();
-
- return true;
- }
-
- // }}}
-
- // {{{ _dirCheck()
-
- /**
- * Check if a directory exists and create it (including parent
- * dirs) if not.
- *
- * @param string $p_dir directory to check
- *
- * @return bool true if the directory exists or was created
- */
- function _dirCheck($p_dir)
- {
- clearstatcache();
- if ((@is_dir($p_dir)) || ($p_dir == '')) {
- return true;
- }
-
- $p_parent_dir = dirname($p_dir);
-
- if (($p_parent_dir != $p_dir) &&
- ($p_parent_dir != '') &&
- (!$this->_dirCheck($p_parent_dir))
- ) {
- return false;
- }
-
- if (!@mkdir($p_dir, 0777)) {
- $this->_error("Unable to create directory '$p_dir'");
- return false;
- }
-
- return true;
- }
-
- // }}}
-
- // {{{ _pathReduction()
-
- /**
- * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
- * rand emove double slashes.
- *
- * @param string $p_dir path to reduce
- *
- * @return string reduced path
- *
- * @access private
- *
- */
- function _pathReduction($p_dir)
- {
- $v_result = '';
-
- // ----- Look for not empty path
- if ($p_dir != '') {
- // ----- Explode path by directory names
- $v_list = explode('/', $p_dir);
-
- // ----- Study directories from last to first
- for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
- // ----- Look for current path
- if ($v_list[$i] == ".") {
- // ----- Ignore this directory
- // Should be the first $i=0, but no check is done
- } else {
- if ($v_list[$i] == "..") {
- // ----- Ignore it and ignore the $i-1
- $i--;
- } else {
- if (($v_list[$i] == '')
- && ($i != (sizeof($v_list) - 1))
- && ($i != 0)
- ) {
- // ----- Ignore only the double '//' in path,
- // but not the first and last /
- } else {
- $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/'
- . $v_result : '');
- }
- }
- }
- }
- }
-
- if (defined('OS_WINDOWS') && OS_WINDOWS) {
- $v_result = strtr($v_result, '\\', '/');
- }
-
- return $v_result;
- }
-
- // }}}
-
- // {{{ _translateWinPath()
- function _translateWinPath($p_path, $p_remove_disk_letter = true)
- {
- if (defined('OS_WINDOWS') && OS_WINDOWS) {
- // ----- Look for potential disk letter
- if (($p_remove_disk_letter)
- && (($v_position = strpos($p_path, ':')) != false)
- ) {
- $p_path = substr($p_path, $v_position + 1);
- }
- // ----- Change potential windows directory separator
- if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
- $p_path = strtr($p_path, '\\', '/');
- }
- }
- return $p_path;
- }
- // }}}
-
-}
-
-?>
diff --git a/data/module/Cache/Lite.php b/data/module/Cache/Lite.php
deleted file mode 100644
index 0ca762d380..0000000000
--- a/data/module/Cache/Lite.php
+++ /dev/null
@@ -1,886 +0,0 @@
-
-*
-* Nota : A chinese documentation (thanks to RainX ) is
-* available at :
-* http://rainx.phpmore.com/manual/cache_lite.html
-*
-* @package Cache_Lite
-* @category Caching
-* @author Fabien MARTY
-* @author Markus Tacker
-*/
-
-define('CACHE_LITE_ERROR_RETURN', 1);
-define('CACHE_LITE_ERROR_DIE', 8);
-
-class Cache_Lite
-{
-
- // --- Private properties ---
-
- /**
- * Directory where to put the cache files
- * (make sure to add a trailing slash)
- *
- * @var string $_cacheDir
- */
- var $_cacheDir = '/tmp/';
-
- /**
- * Enable / disable caching
- *
- * (can be very usefull for the debug of cached scripts)
- *
- * @var boolean $_caching
- */
- var $_caching = true;
-
- /**
- * Cache lifetime (in seconds)
- *
- * If null, the cache is valid forever.
- *
- * @var int $_lifeTime
- */
- var $_lifeTime = 3600;
-
- /**
- * Enable / disable fileLocking
- *
- * (can avoid cache corruption under bad circumstances)
- *
- * @var boolean $_fileLocking
- */
- var $_fileLocking = true;
-
- /**
- * Timestamp of the last valid cache
- *
- * @var int $_refreshTime
- */
- var $_refreshTime;
-
- /**
- * File name (with path)
- *
- * @var string $_file
- */
- var $_file;
-
- /**
- * File name (without path)
- *
- * @var string $_fileName
- */
- var $_fileName;
-
- /**
- * Enable / disable write control (the cache is read just after writing to detect corrupt entries)
- *
- * Enable write control will lightly slow the cache writing but not the cache reading
- * Write control can detect some corrupt cache files but maybe it's not a perfect control
- *
- * @var boolean $_writeControl
- */
- var $_writeControl = true;
-
- /**
- * Enable / disable read control
- *
- * If enabled, a control key is embeded in cache file and this key is compared with the one
- * calculated after the reading.
- *
- * @var boolean $_writeControl
- */
- var $_readControl = true;
-
- /**
- * Type of read control (only if read control is enabled)
- *
- * Available values are :
- * 'md5' for a md5 hash control (best but slowest)
- * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
- * 'strlen' for a length only test (fastest)
- *
- * @var boolean $_readControlType
- */
- var $_readControlType = 'crc32';
-
- /**
- * Pear error mode (when raiseError is called)
- *
- * (see PEAR doc)
- *
- * @see setToDebug()
- * @var int $_pearErrorMode
- */
- var $_pearErrorMode = CACHE_LITE_ERROR_RETURN;
-
- /**
- * Current cache id
- *
- * @var string $_id
- */
- var $_id;
-
- /**
- * Current cache group
- *
- * @var string $_group
- */
- var $_group;
-
- /**
- * Enable / Disable "Memory Caching"
- *
- * NB : There is no lifetime for memory caching !
- *
- * @var boolean $_memoryCaching
- */
- var $_memoryCaching = false;
-
- /**
- * Enable / Disable "Only Memory Caching"
- * (be carefull, memory caching is "beta quality")
- *
- * @var boolean $_onlyMemoryCaching
- */
- var $_onlyMemoryCaching = false;
-
- /**
- * Memory caching array
- *
- * @var array $_memoryCachingArray
- */
- var $_memoryCachingArray = array();
-
- /**
- * Memory caching counter
- *
- * @var int $memoryCachingCounter
- */
- var $_memoryCachingCounter = 0;
-
- /**
- * Memory caching limit
- *
- * @var int $memoryCachingLimit
- */
- var $_memoryCachingLimit = 1000;
-
- /**
- * File Name protection
- *
- * if set to true, you can use any cache id or group name
- * if set to false, it can be faster but cache ids and group names
- * will be used directly in cache file names so be carefull with
- * special characters...
- *
- * @var boolean $fileNameProtection
- */
- var $_fileNameProtection = true;
-
- /**
- * Enable / disable automatic serialization
- *
- * it can be used to save directly datas which aren't strings
- * (but it's slower)
- *
- * @var boolean $_serialize
- */
- var $_automaticSerialization = false;
-
- /**
- * Disable / Tune the automatic cleaning process
- *
- * The automatic cleaning process destroy too old (for the given life time)
- * cache files when a new cache file is written.
- * 0 => no automatic cache cleaning
- * 1 => systematic cache cleaning
- * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
- *
- * @var int $_automaticCleaning
- */
- var $_automaticCleaningFactor = 0;
-
- /**
- * Nested directory level
- *
- * Set the hashed directory structure level. 0 means "no hashed directory
- * structure", 1 means "one level of directory", 2 means "two levels"...
- * This option can speed up Cache_Lite only when you have many thousands of
- * cache file. Only specific benchs can help you to choose the perfect value
- * for you. Maybe, 1 or 2 is a good start.
- *
- * @var int $_hashedDirectoryLevel
- */
- var $_hashedDirectoryLevel = 0;
-
- /**
- * Umask for hashed directory structure
- *
- * @var int $_hashedDirectoryUmask
- */
- var $_hashedDirectoryUmask = 0700;
-
- /**
- * API break for error handling in CACHE_LITE_ERROR_RETURN mode
- *
- * In CACHE_LITE_ERROR_RETURN mode, error handling was not good because
- * for example save() method always returned a boolean (a PEAR_Error object
- * would be better in CACHE_LITE_ERROR_RETURN mode). To correct this without
- * breaking the API, this option (false by default) can change this handling.
- *
- * @var boolean
- */
- var $_errorHandlingAPIBreak = false;
-
- var $_hashedDirectoryGroup = NULL;
-
- var $_cacheFileMode = NULL;
-
- var $_cacheFileGroup = NULL;
-
- // --- Public methods ---
-
- /**
- * Constructor
- *
- * $options is an assoc. Available options are :
- * $options = array(
- * 'cacheDir' => directory where to put the cache files (string),
- * 'caching' => enable / disable caching (boolean),
- * 'lifeTime' => cache lifetime in seconds (int),
- * 'fileLocking' => enable / disable fileLocking (boolean),
- * 'writeControl' => enable / disable write control (boolean),
- * 'readControl' => enable / disable read control (boolean),
- * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string),
- * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int),
- * 'memoryCaching' => enable / disable memory caching (boolean),
- * 'onlyMemoryCaching' => enable / disable only memory caching (boolean),
- * 'memoryCachingLimit' => max nbr of records to store into memory caching (int),
- * 'fileNameProtection' => enable / disable automatic file name protection (boolean),
- * 'automaticSerialization' => enable / disable automatic serialization (boolean),
- * 'automaticCleaningFactor' => distable / tune automatic cleaning process (int),
- * 'hashedDirectoryLevel' => level of the hashed directory system (int),
- * 'hashedDirectoryUmask' => umask for hashed directory structure (int),
- * 'errorHandlingAPIBreak' => API break for better error handling ? (boolean)
- * 'hashedDirectoryGroup' => group of hashed directory structure (int | string) (see function chgrp)
- * 'cacheFileMode' => filesystem mode of newly created cache files (int)
- * 'cacheFileGroup' => group of newly created cache files (int | string) (see function chgrp)
- * );
- *
- * If sys_get_temp_dir() is available and the
- * 'cacheDir' option is not provided in the
- * constructor options array its output is used
- * to determine the suitable temporary directory.
- *
- * @see http://de.php.net/sys_get_temp_dir
- * @see http://pear.php.net/bugs/bug.php?id=18328
- *
- * @param array $options options
- * @access public
- */
- function Cache_Lite($options = array(NULL))
- {
- foreach($options as $key => $value) {
- $this->setOption($key, $value);
- }
- if (!isset($options['cacheDir']) && function_exists('sys_get_temp_dir')) {
- $this->setOption('cacheDir', sys_get_temp_dir() . DIRECTORY_SEPARATOR);
- }
- }
-
- /**
- * Generic way to set a Cache_Lite option
- *
- * see Cache_Lite constructor for available options
- *
- * @var string $name name of the option
- * @var mixed $value value of the option
- * @access public
- */
- function setOption($name, $value)
- {
- $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode', 'hashedDirectoryGroup', 'cacheFileMode', 'cacheFileGroup');
- if (in_array($name, $availableOptions)) {
- $property = '_'.$name;
- $this->$property = $value;
- }
- }
-
- /**
- * Test if a cache is available and (if yes) return it
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @return string data of the cache (else : false)
- * @access public
- */
- function get($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- $this->_id = $id;
- $this->_group = $group;
- $data = false;
- if ($this->_caching) {
- $this->_setRefreshTime();
- $this->_setFileName($id, $group);
- clearstatcache();
- if ($this->_memoryCaching) {
- if (isset($this->_memoryCachingArray[$this->_file])) {
- if ($this->_automaticSerialization) {
- return unserialize($this->_memoryCachingArray[$this->_file]);
- }
- return $this->_memoryCachingArray[$this->_file];
- }
- if ($this->_onlyMemoryCaching) {
- return false;
- }
- }
- if (($doNotTestCacheValidity) || (is_null($this->_refreshTime))) {
- if (file_exists($this->_file)) {
- $data = $this->_read();
- }
- } else {
- if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) {
- $data = $this->_read();
- }
- }
- if (($data) and ($this->_memoryCaching)) {
- $this->_memoryCacheAdd($data);
- }
- if (($this->_automaticSerialization) and (is_string($data))) {
- $data = unserialize($data);
- }
- return $data;
- }
- return false;
- }
-
- /**
- * Save some data in a cache file
- *
- * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on)
- * @param string $id cache id
- * @param string $group name of the cache group
- * @return boolean true if no problem (else : false or a PEAR_Error object)
- * @access public
- */
- function save($data, $id = NULL, $group = 'default')
- {
- if ($this->_caching) {
- if ($this->_automaticSerialization) {
- $data = serialize($data);
- }
- if (isset($id)) {
- $this->_setFileName($id, $group);
- }
- if ($this->_memoryCaching) {
- $this->_memoryCacheAdd($data);
- if ($this->_onlyMemoryCaching) {
- return true;
- }
- }
- if ($this->_automaticCleaningFactor>0 && ($this->_automaticCleaningFactor==1 || mt_rand(1, $this->_automaticCleaningFactor)==1)) {
- $this->clean(false, 'old');
- }
- if ($this->_writeControl) {
- $res = $this->_writeAndControl($data);
- if (is_bool($res)) {
- if ($res) {
- return true;
- }
- // if $res if false, we need to invalidate the cache
- @touch($this->_file, time() - 2*abs($this->_lifeTime));
- return false;
- }
- } else {
- $res = $this->_write($data);
- }
- if (is_object($res)) {
- // $res is a PEAR_Error object
- if (!($this->_errorHandlingAPIBreak)) {
- return false; // we return false (old API)
- }
- }
- return $res;
- }
- return false;
- }
-
- /**
- * Remove a cache file
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $checkbeforeunlink check if file exists before removing it
- * @return boolean true if no problem
- * @access public
- */
- function remove($id, $group = 'default', $checkbeforeunlink = false)
- {
- $this->_setFileName($id, $group);
- if ($this->_memoryCaching) {
- if (isset($this->_memoryCachingArray[$this->_file])) {
- unset($this->_memoryCachingArray[$this->_file]);
- $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
- }
- if ($this->_onlyMemoryCaching) {
- return true;
- }
- }
- if ( $checkbeforeunlink ) {
- if (!file_exists($this->_file)) return true;
- }
- return $this->_unlink($this->_file);
- }
-
- /**
- * Clean the cache
- *
- * if no group is specified all cache files will be destroyed
- * else only cache files of the specified group will be destroyed
- *
- * @param string $group name of the cache group
- * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup',
- * 'callback_myFunction'
- * @return boolean true if no problem
- * @access public
- */
- function clean($group = false, $mode = 'ingroup')
- {
- return $this->_cleanDir($this->_cacheDir, $group, $mode);
- }
-
- /**
- * Set to debug mode
- *
- * When an error is found, the script will stop and the message will be displayed
- * (in debug mode only).
- *
- * @access public
- */
- function setToDebug()
- {
- $this->setOption('pearErrorMode', CACHE_LITE_ERROR_DIE);
- }
-
- /**
- * Set a new life time
- *
- * @param int $newLifeTime new life time (in seconds)
- * @access public
- */
- function setLifeTime($newLifeTime)
- {
- $this->_lifeTime = $newLifeTime;
- $this->_setRefreshTime();
- }
-
- /**
- * Save the state of the caching memory array into a cache file cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @access public
- */
- function saveMemoryCachingState($id, $group = 'default')
- {
- if ($this->_caching) {
- $array = array(
- 'counter' => $this->_memoryCachingCounter,
- 'array' => $this->_memoryCachingArray
- );
- $data = serialize($array);
- $this->save($data, $id, $group);
- }
- }
-
- /**
- * Load the state of the caching memory array from a given cache file cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @access public
- */
- function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- if ($this->_caching) {
- if ($data = $this->get($id, $group, $doNotTestCacheValidity)) {
- $array = unserialize($data);
- $this->_memoryCachingCounter = $array['counter'];
- $this->_memoryCachingArray = $array['array'];
- }
- }
- }
-
- /**
- * Return the cache last modification time
- *
- * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !
- *
- * @return int last modification time
- */
- function lastModified()
- {
- return @filemtime($this->_file);
- }
-
- /**
- * Trigger a PEAR error
- *
- * To improve performances, the PEAR.php file is included dynamically.
- * The file is so included only when an error is triggered. So, in most
- * cases, the file isn't included and perfs are much better.
- *
- * @param string $msg error message
- * @param int $code error code
- * @access public
- */
- function raiseError($msg, $code)
- {
- include_once('PEAR.php');
- return PEAR::raiseError($msg, $code, $this->_pearErrorMode);
- }
-
- /**
- * Extend the life of a valid cache file
- *
- * see http://pear.php.net/bugs/bug.php?id=6681
- *
- * @access public
- */
- function extendLife()
- {
- @touch($this->_file);
- }
-
- // --- Private methods ---
-
- /**
- * Compute & set the refresh time
- *
- * @access private
- */
- function _setRefreshTime()
- {
- if (is_null($this->_lifeTime)) {
- $this->_refreshTime = null;
- } else {
- $this->_refreshTime = time() - $this->_lifeTime;
- }
- }
-
- /**
- * Remove a file
- *
- * @param string $file complete file path and name
- * @return boolean true if no problem
- * @access private
- */
- function _unlink($file)
- {
- if (!@unlink($file)) {
- return $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
- }
- return true;
- }
-
- /**
- * Recursive function for cleaning cache file in the given directory
- *
- * @param string $dir directory complete path (with a trailing slash)
- * @param string $group name of the cache group
- * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup',
- 'callback_myFunction'
- * @return boolean true if no problem
- * @access private
- */
- function _cleanDir($dir, $group = false, $mode = 'ingroup')
- {
- if ($this->_fileNameProtection) {
- $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_';
- } else {
- $motif = ($group) ? 'cache_'.$group.'_' : 'cache_';
- }
- if ($this->_memoryCaching) {
- foreach($this->_memoryCachingArray as $key => $v) {
- if (strpos($key, $motif) !== false) {
- unset($this->_memoryCachingArray[$key]);
- $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
- }
- }
- if ($this->_onlyMemoryCaching) {
- return true;
- }
- }
- if (!($dh = opendir($dir))) {
- return $this->raiseError('Cache_Lite : Unable to open cache directory !', -4);
- }
- $result = true;
- while (($file = readdir($dh)) !== false) {
- if (($file != '.') && ($file != '..')) {
- if (substr($file, 0, 6)=='cache_') {
- $file2 = $dir . $file;
- if (is_file($file2)) {
- switch (substr($mode, 0, 9)) {
- case 'old':
- // files older than lifeTime get deleted from cache
- if (!is_null($this->_lifeTime)) {
- if ((time() - @filemtime($file2)) > $this->_lifeTime) {
- $result = ($result and ($this->_unlink($file2)));
- }
- }
- break;
- case 'notingrou':
- if (strpos($file2, $motif) === false) {
- $result = ($result and ($this->_unlink($file2)));
- }
- break;
- case 'callback_':
- $func = substr($mode, 9, strlen($mode) - 9);
- if ($func($file2, $group)) {
- $result = ($result and ($this->_unlink($file2)));
- }
- break;
- case 'ingroup':
- default:
- if (strpos($file2, $motif) !== false) {
- $result = ($result and ($this->_unlink($file2)));
- }
- break;
- }
- }
- if ((is_dir($file2)) and ($this->_hashedDirectoryLevel>0)) {
- $result = ($result and ($this->_cleanDir($file2 . '/', $group, $mode)));
- }
- }
- }
- }
- return $result;
- }
-
- /**
- * Touch the cache file while are recreating it to avoid
- * launch this task more then once when necessary
- * When the cache recreated and Added in Cache Memory
- * @return void
- * @access private
- */
- function _touchCacheFile(){
- if (file_exists($this->_file)) {
- @touch($this->_file);
- }
- }
- /**
- * Add some date in the memory caching array
- *
- * @param string $data data to cache
- * @access private
- */
- function _memoryCacheAdd($data)
- {
- $this->_touchCacheFile();
- $this->_memoryCachingArray[$this->_file] = $data;
- if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) {
- list($key, ) = each($this->_memoryCachingArray);
- unset($this->_memoryCachingArray[$key]);
- } else {
- $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1;
- }
- }
-
- /**
- * Make a file name (with path)
- *
- * @param string $id cache id
- * @param string $group name of the group
- * @access private
- */
- function _setFileName($id, $group)
- {
-
- if ($this->_fileNameProtection) {
- $suffix = 'cache_'.md5($group).'_'.md5($id);
- } else {
- $suffix = 'cache_'.$group.'_'.$id;
- }
- $root = $this->_cacheDir;
- if ($this->_hashedDirectoryLevel>0) {
- $hash = md5($suffix);
- for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) {
- $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';
- }
- }
- $this->_fileName = $suffix;
- $this->_file = $root.$suffix;
- }
-
- /**
- * Read the cache file and return the content
- *
- * @return string content of the cache file (else : false or a PEAR_Error object)
- * @access private
- */
- function _read()
- {
- $fp = @fopen($this->_file, "rb");
- if ($fp) {
- if ($this->_fileLocking) @flock($fp, LOCK_SH);
- clearstatcache();
- $length = @filesize($this->_file);
- $mqr = get_magic_quotes_runtime();
- if ($mqr) {
- set_magic_quotes_runtime(0);
- }
- if ($this->_readControl) {
- $hashControl = @fread($fp, 32);
- $length = $length - 32;
- }
-
- if ($length) {
- $data = '';
- // See https://bugs.php.net/bug.php?id=30936
- // The 8192 magic number is the chunk size used internally by PHP.
- while(!feof($fp)) $data .= fread($fp, 8192);
- } else {
- $data = '';
- }
- if ($mqr) {
- set_magic_quotes_runtime($mqr);
- }
- if ($this->_fileLocking) @flock($fp, LOCK_UN);
- @fclose($fp);
- if ($this->_readControl) {
- $hashData = $this->_hash($data, $this->_readControlType);
- if ($hashData != $hashControl) {
- if (!(is_null($this->_lifeTime))) {
- @touch($this->_file, time() - 2*abs($this->_lifeTime));
- } else {
- @unlink($this->_file);
- }
- return false;
- }
- }
- return $data;
- }
- return $this->raiseError('Cache_Lite : Unable to read cache !', -2);
- }
-
- /**
- * Write the given data in the cache file
- *
- * @param string $data data to put in cache
- * @return boolean true if ok (a PEAR_Error object else)
- * @access private
- */
- function _write($data)
- {
- if ($this->_hashedDirectoryLevel > 0) {
- $hash = md5($this->_fileName);
- $root = $this->_cacheDir;
- for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) {
- $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';
- if (!(@is_dir($root))) {
- if (@mkdir($root))
- {
- @chmod($root, $this->_hashedDirectoryUmask);
- if (! is_null($this->_hashedDirectoryGroup))
- @chgrp($root, $this->_hashedDirectoryGroup);
- }
- }
- }
- }
- // if both _cacheFileMode and _cacheFileGroup is null, then we don't need to call
- // file_exists (see below: if ($is_newfile) ...)
- $is_newfile = (! is_null($this->_cacheFileMode) || !is_null($this->_cacheFileGroup))
- && ! @file_exists($this->_file);
- $fp = @fopen($this->_file, "wb");
- if ($fp) {
- if ($this->_fileLocking) @flock($fp, LOCK_EX);
- if ($is_newfile)
- {
- if (! is_null($this->_cacheFileMode))
- @chmod($this->_file, $this->_cacheFileMode);
- if (! is_null($this->_cacheFileGroup))
- @chgrp($this->_file, $this->_cacheFileGroup);
- }
- if ($this->_readControl) {
- @fwrite($fp, $this->_hash($data, $this->_readControlType), 32);
- }
- $mqr = get_magic_quotes_runtime();
- if ($mqr) {
- set_magic_quotes_runtime(0);
- }
- @fwrite($fp, $data);
- if ($mqr) {
- set_magic_quotes_runtime($mqr);
- }
- if ($this->_fileLocking) @flock($fp, LOCK_UN);
- @fclose($fp);
- return true;
- }
- return $this->raiseError('Cache_Lite : Unable to write cache file : '.$this->_file, -1);
- }
-
- /**
- * Write the given data in the cache file and control it just after to avoir corrupted cache entries
- *
- * @param string $data data to put in cache
- * @return boolean true if the test is ok (else : false or a PEAR_Error object)
- * @access private
- */
- function _writeAndControl($data)
- {
- $result = $this->_write($data);
- if (is_object($result)) {
- return $result; # We return the PEAR_Error object
- }
- $dataRead = $this->_read();
- if (is_object($dataRead)) {
- return $dataRead; # We return the PEAR_Error object
- }
- if ((is_bool($dataRead)) && (!$dataRead)) {
- return false;
- }
- return ($dataRead==$data);
- }
-
- /**
- * Make a control key with the string containing datas
- *
- * @param string $data data
- * @param string $controlType type of control 'md5', 'crc32' or 'strlen'
- * @return string control key
- * @access private
- */
- function _hash($data, $controlType)
- {
- switch ($controlType) {
- case 'md5':
- return md5($data);
- case 'crc32':
- return sprintf('% 32d', crc32($data));
- case 'strlen':
- return sprintf('% 32d', strlen($data));
- default:
- return $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5);
- }
- }
-
-}
diff --git a/data/module/Cache/Lite/File.php b/data/module/Cache/Lite/File.php
deleted file mode 100644
index 2cb2758b0b..0000000000
--- a/data/module/Cache/Lite/File.php
+++ /dev/null
@@ -1,90 +0,0 @@
-
-*/
-
-require_once('Cache/Lite.php');
-
-class Cache_Lite_File extends Cache_Lite
-{
-
- // --- Private properties ---
-
- /**
- * Complete path of the file used for controlling the cache lifetime
- *
- * @var string $_masterFile
- */
- var $_masterFile = '';
-
- /**
- * Masterfile mtime
- *
- * @var int $_masterFile_mtime
- */
- var $_masterFile_mtime = 0;
-
- // --- Public methods ----
-
- /**
- * Constructor
- *
- * $options is an assoc. To have a look at availables options,
- * see the constructor of the Cache_Lite class in 'Cache_Lite.php'
- *
- * Comparing to Cache_Lite constructor, there is another option :
- * $options = array(
- * (...) see Cache_Lite constructor
- * 'masterFile' => complete path of the file used for controlling the cache lifetime(string)
- * );
- *
- * @param array $options options
- * @access public
- */
- function Cache_Lite_File($options = array(NULL))
- {
- $options['lifetime'] = 0;
- $this->Cache_Lite($options);
- if (isset($options['masterFile'])) {
- $this->_masterFile = $options['masterFile'];
- } else {
- return $this->raiseError('Cache_Lite_File : masterFile option must be set !');
- }
- if (!($this->_masterFile_mtime = @filemtime($this->_masterFile))) {
- return $this->raiseError('Cache_Lite_File : Unable to read masterFile : '.$this->_masterFile, -3);
- }
- }
-
- /**
- * Test if a cache is available and (if yes) return it
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @return string data of the cache (else : false)
- * @access public
- */
- function get($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- if ($data = parent::get($id, $group, true)) {
- if ($filemtime = $this->lastModified()) {
- if ($filemtime > $this->_masterFile_mtime) {
- return $data;
- }
- }
- }
- return false;
- }
-
-}
diff --git a/data/module/Cache/Lite/Function.php b/data/module/Cache/Lite/Function.php
deleted file mode 100644
index 6c4861a438..0000000000
--- a/data/module/Cache/Lite/Function.php
+++ /dev/null
@@ -1,208 +0,0 @@
-
-* @author Fabien MARTY
-*/
-
-require_once('Cache/Lite.php');
-
-class Cache_Lite_Function extends Cache_Lite
-{
-
- // --- Private properties ---
-
- /**
- * Default cache group for function caching
- *
- * @var string $_defaultGroup
- */
- var $_defaultGroup = 'Cache_Lite_Function';
-
- /**
- * Don't cache the method call when its output contains the string "NOCACHE"
- *
- * if set to true, the output of the method will never be displayed (because the output is used
- * to control the cache)
- *
- * @var boolean $_dontCacheWhenTheOutputContainsNOCACHE
- */
- var $_dontCacheWhenTheOutputContainsNOCACHE = false;
-
- /**
- * Don't cache the method call when its result is false
- *
- * @var boolean $_dontCacheWhenTheResultIsFalse
- */
- var $_dontCacheWhenTheResultIsFalse = false;
-
- /**
- * Don't cache the method call when its result is null
- *
- * @var boolean $_dontCacheWhenTheResultIsNull
- */
- var $_dontCacheWhenTheResultIsNull = false;
-
- /**
- * Debug the Cache_Lite_Function caching process
- *
- * @var boolean $_debugCacheLiteFunction
- */
- var $_debugCacheLiteFunction = false;
-
- // --- Public methods ----
-
- /**
- * Constructor
- *
- * $options is an assoc. To have a look at availables options,
- * see the constructor of the Cache_Lite class in 'Cache_Lite.php'
- *
- * Comparing to Cache_Lite constructor, there is another option :
- * $options = array(
- * (...) see Cache_Lite constructor
- * 'debugCacheLiteFunction' => (bool) debug the caching process,
- * 'defaultGroup' => default cache group for function caching (string),
- * 'dontCacheWhenTheOutputContainsNOCACHE' => (bool) don't cache when the function output contains "NOCACHE",
- * 'dontCacheWhenTheResultIsFalse' => (bool) don't cache when the function result is false,
- * 'dontCacheWhenTheResultIsNull' => (bool don't cache when the function result is null
- * );
- *
- * @param array $options options
- * @access public
- */
- function Cache_Lite_Function($options = array(NULL))
- {
- $availableOptions = array('debugCacheLiteFunction', 'defaultGroup', 'dontCacheWhenTheOutputContainsNOCACHE', 'dontCacheWhenTheResultIsFalse', 'dontCacheWhenTheResultIsNull');
- while (list($name, $value) = each($options)) {
- if (in_array($name, $availableOptions)) {
- $property = '_'.$name;
- $this->$property = $value;
- }
- }
- reset($options);
- $this->Cache_Lite($options);
- }
-
- /**
- * Calls a cacheable function or method (or not if there is already a cache for it)
- *
- * Arguments of this method are read with func_get_args. So it doesn't appear
- * in the function definition. Synopsis :
- * call('functionName', $arg1, $arg2, ...)
- * (arg1, arg2... are arguments of 'functionName')
- *
- * @return mixed result of the function/method
- * @access public
- */
- function call()
- {
- $arguments = func_get_args();
- $id = $this->_makeId($arguments);
- $data = $this->get($id, $this->_defaultGroup);
- if ($data !== false) {
- if ($this->_debugCacheLiteFunction) {
- echo "Cache hit !\n";
- }
- $array = unserialize($data);
- $output = $array['output'];
- $result = $array['result'];
- } else {
- if ($this->_debugCacheLiteFunction) {
- echo "Cache missed !\n";
- }
- ob_start();
- ob_implicit_flush(false);
- $target = array_shift($arguments);
- if (is_array($target)) {
- // in this case, $target is for example array($obj, 'method')
- $object = $target[0];
- $method = $target[1];
- $result = call_user_func_array(array(&$object, $method), $arguments);
- } else {
- if (strstr($target, '::')) { // classname::staticMethod
- list($class, $method) = explode('::', $target);
- $result = call_user_func_array(array($class, $method), $arguments);
- } else if (strstr($target, '->')) { // object->method
- // use a stupid name ($objet_123456789 because) of problems where the object
- // name is the same as this var name
- list($object_123456789, $method) = explode('->', $target);
- global $$object_123456789;
- $result = call_user_func_array(array($$object_123456789, $method), $arguments);
- } else { // function
- $result = call_user_func_array($target, $arguments);
- }
- }
- $output = ob_get_contents();
- ob_end_clean();
- if ($this->_dontCacheWhenTheResultIsFalse) {
- if ((is_bool($result)) && (!($result))) {
- echo($output);
- return $result;
- }
- }
- if ($this->_dontCacheWhenTheResultIsNull) {
- if (is_null($result)) {
- echo($output);
- return $result;
- }
- }
- if ($this->_dontCacheWhenTheOutputContainsNOCACHE) {
- if (strpos($output, 'NOCACHE') > -1) {
- return $result;
- }
- }
- $array['output'] = $output;
- $array['result'] = $result;
- $this->save(serialize($array), $id, $this->_defaultGroup);
- }
- echo($output);
- return $result;
- }
-
- /**
- * Drop a cache file
- *
- * Arguments of this method are read with func_get_args. So it doesn't appear
- * in the function definition. Synopsis :
- * remove('functionName', $arg1, $arg2, ...)
- * (arg1, arg2... are arguments of 'functionName')
- *
- * @return boolean true if no problem
- * @access public
- */
- function drop()
- {
- $id = $this->_makeId(func_get_args());
- return $this->remove($id, $this->_defaultGroup);
- }
-
- /**
- * Make an id for the cache
- *
- * @var array result of func_get_args for the call() or the remove() method
- * @return string id
- * @access private
- */
- function _makeId($arguments)
- {
- $id = serialize($arguments); // Generate a cache id
- if (!$this->_fileNameProtection) {
- $id = md5($id);
- // if fileNameProtection is set to false, then the id has to be hashed
- // because it's a very bad file name in most cases
- }
- return $id;
- }
-
-}
diff --git a/data/module/Cache/Lite/NestedOutput.php b/data/module/Cache/Lite/NestedOutput.php
deleted file mode 100644
index 81ece30d63..0000000000
--- a/data/module/Cache/Lite/NestedOutput.php
+++ /dev/null
@@ -1,56 +0,0 @@
-
-*/
-
-require_once('Cache/Lite/Output.php');
-
-class Cache_Lite_NestedOutput extends Cache_Lite_Output
-{
- private $nestedIds = array();
- private $nestedGroups = array();
-
- /**
- * Start the cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @return boolean|string false if the cache is not hit else the data
- * @access public
- */
- function start($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- $this->nestedIds[] = $id;
- $this->nestedGroups[] = $group;
- $data = $this->get($id, $group, $doNotTestCacheValidity);
- if ($data !== false) {
- return $data;
- }
- ob_start();
- ob_implicit_flush(false);
- return false;
- }
-
- /**
- * Stop the cache
- *
- * @param boolen
- * @return string return contents of cache
- */
- function end()
- {
- $data = ob_get_contents();
- ob_end_clean();
- $id = array_pop($this->nestedIds);
- $group = array_pop($this->nestedGroups);
- $this->save($data, $id, $group);
- return $data;
- }
-
-}
diff --git a/data/module/Cache/Lite/Output.php b/data/module/Cache/Lite/Output.php
deleted file mode 100644
index 87d7c19d8e..0000000000
--- a/data/module/Cache/Lite/Output.php
+++ /dev/null
@@ -1,68 +0,0 @@
-
-*/
-
-require_once('Cache/Lite.php');
-
-class Cache_Lite_Output extends Cache_Lite
-{
-
- // --- Public methods ---
-
- /**
- * Constructor
- *
- * $options is an assoc. To have a look at availables options,
- * see the constructor of the Cache_Lite class in 'Cache_Lite.php'
- *
- * @param array $options options
- * @access public
- */
- function Cache_Lite_Output($options)
- {
- $this->Cache_Lite($options);
- }
-
- /**
- * Start the cache
- *
- * @param string $id cache id
- * @param string $group name of the cache group
- * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
- * @return boolean true if the cache is hit (false else)
- * @access public
- */
- function start($id, $group = 'default', $doNotTestCacheValidity = false)
- {
- $data = $this->get($id, $group, $doNotTestCacheValidity);
- if ($data !== false) {
- echo($data);
- return true;
- }
- ob_start();
- ob_implicit_flush(false);
- return false;
- }
-
- /**
- * Stop the cache
- *
- * @access public
- */
- function end()
- {
- $data = ob_get_contents();
- ob_end_clean();
- $this->save($data, $this->_id, $this->_group);
- echo($data);
- }
-
-}
diff --git a/data/module/HTTP/Request.php b/data/module/HTTP/Request.php
index ef6109f22a..912096f85a 100644
--- a/data/module/HTTP/Request.php
+++ b/data/module/HTTP/Request.php
@@ -409,7 +409,7 @@ function reset($url, $params = array())
*/
function setURL($url)
{
- $this->_url = &new Net_URL($url, $this->_useBrackets);
+ $this->_url = new Net_URL($url, $this->_useBrackets);
if (!empty($this->_url->user) || !empty($this->_url->pass)) {
$this->setBasicAuth($this->_url->user, $this->_url->pass);
@@ -559,13 +559,13 @@ function addPostData($name, $value, $preencoded = false)
$this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value);
}
}
-
+
function addPostDataArray($array, $preencoded = false)
{
foreach($array as $key => $val){
$this->addPostData($key, $val, $preencoded);
}
- }
+ }
/**
* Recursively applies the callback function to the value
@@ -740,7 +740,7 @@ function sendRequest($saveBody = true)
$err = null;
} else {
$this->_notify('connect');
- $this->_sock =& new Net_Socket();
+ $this->_sock = new Net_Socket();
$err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions);
}
PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest());
@@ -753,7 +753,7 @@ function sendRequest($saveBody = true)
$this->_notify('sentRequest');
// Read the response
- $this->_response = &new HTTP_Response($this->_sock, $this->_listeners);
+ $this->_response = new HTTP_Response($this->_sock, $this->_listeners);
$err = $this->_response->process(
$this->_saveBody && $saveBody,
HTTP_REQUEST_METHOD_HEAD != $this->_method
@@ -798,7 +798,7 @@ function sendRequest($saveBody = true)
// Absolute URL
if (preg_match('/^https?:\/\//i', $redirect)) {
- $this->_url = &new Net_URL($redirect);
+ $this->_url = new Net_URL($redirect);
$this->addHeader('Host', $this->_generateHostHeader());
// Absolute path
} elseif ($redirect{0} == '/') {
diff --git a/data/module/Mail.php b/data/module/Mail.php
deleted file mode 100644
index 75132ac2a6..0000000000
--- a/data/module/Mail.php
+++ /dev/null
@@ -1,270 +0,0 @@
-
- * @copyright 1997-2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Mail.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-require_once 'PEAR.php';
-
-/**
- * PEAR's Mail:: interface. Defines the interface for implementing
- * mailers under the PEAR hierarchy, and provides supporting functions
- * useful in multiple mailer backends.
- *
- * @access public
- * @version $Revision: 294747 $
- * @package Mail
- */
-class Mail
-{
- /**
- * Line terminator used for separating header lines.
- * @var string
- */
- var $sep = "\r\n";
-
- /**
- * Provides an interface for generating Mail:: objects of various
- * types
- *
- * @param string $driver The kind of Mail:: object to instantiate.
- * @param array $params The parameters to pass to the Mail:: object.
- * @return object Mail a instance of the driver class or if fails a PEAR Error
- * @access public
- */
- function &factory($driver, $params = array())
- {
- $driver = strtolower($driver);
- @include_once 'Mail/' . $driver . '.php';
- $class = 'Mail_' . $driver;
- if (class_exists($class)) {
- $mailer = new $class($params);
- return $mailer;
- } else {
- return PEAR::raiseError('Unable to find class for driver ' . $driver);
- }
- }
-
- /**
- * Implements Mail::send() function using php's built-in mail()
- * command.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- *
- * @access public
- * @deprecated use Mail_mail::send instead
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- // if we're passed an array of recipients, implode it.
- if (is_array($recipients)) {
- $recipients = implode(', ', $recipients);
- }
-
- // get the Subject out of the headers array so that we can
- // pass it as a seperate argument to mail().
- $subject = '';
- if (isset($headers['Subject'])) {
- $subject = $headers['Subject'];
- unset($headers['Subject']);
- }
-
- // flatten the headers out.
- list(, $text_headers) = Mail::prepareHeaders($headers);
-
- return mail($recipients, $subject, $body, $text_headers);
- }
-
- /**
- * Sanitize an array of mail headers by removing any additional header
- * strings present in a legitimate header's value. The goal of this
- * filter is to prevent mail injection attacks.
- *
- * @param array $headers The associative array of headers to sanitize.
- *
- * @access private
- */
- function _sanitizeHeaders(&$headers)
- {
- foreach ($headers as $key => $value) {
- $headers[$key] =
- preg_replace('=((||0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i',
- null, $value);
- }
- }
-
- /**
- * Take an array of mail headers and return a string containing
- * text usable in sending a message.
- *
- * @param array $headers The array of headers to prepare, in an associative
- * array, where the array key is the header name (ie,
- * 'Subject'), and the array value is the header
- * value (ie, 'test'). The header produced from those
- * values would be 'Subject: test'.
- *
- * @return mixed Returns false if it encounters a bad address,
- * otherwise returns an array containing two
- * elements: Any From: address found in the headers,
- * and the plain text version of the headers.
- * @access private
- */
- function prepareHeaders($headers)
- {
- $lines = array();
- $from = null;
-
- foreach ($headers as $key => $value) {
- if (strcasecmp($key, 'From') === 0) {
- include_once 'Mail/RFC822.php';
- $parser = new Mail_RFC822();
- $addresses = $parser->parseAddressList($value, 'localhost', false);
- if (is_a($addresses, 'PEAR_Error')) {
- return $addresses;
- }
-
- $from = $addresses[0]->mailbox . '@' . $addresses[0]->host;
-
- // Reject envelope From: addresses with spaces.
- if (strstr($from, ' ')) {
- return false;
- }
-
- $lines[] = $key . ': ' . $value;
- } elseif (strcasecmp($key, 'Received') === 0) {
- $received = array();
- if (is_array($value)) {
- foreach ($value as $line) {
- $received[] = $key . ': ' . $line;
- }
- }
- else {
- $received[] = $key . ': ' . $value;
- }
- // Put Received: headers at the top. Spam detectors often
- // flag messages with Received: headers after the Subject:
- // as spam.
- $lines = array_merge($received, $lines);
- } else {
- // If $value is an array (i.e., a list of addresses), convert
- // it to a comma-delimited string of its elements (addresses).
- if (is_array($value)) {
- $value = implode(', ', $value);
- }
- $lines[] = $key . ': ' . $value;
- }
- }
-
- return array($from, join($this->sep, $lines));
- }
-
- /**
- * Take a set of recipients and parse them, returning an array of
- * bare addresses (forward paths) that can be passed to sendmail
- * or an smtp server with the rcpt to: command.
- *
- * @param mixed Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid.
- *
- * @return mixed An array of forward paths (bare addresses) or a PEAR_Error
- * object if the address list could not be parsed.
- * @access private
- */
- function parseRecipients($recipients)
- {
- include_once 'Mail/RFC822.php';
-
- // if we're passed an array, assume addresses are valid and
- // implode them before parsing.
- if (is_array($recipients)) {
- $recipients = implode(', ', $recipients);
- }
-
- // Parse recipients, leaving out all personal info. This is
- // for smtp recipients, etc. All relevant personal information
- // should already be in the headers.
- $addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false);
-
- // If parseAddressList() returned a PEAR_Error object, just return it.
- if (is_a($addresses, 'PEAR_Error')) {
- return $addresses;
- }
-
- $recipients = array();
- if (is_array($addresses)) {
- foreach ($addresses as $ob) {
- $recipients[] = $ob->mailbox . '@' . $ob->host;
- }
- }
-
- return $recipients;
- }
-
-}
diff --git a/data/module/Mail/RFC822.php b/data/module/Mail/RFC822.php
deleted file mode 100644
index 58d36465cb..0000000000
--- a/data/module/Mail/RFC822.php
+++ /dev/null
@@ -1,951 +0,0 @@
-
- * @author Chuck Hagenbuch (A comment), ted@example.com (Ted Bloggs), Barney;';
- * $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true)
- * print_r($structure);
- *
- * @author Richard Heyes
- * @author Chuck Hagenbuch
- * @version $Revision: 294749 $
- * @license BSD
- * @package Mail
- */
-class Mail_RFC822 {
-
- /**
- * The address being parsed by the RFC822 object.
- * @var string $address
- */
- var $address = '';
-
- /**
- * The default domain to use for unqualified addresses.
- * @var string $default_domain
- */
- var $default_domain = 'localhost';
-
- /**
- * Should we return a nested array showing groups, or flatten everything?
- * @var boolean $nestGroups
- */
- var $nestGroups = true;
-
- /**
- * Whether or not to validate atoms for non-ascii characters.
- * @var boolean $validate
- */
- var $validate = true;
-
- /**
- * The array of raw addresses built up as we parse.
- * @var array $addresses
- */
- var $addresses = array();
-
- /**
- * The final array of parsed address information that we build up.
- * @var array $structure
- */
- var $structure = array();
-
- /**
- * The current error message, if any.
- * @var string $error
- */
- var $error = null;
-
- /**
- * An internal counter/pointer.
- * @var integer $index
- */
- var $index = null;
-
- /**
- * The number of groups that have been found in the address list.
- * @var integer $num_groups
- * @access public
- */
- var $num_groups = 0;
-
- /**
- * A variable so that we can tell whether or not we're inside a
- * Mail_RFC822 object.
- * @var boolean $mailRFC822
- */
- var $mailRFC822 = true;
-
- /**
- * A limit after which processing stops
- * @var int $limit
- */
- var $limit = null;
-
- /**
- * Sets up the object. The address must either be set here or when
- * calling parseAddressList(). One or the other.
- *
- * @access public
- * @param string $address The address(es) to validate.
- * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
- * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
- * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
- *
- * @return object Mail_RFC822 A new Mail_RFC822 object.
- */
- function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
- {
- if (isset($address)) $this->address = $address;
- if (isset($default_domain)) $this->default_domain = $default_domain;
- if (isset($nest_groups)) $this->nestGroups = $nest_groups;
- if (isset($validate)) $this->validate = $validate;
- if (isset($limit)) $this->limit = $limit;
- }
-
- /**
- * Starts the whole process. The address must either be set here
- * or when creating the object. One or the other.
- *
- * @access public
- * @param string $address The address(es) to validate.
- * @param string $default_domain Default domain/host etc.
- * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
- * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
- *
- * @return array A structured array of addresses.
- */
- function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
- {
- if (!isset($this) || !isset($this->mailRFC822)) {
- $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
- return $obj->parseAddressList();
- }
-
- if (isset($address)) $this->address = $address;
- if (isset($default_domain)) $this->default_domain = $default_domain;
- if (isset($nest_groups)) $this->nestGroups = $nest_groups;
- if (isset($validate)) $this->validate = $validate;
- if (isset($limit)) $this->limit = $limit;
-
- $this->structure = array();
- $this->addresses = array();
- $this->error = null;
- $this->index = null;
-
- // Unfold any long lines in $this->address.
- $this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
- $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
-
- while ($this->address = $this->_splitAddresses($this->address));
-
- if ($this->address === false || isset($this->error)) {
- require_once 'PEAR.php';
- return PEAR::raiseError($this->error);
- }
-
- // Validate each address individually. If we encounter an invalid
- // address, stop iterating and return an error immediately.
- foreach ($this->addresses as $address) {
- $valid = $this->_validateAddress($address);
-
- if ($valid === false || isset($this->error)) {
- require_once 'PEAR.php';
- return PEAR::raiseError($this->error);
- }
-
- if (!$this->nestGroups) {
- $this->structure = array_merge($this->structure, $valid);
- } else {
- $this->structure[] = $valid;
- }
- }
-
- return $this->structure;
- }
-
- /**
- * Splits an address into separate addresses.
- *
- * @access private
- * @param string $address The addresses to split.
- * @return boolean Success or failure.
- */
- function _splitAddresses($address)
- {
- if (!empty($this->limit) && count($this->addresses) == $this->limit) {
- return '';
- }
-
- if ($this->_isGroup($address) && !isset($this->error)) {
- $split_char = ';';
- $is_group = true;
- } elseif (!isset($this->error)) {
- $split_char = ',';
- $is_group = false;
- } elseif (isset($this->error)) {
- return false;
- }
-
- // Split the string based on the above ten or so lines.
- $parts = explode($split_char, $address);
- $string = $this->_splitCheck($parts, $split_char);
-
- // If a group...
- if ($is_group) {
- // If $string does not contain a colon outside of
- // brackets/quotes etc then something's fubar.
-
- // First check there's a colon at all:
- if (strpos($string, ':') === false) {
- $this->error = 'Invalid address: ' . $string;
- return false;
- }
-
- // Now check it's outside of brackets/quotes:
- if (!$this->_splitCheck(explode(':', $string), ':')) {
- return false;
- }
-
- // We must have a group at this point, so increase the counter:
- $this->num_groups++;
- }
-
- // $string now contains the first full address/group.
- // Add to the addresses array.
- $this->addresses[] = array(
- 'address' => trim($string),
- 'group' => $is_group
- );
-
- // Remove the now stored address from the initial line, the +1
- // is to account for the explode character.
- $address = trim(substr($address, strlen($string) + 1));
-
- // If the next char is a comma and this was a group, then
- // there are more addresses, otherwise, if there are any more
- // chars, then there is another address.
- if ($is_group && substr($address, 0, 1) == ','){
- $address = trim(substr($address, 1));
- return $address;
-
- } elseif (strlen($address) > 0) {
- return $address;
-
- } else {
- return '';
- }
-
- // If you got here then something's off
- return false;
- }
-
- /**
- * Checks for a group at the start of the string.
- *
- * @access private
- * @param string $address The address to check.
- * @return boolean Whether or not there is a group at the start of the string.
- */
- function _isGroup($address)
- {
- // First comma not in quotes, angles or escaped:
- $parts = explode(',', $address);
- $string = $this->_splitCheck($parts, ',');
-
- // Now we have the first address, we can reliably check for a
- // group by searching for a colon that's not escaped or in
- // quotes or angle brackets.
- if (count($parts = explode(':', $string)) > 1) {
- $string2 = $this->_splitCheck($parts, ':');
- return ($string2 !== $string);
- } else {
- return false;
- }
- }
-
- /**
- * A common function that will check an exploded string.
- *
- * @access private
- * @param array $parts The exloded string.
- * @param string $char The char that was exploded on.
- * @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
- */
- function _splitCheck($parts, $char)
- {
- $string = $parts[0];
-
- for ($i = 0; $i < count($parts); $i++) {
- if ($this->_hasUnclosedQuotes($string)
- || $this->_hasUnclosedBrackets($string, '<>')
- || $this->_hasUnclosedBrackets($string, '[]')
- || $this->_hasUnclosedBrackets($string, '()')
- || substr($string, -1) == '\\') {
- if (isset($parts[$i + 1])) {
- $string = $string . $char . $parts[$i + 1];
- } else {
- $this->error = 'Invalid address spec. Unclosed bracket or quotes';
- return false;
- }
- } else {
- $this->index = $i;
- break;
- }
- }
-
- return $string;
- }
-
- /**
- * Checks if a string has unclosed quotes or not.
- *
- * @access private
- * @param string $string The string to check.
- * @return boolean True if there are unclosed quotes inside the string,
- * false otherwise.
- */
- function _hasUnclosedQuotes($string)
- {
- $string = trim($string);
- $iMax = strlen($string);
- $in_quote = false;
- $i = $slashes = 0;
-
- for (; $i < $iMax; ++$i) {
- switch ($string[$i]) {
- case '\\':
- ++$slashes;
- break;
-
- case '"':
- if ($slashes % 2 == 0) {
- $in_quote = !$in_quote;
- }
- // Fall through to default action below.
-
- default:
- $slashes = 0;
- break;
- }
- }
-
- return $in_quote;
- }
-
- /**
- * Checks if a string has an unclosed brackets or not. IMPORTANT:
- * This function handles both angle brackets and square brackets;
- *
- * @access private
- * @param string $string The string to check.
- * @param string $chars The characters to check for.
- * @return boolean True if there are unclosed brackets inside the string, false otherwise.
- */
- function _hasUnclosedBrackets($string, $chars)
- {
- $num_angle_start = substr_count($string, $chars[0]);
- $num_angle_end = substr_count($string, $chars[1]);
-
- $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
- $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
-
- if ($num_angle_start < $num_angle_end) {
- $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
- return false;
- } else {
- return ($num_angle_start > $num_angle_end);
- }
- }
-
- /**
- * Sub function that is used only by hasUnclosedBrackets().
- *
- * @access private
- * @param string $string The string to check.
- * @param integer &$num The number of occurences.
- * @param string $char The character to count.
- * @return integer The number of occurences of $char in $string, adjusted for backslashes.
- */
- function _hasUnclosedBracketsSub($string, &$num, $char)
- {
- $parts = explode($char, $string);
- for ($i = 0; $i < count($parts); $i++){
- if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
- $num--;
- if (isset($parts[$i + 1]))
- $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
- }
-
- return $num;
- }
-
- /**
- * Function to begin checking the address.
- *
- * @access private
- * @param string $address The address to validate.
- * @return mixed False on failure, or a structured array of address information on success.
- */
- function _validateAddress($address)
- {
- $is_group = false;
- $addresses = array();
-
- if ($address['group']) {
- $is_group = true;
-
- // Get the group part of the name
- $parts = explode(':', $address['address']);
- $groupname = $this->_splitCheck($parts, ':');
- $structure = array();
-
- // And validate the group part of the name.
- if (!$this->_validatePhrase($groupname)){
- $this->error = 'Group name did not validate.';
- return false;
- } else {
- // Don't include groups if we are not nesting
- // them. This avoids returning invalid addresses.
- if ($this->nestGroups) {
- $structure = new stdClass;
- $structure->groupname = $groupname;
- }
- }
-
- $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
- }
-
- // If a group then split on comma and put into an array.
- // Otherwise, Just put the whole address in an array.
- if ($is_group) {
- while (strlen($address['address']) > 0) {
- $parts = explode(',', $address['address']);
- $addresses[] = $this->_splitCheck($parts, ',');
- $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
- }
- } else {
- $addresses[] = $address['address'];
- }
-
- // Check that $addresses is set, if address like this:
- // Groupname:;
- // Then errors were appearing.
- if (!count($addresses)){
- $this->error = 'Empty group.';
- return false;
- }
-
- // Trim the whitespace from all of the address strings.
- array_map('trim', $addresses);
-
- // Validate each mailbox.
- // Format could be one of: name
- // geezer@domain.com
- // geezer
- // ... or any other format valid by RFC 822.
- for ($i = 0; $i < count($addresses); $i++) {
- if (!$this->validateMailbox($addresses[$i])) {
- if (empty($this->error)) {
- $this->error = 'Validation failed for: ' . $addresses[$i];
- }
- return false;
- }
- }
-
- // Nested format
- if ($this->nestGroups) {
- if ($is_group) {
- $structure->addresses = $addresses;
- } else {
- $structure = $addresses[0];
- }
-
- // Flat format
- } else {
- if ($is_group) {
- $structure = array_merge($structure, $addresses);
- } else {
- $structure = $addresses;
- }
- }
-
- return $structure;
- }
-
- /**
- * Function to validate a phrase.
- *
- * @access private
- * @param string $phrase The phrase to check.
- * @return boolean Success or failure.
- */
- function _validatePhrase($phrase)
- {
- // Splits on one or more Tab or space.
- $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
-
- $phrase_parts = array();
- while (count($parts) > 0){
- $phrase_parts[] = $this->_splitCheck($parts, ' ');
- for ($i = 0; $i < $this->index + 1; $i++)
- array_shift($parts);
- }
-
- foreach ($phrase_parts as $part) {
- // If quoted string:
- if (substr($part, 0, 1) == '"') {
- if (!$this->_validateQuotedString($part)) {
- return false;
- }
- continue;
- }
-
- // Otherwise it's an atom:
- if (!$this->_validateAtom($part)) return false;
- }
-
- return true;
- }
-
- /**
- * Function to validate an atom which from rfc822 is:
- * atom = 1*
- *
- * If validation ($this->validate) has been turned off, then
- * validateAtom() doesn't actually check anything. This is so that you
- * can split a list of addresses up before encoding personal names
- * (umlauts, etc.), for example.
- *
- * @access private
- * @param string $atom The string to check.
- * @return boolean Success or failure.
- */
- function _validateAtom($atom)
- {
- if (!$this->validate) {
- // Validation has been turned off; assume the atom is okay.
- return true;
- }
-
- // Check for any char from ASCII 0 - ASCII 127
- if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
- return false;
- }
-
- // Check for specials:
- if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
- return false;
- }
-
- // Check for control characters (ASCII 0-31):
- if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Function to validate quoted string, which is:
- * quoted-string = <"> *(qtext/quoted-pair) <">
- *
- * @access private
- * @param string $qstring The string to check
- * @return boolean Success or failure.
- */
- function _validateQuotedString($qstring)
- {
- // Leading and trailing "
- $qstring = substr($qstring, 1, -1);
-
- // Perform check, removing quoted characters first.
- return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
- }
-
- /**
- * Function to validate a mailbox, which is:
- * mailbox = addr-spec ; simple address
- * / phrase route-addr ; name and route-addr
- *
- * @access public
- * @param string &$mailbox The string to check.
- * @return boolean Success or failure.
- */
- function validateMailbox(&$mailbox)
- {
- // A couple of defaults.
- $phrase = '';
- $comment = '';
- $comments = array();
-
- // Catch any RFC822 comments and store them separately.
- $_mailbox = $mailbox;
- while (strlen(trim($_mailbox)) > 0) {
- $parts = explode('(', $_mailbox);
- $before_comment = $this->_splitCheck($parts, '(');
- if ($before_comment != $_mailbox) {
- // First char should be a (.
- $comment = substr(str_replace($before_comment, '', $_mailbox), 1);
- $parts = explode(')', $comment);
- $comment = $this->_splitCheck($parts, ')');
- $comments[] = $comment;
-
- // +2 is for the brackets
- $_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2);
- } else {
- break;
- }
- }
-
- foreach ($comments as $comment) {
- $mailbox = str_replace("($comment)", '', $mailbox);
- }
-
- $mailbox = trim($mailbox);
-
- // Check for name + route-addr
- if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
- $parts = explode('<', $mailbox);
- $name = $this->_splitCheck($parts, '<');
-
- $phrase = trim($name);
- $route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
-
- if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
- return false;
- }
-
- // Only got addr-spec
- } else {
- // First snip angle brackets if present.
- if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
- $addr_spec = substr($mailbox, 1, -1);
- } else {
- $addr_spec = $mailbox;
- }
-
- if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
- return false;
- }
- }
-
- // Construct the object that will be returned.
- $mbox = new stdClass();
-
- // Add the phrase (even if empty) and comments
- $mbox->personal = $phrase;
- $mbox->comment = isset($comments) ? $comments : array();
-
- if (isset($route_addr)) {
- $mbox->mailbox = $route_addr['local_part'];
- $mbox->host = $route_addr['domain'];
- $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
- } else {
- $mbox->mailbox = $addr_spec['local_part'];
- $mbox->host = $addr_spec['domain'];
- }
-
- $mailbox = $mbox;
- return true;
- }
-
- /**
- * This function validates a route-addr which is:
- * route-addr = "<" [route] addr-spec ">"
- *
- * Angle brackets have already been removed at the point of
- * getting to this function.
- *
- * @access private
- * @param string $route_addr The string to check.
- * @return mixed False on failure, or an array containing validated address/route information on success.
- */
- function _validateRouteAddr($route_addr)
- {
- // Check for colon.
- if (strpos($route_addr, ':') !== false) {
- $parts = explode(':', $route_addr);
- $route = $this->_splitCheck($parts, ':');
- } else {
- $route = $route_addr;
- }
-
- // If $route is same as $route_addr then the colon was in
- // quotes or brackets or, of course, non existent.
- if ($route === $route_addr){
- unset($route);
- $addr_spec = $route_addr;
- if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
- return false;
- }
- } else {
- // Validate route part.
- if (($route = $this->_validateRoute($route)) === false) {
- return false;
- }
-
- $addr_spec = substr($route_addr, strlen($route . ':'));
-
- // Validate addr-spec part.
- if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
- return false;
- }
- }
-
- if (isset($route)) {
- $return['adl'] = $route;
- } else {
- $return['adl'] = '';
- }
-
- $return = array_merge($return, $addr_spec);
- return $return;
- }
-
- /**
- * Function to validate a route, which is:
- * route = 1#("@" domain) ":"
- *
- * @access private
- * @param string $route The string to check.
- * @return mixed False on failure, or the validated $route on success.
- */
- function _validateRoute($route)
- {
- // Split on comma.
- $domains = explode(',', trim($route));
-
- foreach ($domains as $domain) {
- $domain = str_replace('@', '', trim($domain));
- if (!$this->_validateDomain($domain)) return false;
- }
-
- return $route;
- }
-
- /**
- * Function to validate a domain, though this is not quite what
- * you expect of a strict internet domain.
- *
- * domain = sub-domain *("." sub-domain)
- *
- * @access private
- * @param string $domain The string to check.
- * @return mixed False on failure, or the validated domain on success.
- */
- function _validateDomain($domain)
- {
- // Note the different use of $subdomains and $sub_domains
- $subdomains = explode('.', $domain);
-
- while (count($subdomains) > 0) {
- $sub_domains[] = $this->_splitCheck($subdomains, '.');
- for ($i = 0; $i < $this->index + 1; $i++)
- array_shift($subdomains);
- }
-
- foreach ($sub_domains as $sub_domain) {
- if (!$this->_validateSubdomain(trim($sub_domain)))
- return false;
- }
-
- // Managed to get here, so return input.
- return $domain;
- }
-
- /**
- * Function to validate a subdomain:
- * subdomain = domain-ref / domain-literal
- *
- * @access private
- * @param string $subdomain The string to check.
- * @return boolean Success or failure.
- */
- function _validateSubdomain($subdomain)
- {
- if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
- if (!$this->_validateDliteral($arr[1])) return false;
- } else {
- if (!$this->_validateAtom($subdomain)) return false;
- }
-
- // Got here, so return successful.
- return true;
- }
-
- /**
- * Function to validate a domain literal:
- * domain-literal = "[" *(dtext / quoted-pair) "]"
- *
- * @access private
- * @param string $dliteral The string to check.
- * @return boolean Success or failure.
- */
- function _validateDliteral($dliteral)
- {
- return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\';
- }
-
- /**
- * Function to validate an addr-spec.
- *
- * addr-spec = local-part "@" domain
- *
- * @access private
- * @param string $addr_spec The string to check.
- * @return mixed False on failure, or the validated addr-spec on success.
- */
- function _validateAddrSpec($addr_spec)
- {
- $addr_spec = trim($addr_spec);
-
- // Split on @ sign if there is one.
- if (strpos($addr_spec, '@') !== false) {
- $parts = explode('@', $addr_spec);
- $local_part = $this->_splitCheck($parts, '@');
- $domain = substr($addr_spec, strlen($local_part . '@'));
-
- // No @ sign so assume the default domain.
- } else {
- $local_part = $addr_spec;
- $domain = $this->default_domain;
- }
-
- if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
- if (($domain = $this->_validateDomain($domain)) === false) return false;
-
- // Got here so return successful.
- return array('local_part' => $local_part, 'domain' => $domain);
- }
-
- /**
- * Function to validate the local part of an address:
- * local-part = word *("." word)
- *
- * @access private
- * @param string $local_part
- * @return mixed False on failure, or the validated local part on success.
- */
- function _validateLocalPart($local_part)
- {
- $parts = explode('.', $local_part);
- $words = array();
-
- // Split the local_part into words.
- while (count($parts) > 0){
- $words[] = $this->_splitCheck($parts, '.');
- for ($i = 0; $i < $this->index + 1; $i++) {
- array_shift($parts);
- }
- }
-
- // Validate each word.
- foreach ($words as $word) {
- // If this word contains an unquoted space, it is invalid. (6.2.4)
- if (strpos($word, ' ') && $word[0] !== '"')
- {
- return false;
- }
-
- if ($this->_validatePhrase(trim($word)) === false) return false;
- }
-
- // Managed to get here, so return the input.
- return $local_part;
- }
-
- /**
- * Returns an approximate count of how many addresses are in the
- * given string. This is APPROXIMATE as it only splits based on a
- * comma which has no preceding backslash. Could be useful as
- * large amounts of addresses will end up producing *large*
- * structures when used with parseAddressList().
- *
- * @param string $data Addresses to count
- * @return int Approximate count
- */
- function approximateCount($data)
- {
- return count(preg_split('/(?@. This can be sufficient for most
- * people. Optional stricter mode can be utilised which restricts
- * mailbox characters allowed to alphanumeric, full stop, hyphen
- * and underscore.
- *
- * @param string $data Address to check
- * @param boolean $strict Optional stricter mode
- * @return mixed False if it fails, an indexed array
- * username/domain if it matches
- */
- function isValidInetAddress($data, $strict = false)
- {
- $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
- if (preg_match($regex, trim($data), $matches)) {
- return array($matches[1], $matches[2]);
- } else {
- return false;
- }
- }
-
-}
diff --git a/data/module/Mail/mail.php b/data/module/Mail/mail.php
deleted file mode 100644
index 1754706425..0000000000
--- a/data/module/Mail/mail.php
+++ /dev/null
@@ -1,168 +0,0 @@
-
- * @copyright 2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail/
- */
-
-/**
- * internal PHP-mail() implementation of the PEAR Mail:: interface.
- * @package Mail
- * @version $Revision$
- */
-class Mail_mail extends Mail {
-
- /**
- * Any arguments to pass to the mail() function.
- * @var string
- */
- var $_params = '';
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_mail:: object based on the parameters
- * passed in.
- *
- * @param array $params Extra arguments for the mail() function.
- */
- function Mail_mail($params = null)
- {
- // The other mail implementations accept parameters as arrays.
- // In the interest of being consistent, explode an array into
- // a string of parameter arguments.
- if (is_array($params)) {
- $this->_params = join(' ', $params);
- } else {
- $this->_params = $params;
- }
-
- /* Because the mail() function may pass headers as command
- * line arguments, we can't guarantee the use of the standard
- * "\r\n" separator. Instead, we use the system's native line
- * separator. */
- if (defined('PHP_EOL')) {
- $this->sep = PHP_EOL;
- } else {
- $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
- }
- }
-
- /**
- * Implements Mail_mail::send() function using php's built-in mail()
- * command.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- *
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- // If we're passed an array of recipients, implode it.
- if (is_array($recipients)) {
- $recipients = implode(', ', $recipients);
- }
-
- // Get the Subject out of the headers array so that we can
- // pass it as a seperate argument to mail().
- $subject = '';
- if (isset($headers['Subject'])) {
- $subject = $headers['Subject'];
- unset($headers['Subject']);
- }
-
- // Also remove the To: header. The mail() function will add its own
- // To: header based on the contents of $recipients.
- unset($headers['To']);
-
- // Flatten the headers out.
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- return $headerElements;
- }
- list(, $text_headers) = $headerElements;
-
- // We only use mail()'s optional fifth parameter if the additional
- // parameters have been provided and we're not running in safe mode.
- if (empty($this->_params) || ini_get('safe_mode')) {
- $result = mail($recipients, $subject, $body, $text_headers);
- } else {
- $result = mail($recipients, $subject, $body, $text_headers,
- $this->_params);
- }
-
- // If the mail() function returned failure, we need to create a
- // PEAR_Error object and return it instead of the boolean result.
- if ($result === false) {
- $result = PEAR::raiseError('mail() returned failure');
- }
-
- return $result;
- }
-
-}
diff --git a/data/module/Mail/mime.php b/data/module/Mail/mime.php
deleted file mode 100644
index c5dd305fab..0000000000
--- a/data/module/Mail/mime.php
+++ /dev/null
@@ -1,1468 +0,0 @@
-
- * Copyright (c) 2003-2006, PEAR
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the authors, nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Tomas V.V. Cox
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @author Aleksander Machniak
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail_mime
- *
- * This class is based on HTML Mime Mail class from
- * Richard Heyes which was based also
- * in the mime_mail.class by Tobias Ratschiller
- * and Sascha Schumann
- */
-
-
-/**
- * require PEAR
- *
- * This package depends on PEAR to raise errors.
- */
-require_once 'PEAR.php';
-
-/**
- * require Mail_mimePart
- *
- * Mail_mimePart contains the code required to
- * create all the different parts a mail can
- * consist of.
- */
-require_once 'Mail/mimePart.php';
-
-
-/**
- * The Mail_Mime class provides an OO interface to create MIME
- * enabled email messages. This way you can create emails that
- * contain plain-text bodies, HTML bodies, attachments, inline
- * images and specific headers.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Tomas V.V. Cox
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Mail_mime
- */
-class Mail_mime
-{
- /**
- * Contains the plain text part of the email
- *
- * @var string
- * @access private
- */
- var $_txtbody;
-
- /**
- * Contains the html part of the email
- *
- * @var string
- * @access private
- */
- var $_htmlbody;
-
- /**
- * list of the attached images
- *
- * @var array
- * @access private
- */
- var $_html_images = array();
-
- /**
- * list of the attachements
- *
- * @var array
- * @access private
- */
- var $_parts = array();
-
- /**
- * Headers for the mail
- *
- * @var array
- * @access private
- */
- var $_headers = array();
-
- /**
- * Build parameters
- *
- * @var array
- * @access private
- */
- var $_build_params = array(
- // What encoding to use for the headers
- // Options: quoted-printable or base64
- 'head_encoding' => 'quoted-printable',
- // What encoding to use for plain text
- // Options: 7bit, 8bit, base64, or quoted-printable
- 'text_encoding' => 'quoted-printable',
- // What encoding to use for html
- // Options: 7bit, 8bit, base64, or quoted-printable
- 'html_encoding' => 'quoted-printable',
- // The character set to use for html
- 'html_charset' => 'ISO-8859-1',
- // The character set to use for text
- 'text_charset' => 'ISO-8859-1',
- // The character set to use for headers
- 'head_charset' => 'ISO-8859-1',
- // End-of-line sequence
- 'eol' => "\r\n",
- // Delay attachment files IO until building the message
- 'delay_file_io' => false
- );
-
- /**
- * Constructor function
- *
- * @param mixed $params Build parameters that change the way the email
- * is built. Should be an associative array.
- * See $_build_params.
- *
- * @return void
- * @access public
- */
- function Mail_mime($params = array())
- {
- // Backward-compatible EOL setting
- if (is_string($params)) {
- $this->_build_params['eol'] = $params;
- } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
- $this->_build_params['eol'] = MAIL_MIME_CRLF;
- }
-
- // Update build parameters
- if (!empty($params) && is_array($params)) {
- while (list($key, $value) = each($params)) {
- $this->_build_params[$key] = $value;
- }
- }
- }
-
- /**
- * Set build parameter value
- *
- * @param string $name Parameter name
- * @param string $value Parameter value
- *
- * @return void
- * @access public
- * @since 1.6.0
- */
- function setParam($name, $value)
- {
- $this->_build_params[$name] = $value;
- }
-
- /**
- * Get build parameter value
- *
- * @param string $name Parameter name
- *
- * @return mixed Parameter value
- * @access public
- * @since 1.6.0
- */
- function getParam($name)
- {
- return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
- }
-
- /**
- * Accessor function to set the body text. Body text is used if
- * it's not an html mail being sent or else is used to fill the
- * text/plain part that emails clients who don't support
- * html should show.
- *
- * @param string $data Either a string or
- * the file name with the contents
- * @param bool $isfile If true the first param should be treated
- * as a file name, else as a string (default)
- * @param bool $append If true the text or file is appended to
- * the existing body, else the old body is
- * overwritten
- *
- * @return mixed True on success or PEAR_Error object
- * @access public
- */
- function setTXTBody($data, $isfile = false, $append = false)
- {
- if (!$isfile) {
- if (!$append) {
- $this->_txtbody = $data;
- } else {
- $this->_txtbody .= $data;
- }
- } else {
- $cont = $this->_file2str($data);
- if (PEAR::isError($cont)) {
- return $cont;
- }
- if (!$append) {
- $this->_txtbody = $cont;
- } else {
- $this->_txtbody .= $cont;
- }
- }
- return true;
- }
-
- /**
- * Get message text body
- *
- * @return string Text body
- * @access public
- * @since 1.6.0
- */
- function getTXTBody()
- {
- return $this->_txtbody;
- }
-
- /**
- * Adds a html part to the mail.
- *
- * @param string $data Either a string or the file name with the
- * contents
- * @param bool $isfile A flag that determines whether $data is a
- * filename, or a string(false, default)
- *
- * @return bool True on success
- * @access public
- */
- function setHTMLBody($data, $isfile = false)
- {
- if (!$isfile) {
- $this->_htmlbody = $data;
- } else {
- $cont = $this->_file2str($data);
- if (PEAR::isError($cont)) {
- return $cont;
- }
- $this->_htmlbody = $cont;
- }
-
- return true;
- }
-
- /**
- * Get message HTML body
- *
- * @return string HTML body
- * @access public
- * @since 1.6.0
- */
- function getHTMLBody()
- {
- return $this->_htmlbody;
- }
-
- /**
- * Adds an image to the list of embedded images.
- *
- * @param string $file The image file name OR image data itself
- * @param string $c_type The content type
- * @param string $name The filename of the image.
- * Only used if $file is the image data.
- * @param bool $isfile Whether $file is a filename or not.
- * Defaults to true
- * @param string $content_id Desired Content-ID of MIME part
- * Defaults to generated unique ID
- *
- * @return bool True on success
- * @access public
- */
- function addHTMLImage($file,
- $c_type='application/octet-stream',
- $name = '',
- $isfile = true,
- $content_id = null
- ) {
- $bodyfile = null;
-
- if ($isfile) {
- // Don't load file into memory
- if ($this->_build_params['delay_file_io']) {
- $filedata = null;
- $bodyfile = $file;
- } else {
- if (PEAR::isError($filedata = $this->_file2str($file))) {
- return $filedata;
- }
- }
- $filename = ($name ? $name : $file);
- } else {
- $filedata = $file;
- $filename = $name;
- }
-
- if (!$content_id) {
- $content_id = md5(uniqid(time()));
- }
-
- $this->_html_images[] = array(
- 'body' => $filedata,
- 'body_file' => $bodyfile,
- 'name' => $filename,
- 'c_type' => $c_type,
- 'cid' => $content_id
- );
-
- return true;
- }
-
- /**
- * Adds a file to the list of attachments.
- *
- * @param string $file The file name of the file to attach
- * or the file contents itself
- * @param string $c_type The content type
- * @param string $name The filename of the attachment
- * Only use if $file is the contents
- * @param bool $isfile Whether $file is a filename or not. Defaults to true
- * @param string $encoding The type of encoding to use. Defaults to base64.
- * Possible values: 7bit, 8bit, base64 or quoted-printable.
- * @param string $disposition The content-disposition of this file
- * Defaults to attachment.
- * Possible values: attachment, inline.
- * @param string $charset The character set of attachment's content.
- * @param string $language The language of the attachment
- * @param string $location The RFC 2557.4 location of the attachment
- * @param string $n_encoding Encoding of the attachment's name in Content-Type
- * By default filenames are encoded using RFC2231 method
- * Here you can set RFC2047 encoding (quoted-printable
- * or base64) instead
- * @param string $f_encoding Encoding of the attachment's filename
- * in Content-Disposition header.
- * @param string $description Content-Description header
- * @param string $h_charset The character set of the headers e.g. filename
- * If not specified, $charset will be used
- *
- * @return mixed True on success or PEAR_Error object
- * @access public
- */
- function addAttachment($file,
- $c_type = 'application/octet-stream',
- $name = '',
- $isfile = true,
- $encoding = 'base64',
- $disposition = 'attachment',
- $charset = '',
- $language = '',
- $location = '',
- $n_encoding = null,
- $f_encoding = null,
- $description = '',
- $h_charset = null
- ) {
- $bodyfile = null;
-
- if ($isfile) {
- // Don't load file into memory
- if ($this->_build_params['delay_file_io']) {
- $filedata = null;
- $bodyfile = $file;
- } else {
- if (PEAR::isError($filedata = $this->_file2str($file))) {
- return $filedata;
- }
- }
- // Force the name the user supplied, otherwise use $file
- $filename = ($name ? $name : $file);
- } else {
- $filedata = $file;
- $filename = $name;
- }
-
- if (!strlen($filename)) {
- $msg = "The supplied filename for the attachment can't be empty";
- $err = PEAR::raiseError($msg);
- return $err;
- }
- $filename = $this->_basename($filename);
-
- $this->_parts[] = array(
- 'body' => $filedata,
- 'body_file' => $bodyfile,
- 'name' => $filename,
- 'c_type' => $c_type,
- 'charset' => $charset,
- 'encoding' => $encoding,
- 'language' => $language,
- 'location' => $location,
- 'disposition' => $disposition,
- 'description' => $description,
- 'name_encoding' => $n_encoding,
- 'filename_encoding' => $f_encoding,
- 'headers_charset' => $h_charset,
- );
-
- return true;
- }
-
- /**
- * Get the contents of the given file name as string
- *
- * @param string $file_name Path of file to process
- *
- * @return string Contents of $file_name
- * @access private
- */
- function &_file2str($file_name)
- {
- // Check state of file and raise an error properly
- if (!file_exists($file_name)) {
- $err = PEAR::raiseError('File not found: ' . $file_name);
- return $err;
- }
- if (!is_file($file_name)) {
- $err = PEAR::raiseError('Not a regular file: ' . $file_name);
- return $err;
- }
- if (!is_readable($file_name)) {
- $err = PEAR::raiseError('File is not readable: ' . $file_name);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime and read file contents
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
- $cont = file_get_contents($file_name);
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- return $cont;
- }
-
- /**
- * Adds a text subpart to the mimePart object and
- * returns it during the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created.
- * @param string $text The text to add.
- *
- * @return object The text mimePart object
- * @access private
- */
- function &_addTextPart(&$obj, $text)
- {
- $params['content_type'] = 'text/plain';
- $params['encoding'] = $this->_build_params['text_encoding'];
- $params['charset'] = $this->_build_params['text_charset'];
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- $ret = $obj->addSubpart($text, $params);
- return $ret;
- } else {
- $ret = new Mail_mimePart($text, $params);
- return $ret;
- }
- }
-
- /**
- * Adds a html subpart to the mimePart object and
- * returns it during the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created.
- *
- * @return object The html mimePart object
- * @access private
- */
- function &_addHtmlPart(&$obj)
- {
- $params['content_type'] = 'text/html';
- $params['encoding'] = $this->_build_params['html_encoding'];
- $params['charset'] = $this->_build_params['html_charset'];
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- $ret = $obj->addSubpart($this->_htmlbody, $params);
- return $ret;
- } else {
- $ret = new Mail_mimePart($this->_htmlbody, $params);
- return $ret;
- }
- }
-
- /**
- * Creates a new mimePart object, using multipart/mixed as
- * the initial content-type and returns it during the
- * build process.
- *
- * @return object The multipart/mixed mimePart object
- * @access private
- */
- function &_addMixedPart()
- {
- $params = array();
- $params['content_type'] = 'multipart/mixed';
- $params['eol'] = $this->_build_params['eol'];
-
- // Create empty multipart/mixed Mail_mimePart object to return
- $ret = new Mail_mimePart('', $params);
- return $ret;
- }
-
- /**
- * Adds a multipart/alternative part to a mimePart
- * object (or creates one), and returns it during
- * the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created.
- *
- * @return object The multipart/mixed mimePart object
- * @access private
- */
- function &_addAlternativePart(&$obj)
- {
- $params['content_type'] = 'multipart/alternative';
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- return $obj->addSubpart('', $params);
- } else {
- $ret = new Mail_mimePart('', $params);
- return $ret;
- }
- }
-
- /**
- * Adds a multipart/related part to a mimePart
- * object (or creates one), and returns it during
- * the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created
- *
- * @return object The multipart/mixed mimePart object
- * @access private
- */
- function &_addRelatedPart(&$obj)
- {
- $params['content_type'] = 'multipart/related';
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- return $obj->addSubpart('', $params);
- } else {
- $ret = new Mail_mimePart('', $params);
- return $ret;
- }
- }
-
- /**
- * Adds an html image subpart to a mimePart object
- * and returns it during the build process.
- *
- * @param object &$obj The mimePart to add the image to
- * @param array $value The image information
- *
- * @return object The image mimePart object
- * @access private
- */
- function &_addHtmlImagePart(&$obj, $value)
- {
- $params['content_type'] = $value['c_type'];
- $params['encoding'] = 'base64';
- $params['disposition'] = 'inline';
- $params['filename'] = $value['name'];
- $params['cid'] = $value['cid'];
- $params['body_file'] = $value['body_file'];
- $params['eol'] = $this->_build_params['eol'];
-
- if (!empty($value['name_encoding'])) {
- $params['name_encoding'] = $value['name_encoding'];
- }
- if (!empty($value['filename_encoding'])) {
- $params['filename_encoding'] = $value['filename_encoding'];
- }
-
- $ret = $obj->addSubpart($value['body'], $params);
- return $ret;
- }
-
- /**
- * Adds an attachment subpart to a mimePart object
- * and returns it during the build process.
- *
- * @param object &$obj The mimePart to add the image to
- * @param array $value The attachment information
- *
- * @return object The image mimePart object
- * @access private
- */
- function &_addAttachmentPart(&$obj, $value)
- {
- $params['eol'] = $this->_build_params['eol'];
- $params['filename'] = $value['name'];
- $params['encoding'] = $value['encoding'];
- $params['content_type'] = $value['c_type'];
- $params['body_file'] = $value['body_file'];
- $params['disposition'] = isset($value['disposition']) ?
- $value['disposition'] : 'attachment';
-
- // content charset
- if (!empty($value['charset'])) {
- $params['charset'] = $value['charset'];
- }
- // headers charset (filename, description)
- if (!empty($value['headers_charset'])) {
- $params['headers_charset'] = $value['headers_charset'];
- }
- if (!empty($value['language'])) {
- $params['language'] = $value['language'];
- }
- if (!empty($value['location'])) {
- $params['location'] = $value['location'];
- }
- if (!empty($value['name_encoding'])) {
- $params['name_encoding'] = $value['name_encoding'];
- }
- if (!empty($value['filename_encoding'])) {
- $params['filename_encoding'] = $value['filename_encoding'];
- }
- if (!empty($value['description'])) {
- $params['description'] = $value['description'];
- }
-
- $ret = $obj->addSubpart($value['body'], $params);
- return $ret;
- }
-
- /**
- * Returns the complete e-mail, ready to send using an alternative
- * mail delivery method. Note that only the mailpart that is made
- * with Mail_Mime is created. This means that,
- * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF
- * using the $headers parameter!
- *
- * @param string $separation The separation between these two parts.
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- * @param array $headers The extra headers that should be passed
- * to the &headers() function.
- * See that function for more info.
- * @param bool $overwrite Overwrite the existing headers with new.
- *
- * @return mixed The complete e-mail or PEAR error object
- * @access public
- */
- function getMessage($separation = null, $params = null, $headers = null,
- $overwrite = false
- ) {
- if ($separation === null) {
- $separation = $this->_build_params['eol'];
- }
-
- $body = $this->get($params);
-
- if (PEAR::isError($body)) {
- return $body;
- }
-
- $head = $this->txtHeaders($headers, $overwrite);
- $mail = $head . $separation . $body;
- return $mail;
- }
-
- /**
- * Returns the complete e-mail body, ready to send using an alternative
- * mail delivery method.
- *
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- *
- * @return mixed The e-mail body or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function getMessageBody($params = null)
- {
- return $this->get($params, null, true);
- }
-
- /**
- * Writes (appends) the complete e-mail into file.
- *
- * @param string $filename Output file location
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- * @param array $headers The extra headers that should be passed
- * to the &headers() function.
- * See that function for more info.
- * @param bool $overwrite Overwrite the existing headers with new.
- *
- * @return mixed True or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
- {
- // Check state of file and raise an error properly
- if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writable: ' . $filename);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime and read file contents
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
-
- if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
- }
-
- // Write message headers into file (skipping Content-* headers)
- $head = $this->txtHeaders($headers, $overwrite, true);
- if (fwrite($fh, $head) === false) {
- $err = PEAR::raiseError('Error writing to file: ' . $filename);
- return $err;
- }
-
- fclose($fh);
-
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- // Write the rest of the message into file
- $res = $this->get($params, $filename);
-
- return $res ? $res : true;
- }
-
- /**
- * Writes (appends) the complete e-mail body into file.
- *
- * @param string $filename Output file location
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- *
- * @return mixed True or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function saveMessageBody($filename, $params = null)
- {
- // Check state of file and raise an error properly
- if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writable: ' . $filename);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime and read file contents
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
-
- if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
- }
-
- // Write the rest of the message into file
- $res = $this->get($params, $filename, true);
-
- return $res ? $res : true;
- }
-
- /**
- * Builds the multipart message from the list ($this->_parts) and
- * returns the mime content.
- *
- * @param array $params Build parameters that change the way the email
- * is built. Should be associative. See $_build_params.
- * @param resource $filename Output file where to save the message instead of
- * returning it
- * @param boolean $skip_head True if you want to return/save only the message
- * without headers
- *
- * @return mixed The MIME message content string, null or PEAR error object
- * @access public
- */
- function &get($params = null, $filename = null, $skip_head = false)
- {
- if (isset($params)) {
- while (list($key, $value) = each($params)) {
- $this->_build_params[$key] = $value;
- }
- }
-
- if (isset($this->_headers['From'])) {
- // Bug #11381: Illegal characters in domain ID
- if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
- $domainID = $matches[1];
- } else {
- $domainID = '@localhost';
- }
- foreach ($this->_html_images as $i => $img) {
- $cid = $this->_html_images[$i]['cid'];
- if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
- $this->_html_images[$i]['cid'] = $cid . $domainID;
- }
- }
- }
-
- if (count($this->_html_images) && isset($this->_htmlbody)) {
- foreach ($this->_html_images as $key => $value) {
- $regex = array();
- $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
- preg_quote($value['name'], '#') . '\3#';
- $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
- preg_quote($value['name'], '#') . '\1\s*\)#';
-
- $rep = array();
- $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
- $rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
-
- $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
- $this->_html_images[$key]['name']
- = $this->_basename($this->_html_images[$key]['name']);
- }
- }
-
- $this->_checkParams();
-
- $null = null;
- $attachments = count($this->_parts) ? true : false;
- $html_images = count($this->_html_images) ? true : false;
- $html = strlen($this->_htmlbody) ? true : false;
- $text = (!$html && strlen($this->_txtbody)) ? true : false;
-
- switch (true) {
- case $text && !$attachments:
- $message =& $this->_addTextPart($null, $this->_txtbody);
- break;
-
- case !$text && !$html && $attachments:
- $message =& $this->_addMixedPart();
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- case $text && $attachments:
- $message =& $this->_addMixedPart();
- $this->_addTextPart($message, $this->_txtbody);
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- case $html && !$attachments && !$html_images:
- if (isset($this->_txtbody)) {
- $message =& $this->_addAlternativePart($null);
- $this->_addTextPart($message, $this->_txtbody);
- $this->_addHtmlPart($message);
- } else {
- $message =& $this->_addHtmlPart($null);
- }
- break;
-
- case $html && !$attachments && $html_images:
- // * Content-Type: multipart/alternative;
- // * text
- // * Content-Type: multipart/related;
- // * html
- // * image...
- if (isset($this->_txtbody)) {
- $message =& $this->_addAlternativePart($null);
- $this->_addTextPart($message, $this->_txtbody);
-
- $ht =& $this->_addRelatedPart($message);
- $this->_addHtmlPart($ht);
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($ht, $this->_html_images[$i]);
- }
- } else {
- // * Content-Type: multipart/related;
- // * html
- // * image...
- $message =& $this->_addRelatedPart($null);
- $this->_addHtmlPart($message);
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($message, $this->_html_images[$i]);
- }
- }
- /*
- // #13444, #9725: the code below was a non-RFC compliant hack
- // * Content-Type: multipart/related;
- // * Content-Type: multipart/alternative;
- // * text
- // * html
- // * image...
- $message =& $this->_addRelatedPart($null);
- if (isset($this->_txtbody)) {
- $alt =& $this->_addAlternativePart($message);
- $this->_addTextPart($alt, $this->_txtbody);
- $this->_addHtmlPart($alt);
- } else {
- $this->_addHtmlPart($message);
- }
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($message, $this->_html_images[$i]);
- }
- */
- break;
-
- case $html && $attachments && !$html_images:
- $message =& $this->_addMixedPart();
- if (isset($this->_txtbody)) {
- $alt =& $this->_addAlternativePart($message);
- $this->_addTextPart($alt, $this->_txtbody);
- $this->_addHtmlPart($alt);
- } else {
- $this->_addHtmlPart($message);
- }
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- case $html && $attachments && $html_images:
- $message =& $this->_addMixedPart();
- if (isset($this->_txtbody)) {
- $alt =& $this->_addAlternativePart($message);
- $this->_addTextPart($alt, $this->_txtbody);
- $rel =& $this->_addRelatedPart($alt);
- } else {
- $rel =& $this->_addRelatedPart($message);
- }
- $this->_addHtmlPart($rel);
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($rel, $this->_html_images[$i]);
- }
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- }
-
- if (!isset($message)) {
- $ret = null;
- return $ret;
- }
-
- // Use saved boundary
- if (!empty($this->_build_params['boundary'])) {
- $boundary = $this->_build_params['boundary'];
- } else {
- $boundary = null;
- }
-
- // Write output to file
- if ($filename) {
- // Append mimePart message headers and body into file
- $headers = $message->encodeToFile($filename, $boundary, $skip_head);
- if (PEAR::isError($headers)) {
- return $headers;
- }
- $this->_headers = array_merge($this->_headers, $headers);
- $ret = null;
- return $ret;
- } else {
- $output = $message->encode($boundary, $skip_head);
- if (PEAR::isError($output)) {
- return $output;
- }
- $this->_headers = array_merge($this->_headers, $output['headers']);
- $body = $output['body'];
- return $body;
- }
- }
-
- /**
- * Returns an array with the headers needed to prepend to the email
- * (MIME-Version and Content-Type). Format of argument is:
- * $array['header-name'] = 'header-value';
- *
- * @param array $xtra_headers Assoc array with any extra headers (optional)
- * (Don't set Content-Type for multipart messages here!)
- * @param bool $overwrite Overwrite already existing headers.
- * @param bool $skip_content Don't return content headers: Content-Type,
- * Content-Disposition and Content-Transfer-Encoding
- *
- * @return array Assoc array with the mime headers
- * @access public
- */
- function &headers($xtra_headers = null, $overwrite = false, $skip_content = false)
- {
- // Add mime version header
- $headers['MIME-Version'] = '1.0';
-
- // Content-Type and Content-Transfer-Encoding headers should already
- // be present if get() was called, but we'll re-set them to make sure
- // we got them when called before get() or something in the message
- // has been changed after get() [#14780]
- if (!$skip_content) {
- $headers += $this->_contentHeaders();
- }
-
- if (!empty($xtra_headers)) {
- $headers = array_merge($headers, $xtra_headers);
- }
-
- if ($overwrite) {
- $this->_headers = array_merge($this->_headers, $headers);
- } else {
- $this->_headers = array_merge($headers, $this->_headers);
- }
-
- $headers = $this->_headers;
-
- if ($skip_content) {
- unset($headers['Content-Type']);
- unset($headers['Content-Transfer-Encoding']);
- unset($headers['Content-Disposition']);
- } else if (!empty($this->_build_params['ctype'])) {
- $headers['Content-Type'] = $this->_build_params['ctype'];
- }
-
- $encodedHeaders = $this->_encodeHeaders($headers);
- return $encodedHeaders;
- }
-
- /**
- * Get the text version of the headers
- * (usefull if you want to use the PHP mail() function)
- *
- * @param array $xtra_headers Assoc array with any extra headers (optional)
- * (Don't set Content-Type for multipart messages here!)
- * @param bool $overwrite Overwrite the existing headers with new.
- * @param bool $skip_content Don't return content headers: Content-Type,
- * Content-Disposition and Content-Transfer-Encoding
- *
- * @return string Plain text headers
- * @access public
- */
- function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
- {
- $headers = $this->headers($xtra_headers, $overwrite, $skip_content);
-
- // Place Received: headers at the beginning of the message
- // Spam detectors often flag messages with it after the Subject: as spam
- if (isset($headers['Received'])) {
- $received = $headers['Received'];
- unset($headers['Received']);
- $headers = array('Received' => $received) + $headers;
- }
-
- $ret = '';
- $eol = $this->_build_params['eol'];
-
- foreach ($headers as $key => $val) {
- if (is_array($val)) {
- foreach ($val as $value) {
- $ret .= "$key: $value" . $eol;
- }
- } else {
- $ret .= "$key: $val" . $eol;
- }
- }
-
- return $ret;
- }
-
- /**
- * Sets message Content-Type header.
- * Use it to build messages with various content-types e.g. miltipart/raport
- * not supported by _contentHeaders() function.
- *
- * @param string $type Type name
- * @param array $params Hash array of header parameters
- *
- * @return void
- * @access public
- * @since 1.7.0
- */
- function setContentType($type, $params = array())
- {
- $header = $type;
-
- $eol = !empty($this->_build_params['eol'])
- ? $this->_build_params['eol'] : "\r\n";
-
- // add parameters
- $token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
- . ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
- if (is_array($params)) {
- foreach ($params as $name => $value) {
- if ($name == 'boundary') {
- $this->_build_params['boundary'] = $value;
- }
- if (!preg_match($token_regexp, $value)) {
- $header .= ";$eol $name=$value";
- } else {
- $value = addcslashes($value, '\\"');
- $header .= ";$eol $name=\"$value\"";
- }
- }
- }
-
- // add required boundary parameter if not defined
- if (preg_match('/^multipart\//i', $type)) {
- if (empty($this->_build_params['boundary'])) {
- $this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
- }
-
- $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
- }
-
- $this->_build_params['ctype'] = $header;
- }
-
- /**
- * Sets the Subject header
- *
- * @param string $subject String to set the subject to.
- *
- * @return void
- * @access public
- */
- function setSubject($subject)
- {
- $this->_headers['Subject'] = $subject;
- }
-
- /**
- * Set an email to the From (the sender) header
- *
- * @param string $email The email address to use
- *
- * @return void
- * @access public
- */
- function setFrom($email)
- {
- $this->_headers['From'] = $email;
- }
-
- /**
- * Add an email to the To header
- * (multiple calls to this method are allowed)
- *
- * @param string $email The email direction to add
- *
- * @return void
- * @access public
- */
- function addTo($email)
- {
- if (isset($this->_headers['To'])) {
- $this->_headers['To'] .= ", $email";
- } else {
- $this->_headers['To'] = $email;
- }
- }
-
- /**
- * Add an email to the Cc (carbon copy) header
- * (multiple calls to this method are allowed)
- *
- * @param string $email The email direction to add
- *
- * @return void
- * @access public
- */
- function addCc($email)
- {
- if (isset($this->_headers['Cc'])) {
- $this->_headers['Cc'] .= ", $email";
- } else {
- $this->_headers['Cc'] = $email;
- }
- }
-
- /**
- * Add an email to the Bcc (blank carbon copy) header
- * (multiple calls to this method are allowed)
- *
- * @param string $email The email direction to add
- *
- * @return void
- * @access public
- */
- function addBcc($email)
- {
- if (isset($this->_headers['Bcc'])) {
- $this->_headers['Bcc'] .= ", $email";
- } else {
- $this->_headers['Bcc'] = $email;
- }
- }
-
- /**
- * Since the PHP send function requires you to specify
- * recipients (To: header) separately from the other
- * headers, the To: header is not properly encoded.
- * To fix this, you can use this public method to
- * encode your recipients before sending to the send
- * function
- *
- * @param string $recipients A comma-delimited list of recipients
- *
- * @return string Encoded data
- * @access public
- */
- function encodeRecipients($recipients)
- {
- $input = array("To" => $recipients);
- $retval = $this->_encodeHeaders($input);
- return $retval["To"] ;
- }
-
- /**
- * Encodes headers as per RFC2047
- *
- * @param array $input The header data to encode
- * @param array $params Extra build parameters
- *
- * @return array Encoded data
- * @access private
- */
- function _encodeHeaders($input, $params = array())
- {
- $build_params = $this->_build_params;
- while (list($key, $value) = each($params)) {
- $build_params[$key] = $value;
- }
-
- foreach ($input as $hdr_name => $hdr_value) {
- if (is_array($hdr_value)) {
- foreach ($hdr_value as $idx => $value) {
- $input[$hdr_name][$idx] = $this->encodeHeader(
- $hdr_name, $value,
- $build_params['head_charset'], $build_params['head_encoding']
- );
- }
- } else {
- $input[$hdr_name] = $this->encodeHeader(
- $hdr_name, $hdr_value,
- $build_params['head_charset'], $build_params['head_encoding']
- );
- }
- }
-
- return $input;
- }
-
- /**
- * Encodes a header as per RFC2047
- *
- * @param string $name The header name
- * @param string $value The header data to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- *
- * @return string Encoded header data (without a name)
- * @access public
- * @since 1.5.3
- */
- function encodeHeader($name, $value, $charset, $encoding)
- {
- return Mail_mimePart::encodeHeader(
- $name, $value, $charset, $encoding, $this->_build_params['eol']
- );
- }
-
- /**
- * Get file's basename (locale independent)
- *
- * @param string $filename Filename
- *
- * @return string Basename
- * @access private
- */
- function _basename($filename)
- {
- // basename() is not unicode safe and locale dependent
- if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
- return preg_replace('/^.*[\\\\\\/]/', '', $filename);
- } else {
- return preg_replace('/^.*[\/]/', '', $filename);
- }
- }
-
- /**
- * Get Content-Type and Content-Transfer-Encoding headers of the message
- *
- * @return array Headers array
- * @access private
- */
- function _contentHeaders()
- {
- $attachments = count($this->_parts) ? true : false;
- $html_images = count($this->_html_images) ? true : false;
- $html = strlen($this->_htmlbody) ? true : false;
- $text = (!$html && strlen($this->_txtbody)) ? true : false;
- $headers = array();
-
- // See get()
- switch (true) {
- case $text && !$attachments:
- $headers['Content-Type'] = 'text/plain';
- break;
-
- case !$text && !$html && $attachments:
- case $text && $attachments:
- case $html && $attachments && !$html_images:
- case $html && $attachments && $html_images:
- $headers['Content-Type'] = 'multipart/mixed';
- break;
-
- case $html && !$attachments && !$html_images && isset($this->_txtbody):
- case $html && !$attachments && $html_images && isset($this->_txtbody):
- $headers['Content-Type'] = 'multipart/alternative';
- break;
-
- case $html && !$attachments && !$html_images && !isset($this->_txtbody):
- $headers['Content-Type'] = 'text/html';
- break;
-
- case $html && !$attachments && $html_images && !isset($this->_txtbody):
- $headers['Content-Type'] = 'multipart/related';
- break;
-
- default:
- return $headers;
- }
-
- $this->_checkParams();
-
- $eol = !empty($this->_build_params['eol'])
- ? $this->_build_params['eol'] : "\r\n";
-
- if ($headers['Content-Type'] == 'text/plain') {
- // single-part message: add charset and encoding
- $charset = 'charset=' . $this->_build_params['text_charset'];
- // place charset parameter in the same line, if possible
- // 26 = strlen("Content-Type: text/plain; ")
- $headers['Content-Type']
- .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
- $headers['Content-Transfer-Encoding']
- = $this->_build_params['text_encoding'];
- } else if ($headers['Content-Type'] == 'text/html') {
- // single-part message: add charset and encoding
- $charset = 'charset=' . $this->_build_params['html_charset'];
- // place charset parameter in the same line, if possible
- $headers['Content-Type']
- .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
- $headers['Content-Transfer-Encoding']
- = $this->_build_params['html_encoding'];
- } else {
- // multipart message: and boundary
- if (!empty($this->_build_params['boundary'])) {
- $boundary = $this->_build_params['boundary'];
- } else if (!empty($this->_headers['Content-Type'])
- && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
- ) {
- $boundary = $m[1];
- } else {
- $boundary = '=_' . md5(rand() . microtime());
- }
-
- $this->_build_params['boundary'] = $boundary;
- $headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
- }
-
- return $headers;
- }
-
- /**
- * Validate and set build parameters
- *
- * @return void
- * @access private
- */
- function _checkParams()
- {
- $encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
-
- $this->_build_params['text_encoding']
- = strtolower($this->_build_params['text_encoding']);
- $this->_build_params['html_encoding']
- = strtolower($this->_build_params['html_encoding']);
-
- if (!in_array($this->_build_params['text_encoding'], $encodings)) {
- $this->_build_params['text_encoding'] = '7bit';
- }
- if (!in_array($this->_build_params['html_encoding'], $encodings)) {
- $this->_build_params['html_encoding'] = '7bit';
- }
-
- // text body
- if ($this->_build_params['text_encoding'] == '7bit'
- && !preg_match('/ascii/i', $this->_build_params['text_charset'])
- && preg_match('/[^\x00-\x7F]/', $this->_txtbody)
- ) {
- $this->_build_params['text_encoding'] = 'quoted-printable';
- }
- // html body
- if ($this->_build_params['html_encoding'] == '7bit'
- && !preg_match('/ascii/i', $this->_build_params['html_charset'])
- && preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
- ) {
- $this->_build_params['html_encoding'] = 'quoted-printable';
- }
- }
-
-} // End of class
diff --git a/data/module/Mail/mimeDecode.php b/data/module/Mail/mimeDecode.php
deleted file mode 100644
index 677d245e34..0000000000
--- a/data/module/Mail/mimeDecode.php
+++ /dev/null
@@ -1,1003 +0,0 @@
-
- * Copyright (c) 2003-2006, PEAR
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the authors, nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author George Schlossnagle
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail_mime
- */
-
-
-/**
- * require PEAR
- *
- * This package depends on PEAR to raise errors.
- */
-require_once 'PEAR.php';
-
-
-/**
- * The Mail_mimeDecode class is used to decode mail/mime messages
- *
- * This class will parse a raw mime email and return the structure.
- * Returned structure is similar to that returned by imap_fetchstructure().
- *
- * +----------------------------- IMPORTANT ------------------------------+
- * | Usage of this class compared to native php extensions such as |
- * | mailparse or imap, is slow and may be feature deficient. If available|
- * | you are STRONGLY recommended to use the php extensions. |
- * +----------------------------------------------------------------------+
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author George Schlossnagle
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Mail_mime
- */
-class Mail_mimeDecode extends PEAR
-{
- /**
- * The raw email to decode
- *
- * @var string
- * @access private
- */
- var $_input;
-
- /**
- * The header part of the input
- *
- * @var string
- * @access private
- */
- var $_header;
-
- /**
- * The body part of the input
- *
- * @var string
- * @access private
- */
- var $_body;
-
- /**
- * If an error occurs, this is used to store the message
- *
- * @var string
- * @access private
- */
- var $_error;
-
- /**
- * Flag to determine whether to include bodies in the
- * returned object.
- *
- * @var boolean
- * @access private
- */
- var $_include_bodies;
-
- /**
- * Flag to determine whether to decode bodies
- *
- * @var boolean
- * @access private
- */
- var $_decode_bodies;
-
- /**
- * Flag to determine whether to decode headers
- *
- * @var boolean
- * @access private
- */
- var $_decode_headers;
-
- /**
- * Flag to determine whether to include attached messages
- * as body in the returned object. Depends on $_include_bodies
- *
- * @var boolean
- * @access private
- */
- var $_rfc822_bodies;
-
- /**
- * Constructor.
- *
- * Sets up the object, initialise the variables, and splits and
- * stores the header and body of the input.
- *
- * @param string The input to decode
- * @access public
- */
- function Mail_mimeDecode($input)
- {
- list($header, $body) = $this->_splitBodyHeader($input);
-
- $this->_input = $input;
- $this->_header = $header;
- $this->_body = $body;
- $this->_decode_bodies = false;
- $this->_include_bodies = true;
- $this->_rfc822_bodies = false;
- }
-
- /**
- * Begins the decoding process. If called statically
- * it will create an object and call the decode() method
- * of it.
- *
- * @param array An array of various parameters that determine
- * various things:
- * include_bodies - Whether to include the body in the returned
- * object.
- * decode_bodies - Whether to decode the bodies
- * of the parts. (Transfer encoding)
- * decode_headers - Whether to decode headers
- * input - If called statically, this will be treated
- * as the input
- * @return object Decoded results
- * @access public
- */
- function decode($params = null)
- {
- // determine if this method has been called statically
- $isStatic = empty($this) || !is_a($this, __CLASS__);
-
- // Have we been called statically?
- // If so, create an object and pass details to that.
- if ($isStatic AND isset($params['input'])) {
-
- $obj = new Mail_mimeDecode($params['input']);
- $structure = $obj->decode($params);
-
- // Called statically but no input
- } elseif ($isStatic) {
- return PEAR::raiseError('Called statically and no input given');
-
- // Called via an object
- } else {
- $this->_include_bodies = isset($params['include_bodies']) ?
- $params['include_bodies'] : false;
- $this->_decode_bodies = isset($params['decode_bodies']) ?
- $params['decode_bodies'] : false;
- $this->_decode_headers = isset($params['decode_headers']) ?
- $params['decode_headers'] : false;
- $this->_rfc822_bodies = isset($params['rfc_822bodies']) ?
- $params['rfc_822bodies'] : false;
-
- $structure = $this->_decode($this->_header, $this->_body);
- if ($structure === false) {
- $structure = $this->raiseError($this->_error);
- }
- }
-
- return $structure;
- }
-
- /**
- * Performs the decoding. Decodes the body string passed to it
- * If it finds certain content-types it will call itself in a
- * recursive fashion
- *
- * @param string Header section
- * @param string Body section
- * @return object Results of decoding process
- * @access private
- */
- function _decode($headers, $body, $default_ctype = 'text/plain')
- {
- $return = new stdClass;
- $return->headers = array();
- $headers = $this->_parseHeaders($headers);
-
- foreach ($headers as $value) {
- $value['value'] = $this->_decode_headers ? $this->_decodeHeader($value['value']) : $value['value'];
- if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
- $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]);
- $return->headers[strtolower($value['name'])][] = $value['value'];
-
- } elseif (isset($return->headers[strtolower($value['name'])])) {
- $return->headers[strtolower($value['name'])][] = $value['value'];
-
- } else {
- $return->headers[strtolower($value['name'])] = $value['value'];
- }
- }
-
-
- foreach ($headers as $key => $value) {
- $headers[$key]['name'] = strtolower($headers[$key]['name']);
- switch ($headers[$key]['name']) {
-
- case 'content-type':
- $content_type = $this->_parseHeaderValue($headers[$key]['value']);
-
- if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
- $return->ctype_primary = $regs[1];
- $return->ctype_secondary = $regs[2];
- }
-
- if (isset($content_type['other'])) {
- foreach($content_type['other'] as $p_name => $p_value) {
- $return->ctype_parameters[$p_name] = $p_value;
- }
- }
- break;
-
- case 'content-disposition':
- $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
- $return->disposition = $content_disposition['value'];
- if (isset($content_disposition['other'])) {
- foreach($content_disposition['other'] as $p_name => $p_value) {
- $return->d_parameters[$p_name] = $p_value;
- }
- }
- break;
-
- case 'content-transfer-encoding':
- $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
- break;
- }
- }
-
- if (isset($content_type)) {
- switch (strtolower($content_type['value'])) {
- case 'text/plain':
- $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
- break;
-
- case 'text/html':
- $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
- break;
-
- case 'multipart/parallel':
- case 'multipart/appledouble': // Appledouble mail
- case 'multipart/report': // RFC1892
- case 'multipart/signed': // PGP
- case 'multipart/digest':
- case 'multipart/alternative':
- case 'multipart/related':
- case 'multipart/mixed':
- case 'application/vnd.wap.multipart.related':
- if(!isset($content_type['other']['boundary'])){
- $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
- return false;
- }
-
- $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';
-
- $parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
- for ($i = 0; $i < count($parts); $i++) {
- list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]);
- $part = $this->_decode($part_header, $part_body, $default_ctype);
- if($part === false)
- $part = $this->raiseError($this->_error);
- $return->parts[] = $part;
- }
- break;
-
- case 'message/rfc822':
- if ($this->_rfc822_bodies) {
- $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
- $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body);
- }
- $obj = new Mail_mimeDecode($body);
- $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies,
- 'decode_bodies' => $this->_decode_bodies,
- 'decode_headers' => $this->_decode_headers));
- unset($obj);
- break;
-
- default:
- if(!isset($content_transfer_encoding['value']))
- $content_transfer_encoding['value'] = '7bit';
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null;
- break;
- }
-
- } else {
- $ctype = explode('/', $default_ctype);
- $return->ctype_primary = $ctype[0];
- $return->ctype_secondary = $ctype[1];
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null;
- }
-
- return $return;
- }
-
- /**
- * Given the output of the above function, this will return an
- * array of references to the parts, indexed by mime number.
- *
- * @param object $structure The structure to go through
- * @param string $mime_number Internal use only.
- * @return array Mime numbers
- */
- function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '')
- {
- $return = array();
- if (!empty($structure->parts)) {
- if ($mime_number != '') {
- $structure->mime_id = $prepend . $mime_number;
- $return[$prepend . $mime_number] = &$structure;
- }
- for ($i = 0; $i < count($structure->parts); $i++) {
-
-
- if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') {
- $prepend = $prepend . $mime_number . '.';
- $_mime_number = '';
- } else {
- $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1));
- }
-
- $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend);
- foreach ($arr as $key => $val) {
- $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key];
- }
- }
- } else {
- if ($mime_number == '') {
- $mime_number = '1';
- }
- $structure->mime_id = $prepend . $mime_number;
- $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure;
- }
-
- return $return;
- }
-
- /**
- * Given a string containing a header and body
- * section, this function will split them (at the first
- * blank line) and return them.
- *
- * @param string Input to split apart
- * @return array Contains header and body section
- * @access private
- */
- function _splitBodyHeader($input)
- {
- if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
- return array($match[1], $match[2]);
- }
- // bug #17325 - empty bodies are allowed. - we just check that at least one line
- // of headers exist..
- if (count(explode("\n",$input))) {
- return array($input, '');
- }
- $this->_error = 'Could not split header and body';
- return false;
- }
-
- /**
- * Parse headers given in $input and return
- * as assoc array.
- *
- * @param string Headers to parse
- * @return array Contains parsed headers
- * @access private
- */
- function _parseHeaders($input)
- {
-
- if ($input !== '') {
- // Unfold the input
- $input = preg_replace("/\r?\n/", "\r\n", $input);
- //#7065 - wrapping.. with encoded stuff.. - probably not needed,
- // wrapping space should only get removed if the trailing item on previous line is a
- // encoded character
- $input = preg_replace("/=\r\n(\t| )+/", '=', $input);
- $input = preg_replace("/\r\n(\t| )+/", ' ', $input);
-
- $headers = explode("\r\n", trim($input));
-
- foreach ($headers as $value) {
- $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
- $hdr_value = substr($value, $pos+1);
- if($hdr_value[0] == ' ')
- $hdr_value = substr($hdr_value, 1);
-
- $return[] = array(
- 'name' => $hdr_name,
- 'value' => $hdr_value
- );
- }
- } else {
- $return = array();
- }
-
- return $return;
- }
-
- /**
- * Function to parse a header value,
- * extract first part, and any secondary
- * parts (after ;) This function is not as
- * robust as it could be. Eg. header comments
- * in the wrong place will probably break it.
- *
- * @param string Header value to parse
- * @return array Contains parsed result
- * @access private
- */
- function _parseHeaderValue($input)
- {
-
- if (($pos = strpos($input, ';')) === false) {
- $input = $this->_decode_headers ? $this->_decodeHeader($input) : $input;
- $return['value'] = trim($input);
- return $return;
- }
-
-
-
- $value = substr($input, 0, $pos);
- $value = $this->_decode_headers ? $this->_decodeHeader($value) : $value;
- $return['value'] = trim($value);
- $input = trim(substr($input, $pos+1));
-
- if (!strlen($input) > 0) {
- return $return;
- }
- // at this point input contains xxxx=".....";zzzz="...."
- // since we are dealing with quoted strings, we need to handle this properly..
- $i = 0;
- $l = strlen($input);
- $key = '';
- $val = false; // our string - including quotes..
- $q = false; // in quote..
- $lq = ''; // last quote..
-
- while ($i < $l) {
-
- $c = $input[$i];
- //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val));
-
- $escaped = false;
- if ($c == '\\') {
- $i++;
- if ($i == $l-1) { // end of string.
- break;
- }
- $escaped = true;
- $c = $input[$i];
- }
-
-
- // state - in key..
- if ($val === false) {
- if (!$escaped && $c == '=') {
- $val = '';
- $key = trim($key);
- $i++;
- continue;
- }
- if (!$escaped && $c == ';') {
- if ($key) { // a key without a value..
- $key= trim($key);
- $return['other'][$key] = '';
- $return['other'][strtolower($key)] = '';
- }
- $key = '';
- }
- $key .= $c;
- $i++;
- continue;
- }
-
- // state - in value.. (as $val is set..)
-
- if ($q === false) {
- // not in quote yet.
- if ((!strlen($val) || $lq !== false) && $c == ' ' || $c == "\t") {
- $i++;
- continue; // skip leading spaces after '=' or after '"'
- }
- if (!$escaped && ($c == '"' || $c == "'")) {
- // start quoted area..
- $q = $c;
- // in theory should not happen raw text in value part..
- // but we will handle it as a merged part of the string..
- $val = !strlen(trim($val)) ? '' : trim($val);
- $i++;
- continue;
- }
- // got end....
- if (!$escaped && $c == ';') {
-
- $val = trim($val);
- $added = false;
- if (preg_match('/\*[0-9]+$/', $key)) {
- // this is the extended aaa*0=...;aaa*1=.... code
- // it assumes the pieces arrive in order, and are valid...
- $key = preg_replace('/\*[0-9]+$/', '', $key);
- if (isset($return['other'][$key])) {
- $return['other'][$key] .= $val;
- if (strtolower($key) != $key) {
- $return['other'][strtolower($key)] .= $val;
- }
- $added = true;
- }
- // continue and use standard setters..
- }
- if (!$added) {
- $return['other'][$key] = $val;
- $return['other'][strtolower($key)] = $val;
- }
- $val = false;
- $key = '';
- $lq = false;
- $i++;
- continue;
- }
-
- $val .= $c;
- $i++;
- continue;
- }
-
- // state - in quote..
- if (!$escaped && $c == $q) { // potential exit state..
-
- // end of quoted string..
- $lq = $q;
- $q = false;
- $i++;
- continue;
- }
-
- // normal char inside of quoted string..
- $val.= $c;
- $i++;
- }
-
- // do we have anything left..
- if (strlen(trim($key)) || $val !== false) {
-
- $val = trim($val);
- $added = false;
- if ($val !== false && preg_match('/\*[0-9]+$/', $key)) {
- // no dupes due to our crazy regexp.
- $key = preg_replace('/\*[0-9]+$/', '', $key);
- if (isset($return['other'][$key])) {
- $return['other'][$key] .= $val;
- if (strtolower($key) != $key) {
- $return['other'][strtolower($key)] .= $val;
- }
- $added = true;
- }
- // continue and use standard setters..
- }
- if (!$added) {
- $return['other'][$key] = $val;
- $return['other'][strtolower($key)] = $val;
- }
- }
- // decode values.
- foreach($return['other'] as $key =>$val) {
- $return['other'][$key] = $this->_decode_headers ? $this->_decodeHeader($val) : $val;
- }
- //print_r($return);
- return $return;
- }
-
- /**
- * This function splits the input based
- * on the given boundary
- *
- * @param string Input to parse
- * @return array Contains array of resulting mime parts
- * @access private
- */
- function _boundarySplit($input, $boundary)
- {
- $parts = array();
-
- $bs_possible = substr($boundary, 2, -2);
- $bs_check = '\"' . $bs_possible . '\"';
-
- if ($boundary == $bs_check) {
- $boundary = $bs_possible;
- }
- $tmp = preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input);
-
- $len = count($tmp) -1;
- for ($i = 1; $i < $len; $i++) {
- if (strlen(trim($tmp[$i]))) {
- $parts[] = $tmp[$i];
- }
- }
-
- // add the last part on if it does not end with the 'closing indicator'
- if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') {
- $parts[] = $tmp[$len];
- }
- return $parts;
- }
-
- /**
- * Given a header, this function will decode it
- * according to RFC2047. Probably not *exactly*
- * conformant, but it does pass all the given
- * examples (in RFC2047).
- *
- * @param string Input header value to decode
- * @return string Decoded header value
- * @access private
- */
- function _decodeHeader($input)
- {
- // Remove white space between encoded-words
- $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
-
- // For each encoded-word...
- while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
-
- $encoded = $matches[1];
- $charset = $matches[2];
- $encoding = $matches[3];
- $text = $matches[4];
-
- switch (strtolower($encoding)) {
- case 'b':
- $text = base64_decode($text);
- break;
-
- case 'q':
- $text = str_replace('_', ' ', $text);
- preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
- foreach($matches[1] as $value)
- $text = str_replace('='.$value, chr(hexdec($value)), $text);
- break;
- }
-
- $input = str_replace($encoded, $text, $input);
- }
-
- return $input;
- }
-
- /**
- * Given a body string and an encoding type,
- * this function will decode and return it.
- *
- * @param string Input body to decode
- * @param string Encoding type to use.
- * @return string Decoded body
- * @access private
- */
- function _decodeBody($input, $encoding = '7bit')
- {
- switch (strtolower($encoding)) {
- case '7bit':
- return $input;
- break;
-
- case 'quoted-printable':
- return $this->_quotedPrintableDecode($input);
- break;
-
- case 'base64':
- return base64_decode($input);
- break;
-
- default:
- return $input;
- }
- }
-
- /**
- * Given a quoted-printable string, this
- * function will decode and return it.
- *
- * @param string Input body to decode
- * @return string Decoded body
- * @access private
- */
- function _quotedPrintableDecode($input)
- {
- // Remove soft line breaks
- $input = preg_replace("/=\r?\n/", '', $input);
-
- // Replace encoded characters
- $input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
-
- return $input;
- }
-
- /**
- * Checks the input for uuencoded files and returns
- * an array of them. Can be called statically, eg:
- *
- * $files =& Mail_mimeDecode::uudecode($some_text);
- *
- * It will check for the begin 666 ... end syntax
- * however and won't just blindly decode whatever you
- * pass it.
- *
- * @param string Input body to look for attahcments in
- * @return array Decoded bodies, filenames and permissions
- * @access public
- * @author Unknown
- */
- function &uudecode($input)
- {
- // Find all uuencoded sections
- preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches);
-
- for ($j = 0; $j < count($matches[3]); $j++) {
-
- $str = $matches[3][$j];
- $filename = $matches[2][$j];
- $fileperm = $matches[1][$j];
-
- $file = '';
- $str = preg_split("/\r?\n/", trim($str));
- $strlen = count($str);
-
- for ($i = 0; $i < $strlen; $i++) {
- $pos = 1;
- $d = 0;
- $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077);
-
- while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) {
- $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
- $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
- $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
- $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20);
- $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
-
- $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
-
- $file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077));
-
- $pos += 4;
- $d += 3;
- }
-
- if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) {
- $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
- $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
- $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
- $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
-
- $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
-
- $pos += 3;
- $d += 2;
- }
-
- if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) {
- $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
- $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
- $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
-
- }
- }
- $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file);
- }
-
- return $files;
- }
-
- /**
- * getSendArray() returns the arguments required for Mail::send()
- * used to build the arguments for a mail::send() call
- *
- * Usage:
- * $mailtext = Full email (for example generated by a template)
- * $decoder = new Mail_mimeDecode($mailtext);
- * $parts = $decoder->getSendArray();
- * if (!PEAR::isError($parts) {
- * list($recipents,$headers,$body) = $parts;
- * $mail = Mail::factory('smtp');
- * $mail->send($recipents,$headers,$body);
- * } else {
- * echo $parts->message;
- * }
- * @return mixed array of recipeint, headers,body or Pear_Error
- * @access public
- * @author Alan Knowles
- */
- function getSendArray()
- {
- // prevent warning if this is not set
- $this->_decode_headers = FALSE;
- $headerlist =$this->_parseHeaders($this->_header);
- $to = "";
- if (!$headerlist) {
- return $this->raiseError("Message did not contain headers");
- }
- foreach($headerlist as $item) {
- $header[$item['name']] = $item['value'];
- switch (strtolower($item['name'])) {
- case "to":
- case "cc":
- case "bcc":
- $to .= ",".$item['value'];
- default:
- break;
- }
- }
- if ($to == "") {
- return $this->raiseError("Message did not contain any recipents");
- }
- $to = substr($to,1);
- return array($to,$header,$this->_body);
- }
-
- /**
- * Returns a xml copy of the output of
- * Mail_mimeDecode::decode. Pass the output in as the
- * argument. This function can be called statically. Eg:
- *
- * $output = $obj->decode();
- * $xml = Mail_mimeDecode::getXML($output);
- *
- * The DTD used for this should have been in the package. Or
- * alternatively you can get it from cvs, or here:
- * http://www.phpguru.org/xmail/xmail.dtd.
- *
- * @param object Input to convert to xml. This should be the
- * output of the Mail_mimeDecode::decode function
- * @return string XML version of input
- * @access public
- */
- function getXML($input)
- {
- $crlf = "\r\n";
- $output = '' . $crlf .
- '' . $crlf .
- '' . $crlf .
- Mail_mimeDecode::_getXML($input) .
- '';
-
- return $output;
- }
-
- /**
- * Function that does the actual conversion to xml. Does a single
- * mimepart at a time.
- *
- * @param object Input to convert to xml. This is a mimepart object.
- * It may or may not contain subparts.
- * @param integer Number of tabs to indent
- * @return string XML version of input
- * @access private
- */
- function _getXML($input, $indent = 1)
- {
- $htab = "\t";
- $crlf = "\r\n";
- $output = '';
- $headers = @(array)$input->headers;
-
- foreach ($headers as $hdr_name => $hdr_value) {
-
- // Multiple headers with this name
- if (is_array($headers[$hdr_name])) {
- for ($i = 0; $i < count($hdr_value); $i++) {
- $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent);
- }
-
- // Only one header of this sort
- } else {
- $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent);
- }
- }
-
- if (!empty($input->parts)) {
- for ($i = 0; $i < count($input->parts); $i++) {
- $output .= $crlf . str_repeat($htab, $indent) . '' . $crlf .
- Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) .
- str_repeat($htab, $indent) . '' . $crlf;
- }
- } elseif (isset($input->body)) {
- $output .= $crlf . str_repeat($htab, $indent) . 'body . ']]>' . $crlf;
- }
-
- return $output;
- }
-
- /**
- * Helper function to _getXML(). Returns xml of a header.
- *
- * @param string Name of header
- * @param string Value of header
- * @param integer Number of tabs to indent
- * @return string XML version of input
- * @access private
- */
- function _getXML_helper($hdr_name, $hdr_value, $indent)
- {
- $htab = "\t";
- $crlf = "\r\n";
- $return = '';
-
- $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value);
- $new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name)));
-
- // Sort out any parameters
- if (!empty($new_hdr_value['other'])) {
- foreach ($new_hdr_value['other'] as $paramname => $paramvalue) {
- $params[] = str_repeat($htab, $indent) . $htab . '' . $crlf .
- str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramname) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramvalue) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . '' . $crlf;
- }
-
- $params = implode('', $params);
- } else {
- $params = '';
- }
-
- $return = str_repeat($htab, $indent) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_name) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_value['value']) . '' . $crlf .
- $params .
- str_repeat($htab, $indent) . '' . $crlf;
-
- return $return;
- }
-
-} // End of class
diff --git a/data/module/Mail/mimePart.php b/data/module/Mail/mimePart.php
deleted file mode 100644
index 60b3601e06..0000000000
--- a/data/module/Mail/mimePart.php
+++ /dev/null
@@ -1,1190 +0,0 @@
-
- * Copyright (c) 2003-2006, PEAR
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the authors, nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @author Aleksander Machniak
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail_mime
- */
-
-
-/**
- * The Mail_mimePart class is used to create MIME E-mail messages
- *
- * This class enables you to manipulate and build a mime email
- * from the ground up. The Mail_Mime class is a userfriendly api
- * to this class for people who aren't interested in the internals
- * of mime mail.
- * This class however allows full control over the email.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @author Aleksander Machniak
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Mail_mime
- */
-class Mail_mimePart
-{
- /**
- * The encoding type of this part
- *
- * @var string
- * @access private
- */
- var $_encoding;
-
- /**
- * An array of subparts
- *
- * @var array
- * @access private
- */
- var $_subparts;
-
- /**
- * The output of this part after being built
- *
- * @var string
- * @access private
- */
- var $_encoded;
-
- /**
- * Headers for this part
- *
- * @var array
- * @access private
- */
- var $_headers;
-
- /**
- * The body of this part (not encoded)
- *
- * @var string
- * @access private
- */
- var $_body;
-
- /**
- * The location of file with body of this part (not encoded)
- *
- * @var string
- * @access private
- */
- var $_body_file;
-
- /**
- * The end-of-line sequence
- *
- * @var string
- * @access private
- */
- var $_eol = "\r\n";
-
- /**
- * Constructor.
- *
- * Sets up the object.
- *
- * @param string $body The body of the mime part if any.
- * @param array $params An associative array of optional parameters:
- * content_type - The content type for this part eg multipart/mixed
- * encoding - The encoding to use, 7bit, 8bit,
- * base64, or quoted-printable
- * charset - Content character set
- * cid - Content ID to apply
- * disposition - Content disposition, inline or attachment
- * dfilename - Filename parameter for content disposition
- * description - Content description
- * name_encoding - Encoding of the attachment name (Content-Type)
- * By default filenames are encoded using RFC2231
- * Here you can set RFC2047 encoding (quoted-printable
- * or base64) instead
- * filename_encoding - Encoding of the attachment filename (Content-Disposition)
- * See 'name_encoding'
- * headers_charset - Charset of the headers e.g. filename, description.
- * If not set, 'charset' will be used
- * eol - End of line sequence. Default: "\r\n"
- * body_file - Location of file with part's body (instead of $body)
- *
- * @access public
- */
- function Mail_mimePart($body = '', $params = array())
- {
- if (!empty($params['eol'])) {
- $this->_eol = $params['eol'];
- } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
- $this->_eol = MAIL_MIMEPART_CRLF;
- }
-
- foreach ($params as $key => $value) {
- switch ($key) {
- case 'encoding':
- $this->_encoding = $value;
- $headers['Content-Transfer-Encoding'] = $value;
- break;
-
- case 'cid':
- $headers['Content-ID'] = '<' . $value . '>';
- break;
-
- case 'location':
- $headers['Content-Location'] = $value;
- break;
-
- case 'body_file':
- $this->_body_file = $value;
- break;
- }
- }
-
- // Default content-type
- if (empty($params['content_type'])) {
- $params['content_type'] = 'text/plain';
- }
-
- // Content-Type
- $headers['Content-Type'] = $params['content_type'];
- if (!empty($params['charset'])) {
- $charset = "charset={$params['charset']}";
- // place charset parameter in the same line, if possible
- if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
- $headers['Content-Type'] .= '; ';
- } else {
- $headers['Content-Type'] .= ';' . $this->_eol . ' ';
- }
- $headers['Content-Type'] .= $charset;
-
- // Default headers charset
- if (!isset($params['headers_charset'])) {
- $params['headers_charset'] = $params['charset'];
- }
- }
- if (!empty($params['filename'])) {
- $headers['Content-Type'] .= ';' . $this->_eol;
- $headers['Content-Type'] .= $this->_buildHeaderParam(
- 'name', $params['filename'],
- !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
- !empty($params['language']) ? $params['language'] : null,
- !empty($params['name_encoding']) ? $params['name_encoding'] : null
- );
- }
-
- // Content-Disposition
- if (!empty($params['disposition'])) {
- $headers['Content-Disposition'] = $params['disposition'];
- if (!empty($params['filename'])) {
- $headers['Content-Disposition'] .= ';' . $this->_eol;
- $headers['Content-Disposition'] .= $this->_buildHeaderParam(
- 'filename', $params['filename'],
- !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
- !empty($params['language']) ? $params['language'] : null,
- !empty($params['filename_encoding']) ? $params['filename_encoding'] : null
- );
- }
- }
-
- if (!empty($params['description'])) {
- $headers['Content-Description'] = $this->encodeHeader(
- 'Content-Description', $params['description'],
- !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
- !empty($params['name_encoding']) ? $params['name_encoding'] : 'quoted-printable',
- $this->_eol
- );
- }
-
- // Default encoding
- if (!isset($this->_encoding)) {
- $this->_encoding = '7bit';
- }
-
- // Assign stuff to member variables
- $this->_encoded = array();
- $this->_headers = $headers;
- $this->_body = $body;
- }
-
- /**
- * Encodes and returns the email. Also stores
- * it in the encoded member variable
- *
- * @param string $boundary Pre-defined boundary string
- *
- * @return An associative array containing two elements,
- * body and headers. The headers element is itself
- * an indexed array. On error returns PEAR error object.
- * @access public
- */
- function encode($boundary=null)
- {
- $encoded =& $this->_encoded;
-
- if (count($this->_subparts)) {
- $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
- $eol = $this->_eol;
-
- $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
-
- $encoded['body'] = '';
-
- for ($i = 0; $i < count($this->_subparts); $i++) {
- $encoded['body'] .= '--' . $boundary . $eol;
- $tmp = $this->_subparts[$i]->encode();
- if (PEAR::isError($tmp)) {
- return $tmp;
- }
- foreach ($tmp['headers'] as $key => $value) {
- $encoded['body'] .= $key . ': ' . $value . $eol;
- }
- $encoded['body'] .= $eol . $tmp['body'] . $eol;
- }
-
- $encoded['body'] .= '--' . $boundary . '--' . $eol;
-
- } else if ($this->_body) {
- $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
- } else if ($this->_body_file) {
- // Temporarily reset magic_quotes_runtime for file reads and writes
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
- $body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding);
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- if (PEAR::isError($body)) {
- return $body;
- }
- $encoded['body'] = $body;
- } else {
- $encoded['body'] = '';
- }
-
- // Add headers to $encoded
- $encoded['headers'] =& $this->_headers;
-
- return $encoded;
- }
-
- /**
- * Encodes and saves the email into file. File must exist.
- * Data will be appended to the file.
- *
- * @param string $filename Output file location
- * @param string $boundary Pre-defined boundary string
- * @param boolean $skip_head True if you don't want to save headers
- *
- * @return array An associative array containing message headers
- * or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function encodeToFile($filename, $boundary=null, $skip_head=false)
- {
- if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writeable: ' . $filename);
- return $err;
- }
-
- if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime for file reads and writes
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
-
- $res = $this->_encodePartToFile($fh, $boundary, $skip_head);
-
- fclose($fh);
-
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- return PEAR::isError($res) ? $res : $this->_headers;
- }
-
- /**
- * Encodes given email part into file
- *
- * @param string $fh Output file handle
- * @param string $boundary Pre-defined boundary string
- * @param boolean $skip_head True if you don't want to save headers
- *
- * @return array True on sucess or PEAR error object
- * @access private
- */
- function _encodePartToFile($fh, $boundary=null, $skip_head=false)
- {
- $eol = $this->_eol;
-
- if (count($this->_subparts)) {
- $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
- $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
- }
-
- if (!$skip_head) {
- foreach ($this->_headers as $key => $value) {
- fwrite($fh, $key . ': ' . $value . $eol);
- }
- $f_eol = $eol;
- } else {
- $f_eol = '';
- }
-
- if (count($this->_subparts)) {
- for ($i = 0; $i < count($this->_subparts); $i++) {
- fwrite($fh, $f_eol . '--' . $boundary . $eol);
- $res = $this->_subparts[$i]->_encodePartToFile($fh);
- if (PEAR::isError($res)) {
- return $res;
- }
- $f_eol = $eol;
- }
-
- fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
-
- } else if ($this->_body) {
- fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding));
- } else if ($this->_body_file) {
- fwrite($fh, $f_eol);
- $res = $this->_getEncodedDataFromFile(
- $this->_body_file, $this->_encoding, $fh
- );
- if (PEAR::isError($res)) {
- return $res;
- }
- }
-
- return true;
- }
-
- /**
- * Adds a subpart to current mime part and returns
- * a reference to it
- *
- * @param string $body The body of the subpart, if any.
- * @param array $params The parameters for the subpart, same
- * as the $params argument for constructor.
- *
- * @return Mail_mimePart A reference to the part you just added. It is
- * crucial if using multipart/* in your subparts that
- * you use =& in your script when calling this function,
- * otherwise you will not be able to add further subparts.
- * @access public
- */
- function &addSubpart($body, $params)
- {
- $this->_subparts[] = new Mail_mimePart($body, $params);
- return $this->_subparts[count($this->_subparts) - 1];
- }
-
- /**
- * Returns encoded data based upon encoding passed to it
- *
- * @param string $data The data to encode.
- * @param string $encoding The encoding type to use, 7bit, base64,
- * or quoted-printable.
- *
- * @return string
- * @access private
- */
- function _getEncodedData($data, $encoding)
- {
- switch ($encoding) {
- case 'quoted-printable':
- return $this->_quotedPrintableEncode($data);
- break;
-
- case 'base64':
- return rtrim(chunk_split(base64_encode($data), 76, $this->_eol));
- break;
-
- case '8bit':
- case '7bit':
- default:
- return $data;
- }
- }
-
- /**
- * Returns encoded data based upon encoding passed to it
- *
- * @param string $filename Data file location
- * @param string $encoding The encoding type to use, 7bit, base64,
- * or quoted-printable.
- * @param resource $fh Output file handle. If set, data will be
- * stored into it instead of returning it
- *
- * @return string Encoded data or PEAR error object
- * @access private
- */
- function _getEncodedDataFromFile($filename, $encoding, $fh=null)
- {
- if (!is_readable($filename)) {
- $err = PEAR::raiseError('Unable to read file: ' . $filename);
- return $err;
- }
-
- if (!($fd = fopen($filename, 'rb'))) {
- $err = PEAR::raiseError('Could not open file: ' . $filename);
- return $err;
- }
-
- $data = '';
-
- switch ($encoding) {
- case 'quoted-printable':
- while (!feof($fd)) {
- $buffer = $this->_quotedPrintableEncode(fgets($fd));
- if ($fh) {
- fwrite($fh, $buffer);
- } else {
- $data .= $buffer;
- }
- }
- break;
-
- case 'base64':
- while (!feof($fd)) {
- // Should read in a multiple of 57 bytes so that
- // the output is 76 bytes per line. Don't use big chunks
- // because base64 encoding is memory expensive
- $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
- $buffer = base64_encode($buffer);
- $buffer = chunk_split($buffer, 76, $this->_eol);
- if (feof($fd)) {
- $buffer = rtrim($buffer);
- }
-
- if ($fh) {
- fwrite($fh, $buffer);
- } else {
- $data .= $buffer;
- }
- }
- break;
-
- case '8bit':
- case '7bit':
- default:
- while (!feof($fd)) {
- $buffer = fread($fd, 1048576); // 1 MB
- if ($fh) {
- fwrite($fh, $buffer);
- } else {
- $data .= $buffer;
- }
- }
- }
-
- fclose($fd);
-
- if (!$fh) {
- return $data;
- }
- }
-
- /**
- * Encodes data to quoted-printable standard.
- *
- * @param string $input The data to encode
- * @param int $line_max Optional max line length. Should
- * not be more than 76 chars
- *
- * @return string Encoded data
- *
- * @access private
- */
- function _quotedPrintableEncode($input , $line_max = 76)
- {
- $eol = $this->_eol;
- /*
- // imap_8bit() is extremely fast, but doesn't handle properly some characters
- if (function_exists('imap_8bit') && $line_max == 76) {
- $input = preg_replace('/\r?\n/', "\r\n", $input);
- $input = imap_8bit($input);
- if ($eol != "\r\n") {
- $input = str_replace("\r\n", $eol, $input);
- }
- return $input;
- }
- */
- $lines = preg_split("/\r?\n/", $input);
- $escape = '=';
- $output = '';
-
- while (list($idx, $line) = each($lines)) {
- $newline = '';
- $i = 0;
-
- while (isset($line[$i])) {
- $char = $line[$i];
- $dec = ord($char);
- $i++;
-
- if (($dec == 32) && (!isset($line[$i]))) {
- // convert space at eol only
- $char = '=20';
- } elseif ($dec == 9 && isset($line[$i])) {
- ; // Do nothing if a TAB is not on eol
- } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
- $char = $escape . sprintf('%02X', $dec);
- } elseif (($dec == 46) && (($newline == '')
- || ((strlen($newline) + strlen("=2E")) >= $line_max))
- ) {
- // Bug #9722: convert full-stop at bol,
- // some Windows servers need this, won't break anything (cipri)
- // Bug #11731: full-stop at bol also needs to be encoded
- // if this line would push us over the line_max limit.
- $char = '=2E';
- }
-
- // Note, when changing this line, also change the ($dec == 46)
- // check line, as it mimics this line due to Bug #11731
- // EOL is not counted
- if ((strlen($newline) + strlen($char)) >= $line_max) {
- // soft line break; " =\r\n" is okay
- $output .= $newline . $escape . $eol;
- $newline = '';
- }
- $newline .= $char;
- } // end of for
- $output .= $newline . $eol;
- unset($lines[$idx]);
- }
- // Don't want last crlf
- $output = substr($output, 0, -1 * strlen($eol));
- return $output;
- }
-
- /**
- * Encodes the paramater of a header.
- *
- * @param string $name The name of the header-parameter
- * @param string $value The value of the paramter
- * @param string $charset The characterset of $value
- * @param string $language The language used in $value
- * @param string $encoding Parameter encoding. If not set, parameter value
- * is encoded according to RFC2231
- * @param int $maxLength The maximum length of a line. Defauls to 75
- *
- * @return string
- *
- * @access private
- */
- function _buildHeaderParam($name, $value, $charset=null, $language=null,
- $encoding=null, $maxLength=75
- ) {
- // RFC 2045:
- // value needs encoding if contains non-ASCII chars or is longer than 78 chars
- if (!preg_match('#[^\x20-\x7E]#', $value)) {
- $token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
- . ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
- if (!preg_match($token_regexp, $value)) {
- // token
- if (strlen($name) + strlen($value) + 3 <= $maxLength) {
- return " {$name}={$value}";
- }
- } else {
- // quoted-string
- $quoted = addcslashes($value, '\\"');
- if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
- return " {$name}=\"{$quoted}\"";
- }
- }
- }
-
- // RFC2047: use quoted-printable/base64 encoding
- if ($encoding == 'quoted-printable' || $encoding == 'base64') {
- return $this->_buildRFC2047Param($name, $value, $charset, $encoding);
- }
-
- // RFC2231:
- $encValue = preg_replace_callback(
- '/([^\x21,\x23,\x24,\x26,\x2B,\x2D,\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])/',
- array($this, '_encodeReplaceCallback'), $value
- );
- $value = "$charset'$language'$encValue";
-
- $header = " {$name}*={$value}";
- if (strlen($header) <= $maxLength) {
- return $header;
- }
-
- $preLength = strlen(" {$name}*0*=");
- $maxLength = max(16, $maxLength - $preLength - 3);
- $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
-
- $headers = array();
- $headCount = 0;
- while ($value) {
- $matches = array();
- $found = preg_match($maxLengthReg, $value, $matches);
- if ($found) {
- $headers[] = " {$name}*{$headCount}*={$matches[0]}";
- $value = substr($value, strlen($matches[0]));
- } else {
- $headers[] = " {$name}*{$headCount}*={$value}";
- $value = '';
- }
- $headCount++;
- }
-
- $headers = implode(';' . $this->_eol, $headers);
- return $headers;
- }
-
- /**
- * Encodes header parameter as per RFC2047 if needed
- *
- * @param string $name The parameter name
- * @param string $value The parameter value
- * @param string $charset The parameter charset
- * @param string $encoding Encoding type (quoted-printable or base64)
- * @param int $maxLength Encoded parameter max length. Default: 76
- *
- * @return string Parameter line
- * @access private
- */
- function _buildRFC2047Param($name, $value, $charset,
- $encoding='quoted-printable', $maxLength=76
- ) {
- // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
- // parameter of a MIME Content-Type or Content-Disposition field",
- // but... it's supported by many clients/servers
- $quoted = '';
-
- if ($encoding == 'base64') {
- $value = base64_encode($value);
- $prefix = '=?' . $charset . '?B?';
- $suffix = '?=';
-
- // 2 x SPACE, 2 x '"', '=', ';'
- $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
- $len = $add_len + strlen($value);
-
- while ($len > $maxLength) {
- // We can cut base64-encoded string every 4 characters
- $real_len = floor(($maxLength - $add_len) / 4) * 4;
- $_quote = substr($value, 0, $real_len);
- $value = substr($value, $real_len);
-
- $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
- $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
- $len = strlen($value) + $add_len;
- }
- $quoted .= $prefix . $value . $suffix;
-
- } else {
- // quoted-printable
- $value = $this->encodeQP($value);
- $prefix = '=?' . $charset . '?Q?';
- $suffix = '?=';
-
- // 2 x SPACE, 2 x '"', '=', ';'
- $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
- $len = $add_len + strlen($value);
-
- while ($len > $maxLength) {
- $length = $maxLength - $add_len;
- // don't break any encoded letters
- if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
- $_quote = $matches[1];
- }
-
- $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
- $value = substr($value, strlen($_quote));
- $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
- $len = strlen($value) + $add_len;
- }
-
- $quoted .= $prefix . $value . $suffix;
- }
-
- return " {$name}=\"{$quoted}\"";
- }
-
- /**
- * Encodes a header as per RFC2047
- *
- * @param string $name The header name
- * @param string $value The header data to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- * @param string $eol End-of-line sequence. Default: "\r\n"
- *
- * @return string Encoded header data (without a name)
- * @access public
- * @since 1.6.1
- */
- function encodeHeader($name, $value, $charset='ISO-8859-1',
- $encoding='quoted-printable', $eol="\r\n"
- ) {
- // Structured headers
- $comma_headers = array(
- 'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
- 'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
- 'resent-sender', 'resent-reply-to',
- 'return-receipt-to', 'disposition-notification-to',
- );
- $other_headers = array(
- 'references', 'in-reply-to', 'message-id', 'resent-message-id',
- );
-
- $name = strtolower($name);
-
- if (in_array($name, $comma_headers)) {
- $separator = ',';
- } else if (in_array($name, $other_headers)) {
- $separator = ' ';
- }
-
- if (!$charset) {
- $charset = 'ISO-8859-1';
- }
-
- // Structured header (make sure addr-spec inside is not encoded)
- if (!empty($separator)) {
- $parts = Mail_mimePart::_explodeQuotedString($separator, $value);
- $value = '';
-
- foreach ($parts as $part) {
- $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
- $part = trim($part);
-
- if (!$part) {
- continue;
- }
- if ($value) {
- $value .= $separator==',' ? $separator.' ' : ' ';
- } else {
- $value = $name . ': ';
- }
-
- // let's find phrase (name) and/or addr-spec
- if (preg_match('/^<\S+@\S+>$/', $part)) {
- $value .= $part;
- } else if (preg_match('/^\S+@\S+$/', $part)) {
- // address without brackets and without name
- $value .= $part;
- } else if (preg_match('/<*\S+@\S+>*$/', $part, $matches)) {
- // address with name (handle name)
- $address = $matches[0];
- $word = str_replace($address, '', $part);
- $word = trim($word);
- // check if phrase requires quoting
- if ($word) {
- // non-ASCII: require encoding
- if (preg_match('#([\x80-\xFF]){1}#', $word)) {
- if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
- // de-quote quoted-string, encoding changes
- // string to atom
- $search = array("\\\"", "\\\\");
- $replace = array("\"", "\\");
- $word = str_replace($search, $replace, $word);
- $word = substr($word, 1, -1);
- }
- // find length of last line
- if (($pos = strrpos($value, $eol)) !== false) {
- $last_len = strlen($value) - $pos;
- } else {
- $last_len = strlen($value);
- }
- $word = Mail_mimePart::encodeHeaderValue(
- $word, $charset, $encoding, $last_len, $eol
- );
- } else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
- && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
- ) {
- // ASCII: quote string if needed
- $word = '"'.addcslashes($word, '\\"').'"';
- }
- }
- $value .= $word.' '.$address;
- } else {
- // addr-spec not found, don't encode (?)
- $value .= $part;
- }
-
- // RFC2822 recommends 78 characters limit, use 76 from RFC2047
- $value = wordwrap($value, 76, $eol . ' ');
- }
-
- // remove header name prefix (there could be EOL too)
- $value = preg_replace(
- '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
- );
-
- } else {
- // Unstructured header
- // non-ASCII: require encoding
- if (preg_match('#([\x80-\xFF]){1}#', $value)) {
- if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
- // de-quote quoted-string, encoding changes
- // string to atom
- $search = array("\\\"", "\\\\");
- $replace = array("\"", "\\");
- $value = str_replace($search, $replace, $value);
- $value = substr($value, 1, -1);
- }
- $value = Mail_mimePart::encodeHeaderValue(
- $value, $charset, $encoding, strlen($name) + 2, $eol
- );
- } else if (strlen($name.': '.$value) > 78) {
- // ASCII: check if header line isn't too long and use folding
- $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
- $tmp = wordwrap($name.': '.$value, 78, $eol . ' ');
- $value = preg_replace('/^'.$name.':\s*/', '', $tmp);
- // hard limit 998 (RFC2822)
- $value = wordwrap($value, 998, $eol . ' ', true);
- }
- }
-
- return $value;
- }
-
- /**
- * Explode quoted string
- *
- * @param string $delimiter Delimiter expression string for preg_match()
- * @param string $string Input string
- *
- * @return array String tokens array
- * @access private
- */
- function _explodeQuotedString($delimiter, $string)
- {
- $result = array();
- $strlen = strlen($string);
-
- for ($q=$p=$i=0; $i < $strlen; $i++) {
- if ($string[$i] == "\""
- && (empty($string[$i-1]) || $string[$i-1] != "\\")
- ) {
- $q = $q ? false : true;
- } else if (!$q && preg_match("/$delimiter/", $string[$i])) {
- $result[] = substr($string, $p, $i - $p);
- $p = $i + 1;
- }
- }
-
- $result[] = substr($string, $p);
- return $result;
- }
-
- /**
- * Encodes a header value as per RFC2047
- *
- * @param string $value The header data to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- * @param int $prefix_len Prefix length. Default: 0
- * @param string $eol End-of-line sequence. Default: "\r\n"
- *
- * @return string Encoded header data
- * @access public
- * @since 1.6.1
- */
- function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n")
- {
- // #17311: Use multibyte aware method (requires mbstring extension)
- if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
- return $result;
- }
-
- // Generate the header using the specified params and dynamicly
- // determine the maximum length of such strings.
- // 75 is the value specified in the RFC.
- $encoding = $encoding == 'base64' ? 'B' : 'Q';
- $prefix = '=?' . $charset . '?' . $encoding .'?';
- $suffix = '?=';
- $maxLength = 75 - strlen($prefix . $suffix);
- $maxLength1stLine = $maxLength - $prefix_len;
-
- if ($encoding == 'B') {
- // Base64 encode the entire string
- $value = base64_encode($value);
-
- // We can cut base64 every 4 characters, so the real max
- // we can get must be rounded down.
- $maxLength = $maxLength - ($maxLength % 4);
- $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);
-
- $cutpoint = $maxLength1stLine;
- $output = '';
-
- while ($value) {
- // Split translated string at every $maxLength
- $part = substr($value, 0, $cutpoint);
- $value = substr($value, $cutpoint);
- $cutpoint = $maxLength;
- // RFC 2047 specifies that any split header should
- // be seperated by a CRLF SPACE.
- if ($output) {
- $output .= $eol . ' ';
- }
- $output .= $prefix . $part . $suffix;
- }
- $value = $output;
- } else {
- // quoted-printable encoding has been selected
- $value = Mail_mimePart::encodeQP($value);
-
- // This regexp will break QP-encoded text at every $maxLength
- // but will not break any encoded letters.
- $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
- $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";
-
- if (strlen($value) > $maxLength1stLine) {
- // Begin with the regexp for the first line.
- $reg = $reg1st;
- $output = '';
- while ($value) {
- // Split translated string at every $maxLength
- // But make sure not to break any translated chars.
- $found = preg_match($reg, $value, $matches);
-
- // After this first line, we need to use a different
- // regexp for the first line.
- $reg = $reg2nd;
-
- // Save the found part and encapsulate it in the
- // prefix & suffix. Then remove the part from the
- // $value_out variable.
- if ($found) {
- $part = $matches[0];
- $len = strlen($matches[0]);
- $value = substr($value, $len);
- } else {
- $part = $value;
- $value = '';
- }
-
- // RFC 2047 specifies that any split header should
- // be seperated by a CRLF SPACE
- if ($output) {
- $output .= $eol . ' ';
- }
- $output .= $prefix . $part . $suffix;
- }
- $value = $output;
- } else {
- $value = $prefix . $value . $suffix;
- }
- }
-
- return $value;
- }
-
- /**
- * Encodes the given string using quoted-printable
- *
- * @param string $str String to encode
- *
- * @return string Encoded string
- * @access public
- * @since 1.6.0
- */
- function encodeQP($str)
- {
- // Bug #17226 RFC 2047 restricts some characters
- // if the word is inside a phrase, permitted chars are only:
- // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
-
- // "=", "_", "?" must be encoded
- $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
- $str = preg_replace_callback(
- $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str
- );
-
- return str_replace(' ', '_', $str);
- }
-
- /**
- * Encodes the given string using base64 or quoted-printable.
- * This method makes sure that encoded-word represents an integral
- * number of characters as per RFC2047.
- *
- * @param string $str String to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- * @param int $prefix_len Prefix length. Default: 0
- * @param string $eol End-of-line sequence. Default: "\r\n"
- *
- * @return string Encoded string
- * @access public
- * @since 1.8.0
- */
- function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
- {
- if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
- return;
- }
-
- $encoding = $encoding == 'base64' ? 'B' : 'Q';
- // 75 is the value specified in the RFC
- $prefix = '=?' . $charset . '?'.$encoding.'?';
- $suffix = '?=';
- $maxLength = 75 - strlen($prefix . $suffix);
-
- // A multi-octet character may not be split across adjacent encoded-words
- // So, we'll loop over each character
- // mb_stlen() with wrong charset will generate a warning here and return null
- $length = mb_strlen($str, $charset);
- $result = '';
- $line_length = $prefix_len;
-
- if ($encoding == 'B') {
- // base64
- $start = 0;
- $prev = '';
-
- for ($i=1; $i<=$length; $i++) {
- // See #17311
- $chunk = mb_substr($str, $start, $i-$start, $charset);
- $chunk = base64_encode($chunk);
- $chunk_len = strlen($chunk);
-
- if ($line_length + $chunk_len == $maxLength || $i == $length) {
- if ($result) {
- $result .= "\n";
- }
- $result .= $chunk;
- $line_length = 0;
- $start = $i;
- } else if ($line_length + $chunk_len > $maxLength) {
- if ($result) {
- $result .= "\n";
- }
- if ($prev) {
- $result .= $prev;
- }
- $line_length = 0;
- $start = $i - 1;
- } else {
- $prev = $chunk;
- }
- }
- } else {
- // quoted-printable
- // see encodeQP()
- $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
-
- for ($i=0; $i<=$length; $i++) {
- $char = mb_substr($str, $i, 1, $charset);
- // RFC recommends underline (instead of =20) in place of the space
- // that's one of the reasons why we're not using iconv_mime_encode()
- if ($char == ' ') {
- $char = '_';
- $char_len = 1;
- } else {
- $char = preg_replace_callback(
- $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char
- );
- $char_len = strlen($char);
- }
-
- if ($line_length + $char_len > $maxLength) {
- if ($result) {
- $result .= "\n";
- }
- $line_length = 0;
- }
-
- $result .= $char;
- $line_length += $char_len;
- }
- }
-
- if ($result) {
- $result = $prefix
- .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
- }
-
- return $result;
- }
-
- /**
- * Callback function to replace extended characters (\x80-xFF) with their
- * ASCII values (RFC2047: quoted-printable)
- *
- * @param array $matches Preg_replace's matches array
- *
- * @return string Encoded character string
- * @access private
- */
- function _qpReplaceCallback($matches)
- {
- return sprintf('=%02X', ord($matches[1]));
- }
-
- /**
- * Callback function to replace extended characters (\x80-xFF) with their
- * ASCII values (RFC2231)
- *
- * @param array $matches Preg_replace's matches array
- *
- * @return string Encoded character string
- * @access private
- */
- function _encodeReplaceCallback($matches)
- {
- return sprintf('%%%02X', ord($matches[1]));
- }
-
-} // End of class
diff --git a/data/module/Mail/mock.php b/data/module/Mail/mock.php
deleted file mode 100644
index 61570ba408..0000000000
--- a/data/module/Mail/mock.php
+++ /dev/null
@@ -1,143 +0,0 @@
-
- * @copyright 2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: mock.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-/**
- * Mock implementation of the PEAR Mail:: interface for testing.
- * @access public
- * @package Mail
- * @version $Revision: 294747 $
- */
-class Mail_mock extends Mail {
-
- /**
- * Array of messages that have been sent with the mock.
- *
- * @var array
- * @access public
- */
- var $sentMessages = array();
-
- /**
- * Callback before sending mail.
- *
- * @var callback
- */
- var $_preSendCallback;
-
- /**
- * Callback after sending mai.
- *
- * @var callback
- */
- var $_postSendCallback;
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_mock:: object based on the parameters
- * passed in. It looks for the following parameters, both optional:
- * preSendCallback Called before an email would be sent.
- * postSendCallback Called after an email would have been sent.
- *
- * @param array Hash containing any parameters.
- * @access public
- */
- function Mail_mock($params)
- {
- if (isset($params['preSendCallback']) &&
- is_callable($params['preSendCallback'])) {
- $this->_preSendCallback = $params['preSendCallback'];
- }
-
- if (isset($params['postSendCallback']) &&
- is_callable($params['postSendCallback'])) {
- $this->_postSendCallback = $params['postSendCallback'];
- }
- }
-
- /**
- * Implements Mail_mock::send() function. Silently discards all
- * mail.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- if ($this->_preSendCallback) {
- call_user_func_array($this->_preSendCallback,
- array(&$this, $recipients, $headers, $body));
- }
-
- $entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body);
- $this->sentMessages[] = $entry;
-
- if ($this->_postSendCallback) {
- call_user_func_array($this->_postSendCallback,
- array(&$this, $recipients, $headers, $body));
- }
-
- return true;
- }
-
-}
diff --git a/data/module/Mail/null.php b/data/module/Mail/null.php
deleted file mode 100644
index c8d9fbc16c..0000000000
--- a/data/module/Mail/null.php
+++ /dev/null
@@ -1,84 +0,0 @@
-
- * @copyright 2010 Phil Kernick
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail/
- */
-
-/**
- * Null implementation of the PEAR Mail:: interface.
- * @access public
- * @package Mail
- * @version $Revision$
- */
-class Mail_null extends Mail {
-
- /**
- * Implements Mail_null::send() function. Silently discards all
- * mail.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- return true;
- }
-
-}
diff --git a/data/module/Mail/sendmail.php b/data/module/Mail/sendmail.php
deleted file mode 100644
index 627b0e8f6a..0000000000
--- a/data/module/Mail/sendmail.php
+++ /dev/null
@@ -1,171 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-
-/**
- * Sendmail implementation of the PEAR Mail:: interface.
- * @access public
- * @package Mail
- * @version $Revision$
- */
-class Mail_sendmail extends Mail {
-
- /**
- * The location of the sendmail or sendmail wrapper binary on the
- * filesystem.
- * @var string
- */
- var $sendmail_path = '/usr/sbin/sendmail';
-
- /**
- * Any extra command-line parameters to pass to the sendmail or
- * sendmail wrapper binary.
- * @var string
- */
- var $sendmail_args = '-i';
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_sendmail:: object based on the parameters
- * passed in. It looks for the following parameters:
- * sendmail_path The location of the sendmail binary on the
- * filesystem. Defaults to '/usr/sbin/sendmail'.
- *
- * sendmail_args Any extra parameters to pass to the sendmail
- * or sendmail wrapper binary.
- *
- * If a parameter is present in the $params array, it replaces the
- * default.
- *
- * @param array $params Hash containing any parameters different from the
- * defaults.
- * @access public
- */
- function Mail_sendmail($params)
- {
- if (isset($params['sendmail_path'])) {
- $this->sendmail_path = $params['sendmail_path'];
- }
- if (isset($params['sendmail_args'])) {
- $this->sendmail_args = $params['sendmail_args'];
- }
-
- /*
- * Because we need to pass message headers to the sendmail program on
- * the commandline, we can't guarantee the use of the standard "\r\n"
- * separator. Instead, we use the system's native line separator.
- */
- if (defined('PHP_EOL')) {
- $this->sep = PHP_EOL;
- } else {
- $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
- }
- }
-
- /**
- * Implements Mail::send() function using the sendmail
- * command-line binary.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- $recipients = $this->parseRecipients($recipients);
- if (is_a($recipients, 'PEAR_Error')) {
- return $recipients;
- }
- $recipients = implode(' ', array_map('escapeshellarg', $recipients));
-
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- return $headerElements;
- }
- list($from, $text_headers) = $headerElements;
-
- /* Since few MTAs are going to allow this header to be forged
- * unless it's in the MAIL FROM: exchange, we'll use
- * Return-Path instead of From: if it's set. */
- if (!empty($headers['Return-Path'])) {
- $from = $headers['Return-Path'];
- }
-
- if (!isset($from)) {
- return PEAR::raiseError('No from address given.');
- } elseif (strpos($from, ' ') !== false ||
- strpos($from, ';') !== false ||
- strpos($from, '&') !== false ||
- strpos($from, '`') !== false) {
- return PEAR::raiseError('From address specified with dangerous characters.');
- }
-
- $from = escapeshellarg($from); // Security bug #16200
-
- $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w');
- if (!$mail) {
- return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.');
- }
-
- // Write the headers following by two newlines: one to end the headers
- // section and a second to separate the headers block from the body.
- fputs($mail, $text_headers . $this->sep . $this->sep);
-
- fputs($mail, $body);
- $result = pclose($mail);
- if (version_compare(phpversion(), '4.2.3') == -1) {
- // With older php versions, we need to shift the pclose
- // result to get the exit code.
- $result = $result >> 8 & 0xFF;
- }
-
- if ($result != 0) {
- return PEAR::raiseError('sendmail returned error code ' . $result,
- $result);
- }
-
- return true;
- }
-
-}
diff --git a/data/module/Mail/smtp.php b/data/module/Mail/smtp.php
deleted file mode 100644
index 52ea602086..0000000000
--- a/data/module/Mail/smtp.php
+++ /dev/null
@@ -1,444 +0,0 @@
-
- * @author Chuck Hagenbuch
- * @copyright 2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: smtp.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-/** Error: Failed to create a Net_SMTP object */
-define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
-
-/** Error: Failed to connect to SMTP server */
-define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
-
-/** Error: SMTP authentication failure */
-define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
-
-/** Error: No From: address has been provided */
-define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
-
-/** Error: Failed to set sender */
-define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
-
-/** Error: Failed to add recipient */
-define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
-
-/** Error: Failed to send data */
-define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);
-
-/**
- * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
- * @access public
- * @package Mail
- * @version $Revision: 294747 $
- */
-class Mail_smtp extends Mail {
-
- /**
- * SMTP connection object.
- *
- * @var object
- * @access private
- */
- var $_smtp = null;
-
- /**
- * The list of service extension parameters to pass to the Net_SMTP
- * mailFrom() command.
- * @var array
- */
- var $_extparams = array();
-
- /**
- * The SMTP host to connect to.
- * @var string
- */
- var $host = 'localhost';
-
- /**
- * The port the SMTP server is on.
- * @var integer
- */
- var $port = 25;
-
- /**
- * Should SMTP authentication be used?
- *
- * This value may be set to true, false or the name of a specific
- * authentication method.
- *
- * If the value is set to true, the Net_SMTP package will attempt to use
- * the best authentication method advertised by the remote SMTP server.
- *
- * @var mixed
- */
- var $auth = false;
-
- /**
- * The username to use if the SMTP server requires authentication.
- * @var string
- */
- var $username = '';
-
- /**
- * The password to use if the SMTP server requires authentication.
- * @var string
- */
- var $password = '';
-
- /**
- * Hostname or domain that will be sent to the remote SMTP server in the
- * HELO / EHLO message.
- *
- * @var string
- */
- var $localhost = 'localhost';
-
- /**
- * SMTP connection timeout value. NULL indicates no timeout.
- *
- * @var integer
- */
- var $timeout = null;
-
- /**
- * Turn on Net_SMTP debugging?
- *
- * @var boolean $debug
- */
- var $debug = false;
-
- /**
- * Indicates whether or not the SMTP connection should persist over
- * multiple calls to the send() method.
- *
- * @var boolean
- */
- var $persist = false;
-
- /**
- * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server
- * supports it. This speeds up delivery over high-latency connections. By
- * default, use the default value supplied by Net_SMTP.
- * @var bool
- */
- var $pipelining;
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_smtp:: object based on the parameters
- * passed in. It looks for the following parameters:
- * host The server to connect to. Defaults to localhost.
- * port The port to connect to. Defaults to 25.
- * auth SMTP authentication. Defaults to none.
- * username The username to use for SMTP auth. No default.
- * password The password to use for SMTP auth. No default.
- * localhost The local hostname / domain. Defaults to localhost.
- * timeout The SMTP connection timeout. Defaults to none.
- * verp Whether to use VERP or not. Defaults to false.
- * DEPRECATED as of 1.2.0 (use setMailParams()).
- * debug Activate SMTP debug mode? Defaults to false.
- * persist Should the SMTP connection persist?
- * pipelining Use SMTP command pipelining
- *
- * If a parameter is present in the $params array, it replaces the
- * default.
- *
- * @param array Hash containing any parameters different from the
- * defaults.
- * @access public
- */
- function Mail_smtp($params)
- {
- if (isset($params['host'])) $this->host = $params['host'];
- if (isset($params['port'])) $this->port = $params['port'];
- if (isset($params['auth'])) $this->auth = $params['auth'];
- if (isset($params['username'])) $this->username = $params['username'];
- if (isset($params['password'])) $this->password = $params['password'];
- if (isset($params['localhost'])) $this->localhost = $params['localhost'];
- if (isset($params['timeout'])) $this->timeout = $params['timeout'];
- if (isset($params['debug'])) $this->debug = (bool)$params['debug'];
- if (isset($params['persist'])) $this->persist = (bool)$params['persist'];
- if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining'];
-
- // Deprecated options
- if (isset($params['verp'])) {
- $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']);
- }
-
- register_shutdown_function(array(&$this, '_Mail_smtp'));
- }
-
- /**
- * Destructor implementation to ensure that we disconnect from any
- * potentially-alive persistent SMTP connections.
- */
- function _Mail_smtp()
- {
- $this->disconnect();
- }
-
- /**
- * Implements Mail::send() function using SMTP.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (e.g., 'Subject'), and the array value
- * is the header value (e.g., 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * MIME parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- /* If we don't already have an SMTP object, create one. */
- $result = &$this->getSMTPObject();
- if (PEAR::isError($result)) {
- return $result;
- }
-
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $this->_sanitizeHeaders($headers);
-
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- $this->_smtp->rset();
- return $headerElements;
- }
- list($from, $textHeaders) = $headerElements;
-
- /* Since few MTAs are going to allow this header to be forged
- * unless it's in the MAIL FROM: exchange, we'll use
- * Return-Path instead of From: if it's set. */
- if (!empty($headers['Return-Path'])) {
- $from = $headers['Return-Path'];
- }
-
- if (!isset($from)) {
- $this->_smtp->rset();
- return PEAR::raiseError('No From: address has been provided',
- PEAR_MAIL_SMTP_ERROR_FROM);
- }
-
- $params = null;
- if (!empty($this->_extparams)) {
- foreach ($this->_extparams as $key => $val) {
- $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
- }
- }
- if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) {
- $error = $this->_error("Failed to set sender: $from", $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
- }
-
- $recipients = $this->parseRecipients($recipients);
- if (is_a($recipients, 'PEAR_Error')) {
- $this->_smtp->rset();
- return $recipients;
- }
-
- foreach ($recipients as $recipient) {
- $res = $this->_smtp->rcptTo($recipient);
- if (is_a($res, 'PEAR_Error')) {
- $error = $this->_error("Failed to add recipient: $recipient", $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
- }
- }
-
- /* Send the message's headers and the body as SMTP data. */
- $res = $this->_smtp->data($textHeaders . "\r\n\r\n" . $body);
- list(,$args) = $this->_smtp->getResponse();
-
- if (preg_match("/Ok: queued as (.*)/", $args, $queued)) {
- $this->queued_as = $queued[1];
- }
-
- /* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to.
- * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */
- $this->greeting = $this->_smtp->getGreeting();
-
- if (is_a($res, 'PEAR_Error')) {
- $error = $this->_error('Failed to send data', $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
- }
-
- /* If persistent connections are disabled, destroy our SMTP object. */
- if ($this->persist === false) {
- $this->disconnect();
- }
-
- return true;
- }
-
- /**
- * Connect to the SMTP server by instantiating a Net_SMTP object.
- *
- * @return mixed Returns a reference to the Net_SMTP object on success, or
- * a PEAR_Error containing a descriptive error message on
- * failure.
- *
- * @since 1.2.0
- * @access public
- */
- function &getSMTPObject()
- {
- if (is_object($this->_smtp) !== false) {
- return $this->_smtp;
- }
-
- include_once 'Net/SMTP.php';
- $this->_smtp = &new Net_SMTP($this->host,
- $this->port,
- $this->localhost);
-
- /* If we still don't have an SMTP object at this point, fail. */
- if (is_object($this->_smtp) === false) {
- return PEAR::raiseError('Failed to create a Net_SMTP object',
- PEAR_MAIL_SMTP_ERROR_CREATE);
- }
-
- /* Configure the SMTP connection. */
- if ($this->debug) {
- $this->_smtp->setDebug(true);
- }
-
- /* Attempt to connect to the configured SMTP server. */
- if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
- $error = $this->_error('Failed to connect to ' .
- $this->host . ':' . $this->port,
- $res);
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
- }
-
- /* Attempt to authenticate if authentication has been enabled. */
- if ($this->auth) {
- $method = is_string($this->auth) ? $this->auth : '';
-
- if (PEAR::isError($res = $this->_smtp->auth($this->username,
- $this->password,
- $method))) {
- $error = $this->_error("$method authentication failure",
- $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
- }
- }
-
- return $this->_smtp;
- }
-
- /**
- * Add parameter associated with a SMTP service extension.
- *
- * @param string Extension keyword.
- * @param string Any value the keyword needs.
- *
- * @since 1.2.0
- * @access public
- */
- function addServiceExtensionParameter($keyword, $value = null)
- {
- $this->_extparams[$keyword] = $value;
- }
-
- /**
- * Disconnect and destroy the current SMTP connection.
- *
- * @return boolean True if the SMTP connection no longer exists.
- *
- * @since 1.1.9
- * @access public
- */
- function disconnect()
- {
- /* If we have an SMTP object, disconnect and destroy it. */
- if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
- $this->_smtp = null;
- }
-
- /* We are disconnected if we no longer have an SMTP object. */
- return ($this->_smtp === null);
- }
-
- /**
- * Build a standardized string describing the current SMTP error.
- *
- * @param string $text Custom string describing the error context.
- * @param object $error Reference to the current PEAR_Error object.
- *
- * @return string A string describing the current SMTP error.
- *
- * @since 1.1.7
- * @access private
- */
- function _error($text, &$error)
- {
- /* Split the SMTP response into a code and a response string. */
- list($code, $response) = $this->_smtp->getResponse();
-
- /* Build our standardized error string. */
- return $text
- . ' [SMTP: ' . $error->getMessage()
- . " (code: $code, response: $response)]";
- }
-
-}
diff --git a/data/module/Mail/smtpmx.php b/data/module/Mail/smtpmx.php
deleted file mode 100644
index f0b6940868..0000000000
--- a/data/module/Mail/smtpmx.php
+++ /dev/null
@@ -1,502 +0,0 @@
-
- * @copyright 2010 gERD Schaufelberger
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: smtpmx.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-require_once 'Net/SMTP.php';
-
-/**
- * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
- *
- *
- * @access public
- * @author gERD Schaufelberger
- * @package Mail
- * @version $Revision: 294747 $
- */
-class Mail_smtpmx extends Mail {
-
- /**
- * SMTP connection object.
- *
- * @var object
- * @access private
- */
- var $_smtp = null;
-
- /**
- * The port the SMTP server is on.
- * @var integer
- * @see getservicebyname()
- */
- var $port = 25;
-
- /**
- * Hostname or domain that will be sent to the remote SMTP server in the
- * HELO / EHLO message.
- *
- * @var string
- * @see posix_uname()
- */
- var $mailname = 'localhost';
-
- /**
- * SMTP connection timeout value. NULL indicates no timeout.
- *
- * @var integer
- */
- var $timeout = 10;
-
- /**
- * use either PEAR:Net_DNS or getmxrr
- *
- * @var boolean
- */
- var $withNetDns = true;
-
- /**
- * PEAR:Net_DNS_Resolver
- *
- * @var object
- */
- var $resolver;
-
- /**
- * Whether to use VERP or not. If not a boolean, the string value
- * will be used as the VERP separators.
- *
- * @var mixed boolean or string
- */
- var $verp = false;
-
- /**
- * Whether to use VRFY or not.
- *
- * @var boolean $vrfy
- */
- var $vrfy = false;
-
- /**
- * Switch to test mode - don't send emails for real
- *
- * @var boolean $debug
- */
- var $test = false;
-
- /**
- * Turn on Net_SMTP debugging?
- *
- * @var boolean $peardebug
- */
- var $debug = false;
-
- /**
- * internal error codes
- *
- * translate internal error identifier to PEAR-Error codes and human
- * readable messages.
- *
- * @var boolean $debug
- * @todo as I need unique error-codes to identify what exactly went wrond
- * I did not use intergers as it should be. Instead I added a "namespace"
- * for each code. This avoids conflicts with error codes from different
- * classes. How can I use unique error codes and stay conform with PEAR?
- */
- var $errorCode = array(
- 'not_connected' => array(
- 'code' => 1,
- 'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
- ),
- 'failed_vrfy_rcpt' => array(
- 'code' => 2,
- 'msg' => 'Recipient "{RCPT}" could not be veryfied.'
- ),
- 'failed_set_from' => array(
- 'code' => 3,
- 'msg' => 'Failed to set sender: {FROM}.'
- ),
- 'failed_set_rcpt' => array(
- 'code' => 4,
- 'msg' => 'Failed to set recipient: {RCPT}.'
- ),
- 'failed_send_data' => array(
- 'code' => 5,
- 'msg' => 'Failed to send mail to: {RCPT}.'
- ),
- 'no_from' => array(
- 'code' => 5,
- 'msg' => 'No from address has be provided.'
- ),
- 'send_data' => array(
- 'code' => 7,
- 'msg' => 'Failed to create Net_SMTP object.'
- ),
- 'no_mx' => array(
- 'code' => 8,
- 'msg' => 'No MX-record for {RCPT} found.'
- ),
- 'no_resolver' => array(
- 'code' => 9,
- 'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
- ),
- 'failed_rset' => array(
- 'code' => 10,
- 'msg' => 'RSET command failed, SMTP-connection corrupt.'
- ),
- );
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_smtp:: object based on the parameters
- * passed in. It looks for the following parameters:
- * mailname The name of the local mail system (a valid hostname which matches the reverse lookup)
- * port smtp-port - the default comes from getservicebyname() and should work fine
- * timeout The SMTP connection timeout. Defaults to 30 seconds.
- * vrfy Whether to use VRFY or not. Defaults to false.
- * verp Whether to use VERP or not. Defaults to false.
- * test Activate test mode? Defaults to false.
- * debug Activate SMTP and Net_DNS debug mode? Defaults to false.
- * netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true
- *
- * If a parameter is present in the $params array, it replaces the
- * default.
- *
- * @access public
- * @param array Hash containing any parameters different from the
- * defaults.
- * @see _Mail_smtpmx()
- */
- function __construct($params)
- {
- if (isset($params['mailname'])) {
- $this->mailname = $params['mailname'];
- } else {
- // try to find a valid mailname
- if (function_exists('posix_uname')) {
- $uname = posix_uname();
- $this->mailname = $uname['nodename'];
- }
- }
-
- // port number
- if (isset($params['port'])) {
- $this->_port = $params['port'];
- } else {
- $this->_port = getservbyname('smtp', 'tcp');
- }
-
- if (isset($params['timeout'])) $this->timeout = $params['timeout'];
- if (isset($params['verp'])) $this->verp = $params['verp'];
- if (isset($params['test'])) $this->test = $params['test'];
- if (isset($params['peardebug'])) $this->test = $params['peardebug'];
- if (isset($params['netdns'])) $this->withNetDns = $params['netdns'];
- }
-
- /**
- * Constructor wrapper for PHP4
- *
- * @access public
- * @param array Hash containing any parameters different from the defaults
- * @see __construct()
- */
- function Mail_smtpmx($params)
- {
- $this->__construct($params);
- register_shutdown_function(array(&$this, '__destruct'));
- }
-
- /**
- * Destructor implementation to ensure that we disconnect from any
- * potentially-alive persistent SMTP connections.
- */
- function __destruct()
- {
- if (is_object($this->_smtp)) {
- $this->_smtp->disconnect();
- $this->_smtp = null;
- }
- }
-
- /**
- * Implements Mail::send() function using SMTP direct delivery
- *
- * @access public
- * @param mixed $recipients in RFC822 style or array
- * @param array $headers The array of headers to send with the mail.
- * @param string $body The full text of the message body,
- * @return mixed Returns true on success, or a PEAR_Error
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- // Prepare headers
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- return $headerElements;
- }
- list($from, $textHeaders) = $headerElements;
-
- // use 'Return-Path' if possible
- if (!empty($headers['Return-Path'])) {
- $from = $headers['Return-Path'];
- }
- if (!isset($from)) {
- return $this->_raiseError('no_from');
- }
-
- // Prepare recipients
- $recipients = $this->parseRecipients($recipients);
- if (is_a($recipients, 'PEAR_Error')) {
- return $recipients;
- }
-
- foreach ($recipients as $rcpt) {
- list($user, $host) = explode('@', $rcpt);
-
- $mx = $this->_getMx($host);
- if (is_a($mx, 'PEAR_Error')) {
- return $mx;
- }
-
- if (empty($mx)) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('no_mx', $info);
- }
-
- $connected = false;
- foreach ($mx as $mserver => $mpriority) {
- $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname);
-
- // configure the SMTP connection.
- if ($this->debug) {
- $this->_smtp->setDebug(true);
- }
-
- // attempt to connect to the configured SMTP server.
- $res = $this->_smtp->connect($this->timeout);
- if (is_a($res, 'PEAR_Error')) {
- $this->_smtp = null;
- continue;
- }
-
- // connection established
- if ($res) {
- $connected = true;
- break;
- }
- }
-
- if (!$connected) {
- $info = array(
- 'host' => implode(', ', array_keys($mx)),
- 'port' => $this->port,
- 'rcpt' => $rcpt,
- );
- return $this->_raiseError('not_connected', $info);
- }
-
- // Verify recipient
- if ($this->vrfy) {
- $res = $this->_smtp->vrfy($rcpt);
- if (is_a($res, 'PEAR_Error')) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('failed_vrfy_rcpt', $info);
- }
- }
-
- // mail from:
- $args['verp'] = $this->verp;
- $res = $this->_smtp->mailFrom($from, $args);
- if (is_a($res, 'PEAR_Error')) {
- $info = array('from' => $from);
- return $this->_raiseError('failed_set_from', $info);
- }
-
- // rcpt to:
- $res = $this->_smtp->rcptTo($rcpt);
- if (is_a($res, 'PEAR_Error')) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('failed_set_rcpt', $info);
- }
-
- // Don't send anything in test mode
- if ($this->test) {
- $result = $this->_smtp->rset();
- $res = $this->_smtp->rset();
- if (is_a($res, 'PEAR_Error')) {
- return $this->_raiseError('failed_rset');
- }
-
- $this->_smtp->disconnect();
- $this->_smtp = null;
- return true;
- }
-
- // Send data
- $res = $this->_smtp->data("$textHeaders\r\n$body");
- if (is_a($res, 'PEAR_Error')) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('failed_send_data', $info);
- }
-
- $this->_smtp->disconnect();
- $this->_smtp = null;
- }
-
- return true;
- }
-
- /**
- * Recieve mx rexords for a spciefied host
- *
- * The MX records
- *
- * @access private
- * @param string $host mail host
- * @return mixed sorted
- */
- function _getMx($host)
- {
- $mx = array();
-
- if ($this->withNetDns) {
- $res = $this->_loadNetDns();
- if (is_a($res, 'PEAR_Error')) {
- return $res;
- }
-
- $response = $this->resolver->query($host, 'MX');
- if (!$response) {
- return false;
- }
-
- foreach ($response->answer as $rr) {
- if ($rr->type == 'MX') {
- $mx[$rr->exchange] = $rr->preference;
- }
- }
- } else {
- $mxHost = array();
- $mxWeight = array();
-
- if (!getmxrr($host, $mxHost, $mxWeight)) {
- return false;
- }
- for ($i = 0; $i < count($mxHost); ++$i) {
- $mx[$mxHost[$i]] = $mxWeight[$i];
- }
- }
-
- asort($mx);
- return $mx;
- }
-
- /**
- * initialize PEAR:Net_DNS_Resolver
- *
- * @access private
- * @return boolean true on success
- */
- function _loadNetDns()
- {
- if (is_object($this->resolver)) {
- return true;
- }
-
- if (!include_once 'Net/DNS.php') {
- return $this->_raiseError('no_resolver');
- }
-
- $this->resolver = new Net_DNS_Resolver();
- if ($this->debug) {
- $this->resolver->test = 1;
- }
-
- return true;
- }
-
- /**
- * raise standardized error
- *
- * include additional information in error message
- *
- * @access private
- * @param string $id maps error ids to codes and message
- * @param array $info optional information in associative array
- * @see _errorCode
- */
- function _raiseError($id, $info = array())
- {
- $code = $this->errorCode[$id]['code'];
- $msg = $this->errorCode[$id]['msg'];
-
- // include info to messages
- if (!empty($info)) {
- $search = array();
- $replace = array();
-
- foreach ($info as $key => $value) {
- array_push($search, '{' . strtoupper($key) . '}');
- array_push($replace, $value);
- }
-
- $msg = str_replace($search, $replace, $msg);
- }
-
- return PEAR::raiseError($msg, $code);
- }
-
-}
diff --git a/data/module/Mobile/Detect.php b/data/module/Mobile/Detect.php
deleted file mode 100755
index b6eb0da21b..0000000000
--- a/data/module/Mobile/Detect.php
+++ /dev/null
@@ -1,1248 +0,0 @@
-, Nick Ilyin
- * Original author: Victor Stanciu
- *
- * @license Code and contributions have 'MIT License'
- * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
- *
- * @link Homepage: http://mobiledetect.net
- * GitHub Repo: https://github.com/serbanghita/Mobile-Detect
- * Google Code: http://code.google.com/p/php-mobile-detect/
- * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
- * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
- *
- * @version 2.8.3
- */
-
-class Mobile_Detect
-{
- /**
- * Mobile detection type.
- *
- * @deprecated since version 2.6.9
- */
- const DETECTION_TYPE_MOBILE = 'mobile';
-
- /**
- * Extended detection type.
- *
- * @deprecated since version 2.6.9
- */
- const DETECTION_TYPE_EXTENDED = 'extended';
-
- /**
- * A frequently used regular expression to extract version #s.
- *
- * @deprecated since version 2.6.9
- */
- const VER = '([\w._\+]+)';
-
- /**
- * Top-level device.
- */
- const MOBILE_GRADE_A = 'A';
-
- /**
- * Mid-level device.
- */
- const MOBILE_GRADE_B = 'B';
-
- /**
- * Low-level device.
- */
- const MOBILE_GRADE_C = 'C';
-
- /**
- * Stores the version number of the current release.
- */
- const VERSION = '2.8.3';
-
- /**
- * A type for the version() method indicating a string return value.
- */
- const VERSION_TYPE_STRING = 'text';
-
- /**
- * A type for the version() method indicating a float return value.
- */
- const VERSION_TYPE_FLOAT = 'float';
-
- /**
- * The User-Agent HTTP header is stored in here.
- * @var string
- */
- protected $userAgent = null;
-
- /**
- * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
- * @var array
- */
- protected $httpHeaders = array();
-
- /**
- * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
- *
- * @deprecated since version 2.6.9
- *
- * @var string
- */
- protected $detectionType = self::DETECTION_TYPE_MOBILE;
-
- /**
- * HTTP headers that trigger the 'isMobile' detection
- * to be true.
- *
- * @var array
- */
- protected static $mobileHeaders = array(
-
- 'HTTP_ACCEPT' => array('matches' => array(
- // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
- 'application/x-obml2d',
- // BlackBerry devices.
- 'application/vnd.rim.html',
- 'text/vnd.wap.wml',
- 'application/vnd.wap.xhtml+xml'
- )),
- 'HTTP_X_WAP_PROFILE' => null,
- 'HTTP_X_WAP_CLIENTID' => null,
- 'HTTP_WAP_CONNECTION' => null,
- 'HTTP_PROFILE' => null,
- // Reported by Opera on Nokia devices (eg. C3).
- 'HTTP_X_OPERAMINI_PHONE_UA' => null,
- 'HTTP_X_NOKIA_GATEWAY_ID' => null,
- 'HTTP_X_ORANGE_ID' => null,
- 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
- 'HTTP_X_HUAWEI_USERID' => null,
- // Reported by Windows Smartphones.
- 'HTTP_UA_OS' => null,
- // Reported by Verizon, Vodafone proxy system.
- 'HTTP_X_MOBILE_GATEWAY' => null,
- // Seend this on HTC Sensation. @ref: SensationXE_Beats_Z715e.
- 'HTTP_X_ATT_DEVICEID' => null,
- // Seen this on a HTC.
- 'HTTP_UA_CPU' => array('matches' => array('ARM')),
- );
-
- /**
- * List of mobile devices (phones).
- *
- * @var array
- */
- protected static $phoneDevices = array(
- 'iPhone' => '\biPhone.*(Mobile|PhoneGap)|\biPod', // |\biTunes
- 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
- 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m',
- 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile',
- // @todo: Is 'Dell Streak' a tablet or a phone? ;)
- 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
- 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|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|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925',
- 'Samsung' => 'Samsung|SGH-I337|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-C3262|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-I8190|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-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|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-S7562|GT-S7710|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-I959|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-i747M|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|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E',
- 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802)',
- 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i',
- 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
- // @ref: http://www.micromaxinfo.com/mobiles/smartphones
- // Added because the codes might conflict with Acer Tablets.
- 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
- 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex.
- 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
- // @ref: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
- // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
- 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
- // @ref: http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
- 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
- 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
- // Added simvalley mobile just for fun. They have some interesting devices.
- // @ref: http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
- 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
- // @Tapatalk is a mobile app; @ref: http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
- 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser'
- );
-
- /**
- * List of tablet devices.
- *
- * @var array
- */
- protected static $tabletDevices = array(
- 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
- 'NexusTablet' => 'Android.*Nexus[\s]+(7|10)|^.*Android.*Nexus(?:(?!Mobile).)*$',
- 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|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-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-I9205|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705C|SM-T535|SM-T331', // SCH-P709|SCH-P729|SM-T2558 - Samsung Mega - treat them like a regular phone.
- // @reference: http://www.labnol.org/software/kindle-user-agent-string/20378/
- 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE)\b',
- // Only the Surface tablets with Windows RT are considered mobile.
- // @ref: http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
- 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;',
- // @ref: http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
- 'HPTablet' => 'HP Slate 7|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8',
- // @note: watch out for PadFone, see #132
- 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|TX201LA',
- 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
- 'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
- 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
- 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
- // @ref: http://www.acer.ro/ac/ro/RO/content/drivers
- // @ref: http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
- // @ref: http://us.acer.com/ac/en/US/content/group/tablets
- // @note: Can conflict with Micromax and Motorola phones codes.
- 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-830)\b|W3-810|\bA3-A10\b',
- // @ref: http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
- // @ref: http://us.toshiba.com/tablets/tablet-finder
- // @ref: http://www.toshiba.co.jp/regza/tablet/
- 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
- // @ref: http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
- // @ref: http://www.lg.com/us/tablets
- 'LGTablet' => '\bL-06C|LG-V900|LG-V500|LG-V909|LG-V500|LG-V510|LG-VK810\b',
- 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
- // Prestigio Tablets http://www.prestigio.com/support
- 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD',
- // @ref: http://support.lenovo.com/en_GB/downloads/default.page?#
- 'LenovoTablet' => 'IdeaTab|ThinkPad([ ]+)?Tablet|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A1000|A2107|A2109|A1107|B6000|B8000|B8080-F)',
- // @ref: http://www.yarvik.com/en/matrix/tablets/
- 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
- 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
- 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT',
- // http://www.intenso.de/kategorie_en.php?kategorie=33
- // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
- 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab',
- // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
- 'IRUTablet' => 'M702pro',
- 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
- // @ref: http://www.e-boda.ro/tablete-pc.html
- 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
- // @ref: http://www.allview.ro/produse/droseries/lista-tablete-pc/
- 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
- // @reference: http://wiki.archosfans.com/index.php?title=Main_Page
- 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|ARCHOS 101G10|Archos 101 Neon',
- // @ref: http://www.ainol.com/plugin.php?identifier=ainol&module=product
- 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
- // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
- // @ref: Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
- // @ref: http://www.sony.jp/support/tablet/
- 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551',
- // @ref: db + http://www.cube-tablet.com/buy-products.html
- 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
- // @ref: http://www.cobyusa.com/?p=pcat&pcat_id=3001
- 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
- // @ref: http://www.match.net.cn/products.asp
- 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733',
- // @ref: http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
- // @ref: http://www.imp3.net/14/show.php?itemid=20454
- 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
- // @ref: http://www.rock-chips.com/index.php?do=prod&pid=2
- 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
- // @ref: http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
- 'FlyTablet' => 'IQ310|Fly Vision',
- // @ref: http://www.bqreaders.com/gb/tablets-prices-sale.html
- 'bqTablet' => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)|Maxwell.*Lite|Maxwell.*Plus',
- // @ref: http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
- // @ref: http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
- 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
- // Nec or Medias Tab
- 'NecTablet' => '\bN-06D|\bN-08D',
- // Pantech Tablets: http://www.pantechusa.com/phones/
- 'PantechTablet' => 'Pantech.*P4100',
- // Broncho Tablets: http://www.broncho.cn/ (hard to find)
- 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
- // @ref: http://versusuk.com/support.html
- 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
- // @ref: http://www.zync.in/index.php/our-products/tablet-phablets
- 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
- // @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
- 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
- // @ref: https://www.nabitablet.com/
- 'NabiTablet' => 'Android.*\bNabi',
- 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
- // French Danew Tablets http://www.danew.com/produits-tablette.php
- 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
- // Texet Tablets and Readers http://www.texet.ru/tablet/
- 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
- // @note: Avoid detecting 'PLAYSTATION 3' as mobile.
- 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
- // @ref: http://www.trekstor.de/surftabs.html
- 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A',
- // @ref: http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
- 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
- // @ref: http://www.advandigital.com/index.php?link=content-product&jns=JP001
- // @Note: because of the short codenames we have to include whitespaces to reduce the possible conflicts.
- 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
- // @ref: http://www.danytech.com/category/tablet-pc
- 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
- // @ref: http://www.galapad.net/product.html
- 'GalapadTablet' => 'Android.*\bG1\b',
- // @ref: http://www.micromaxinfo.com/tablet/funbook
- 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
- // http://www.karbonnmobiles.com/products_tablet.php
- 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
- // @ref: http://www.myallfine.com/Products.asp
- 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
- // @ref: http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
- 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
- // @ref: http://www.yonesnav.com/products/products.php
- 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
- // @ref: http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
- // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
- 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
- // @ref: http://www.gloryunion.cn/products.asp
- // @ref: http://www.allwinnertech.com/en/apply/mobile.html
- // @ref: http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
- // @todo: Softwiner tablets?
- // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
- 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
- // @ref: http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
- 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
- // @ref: http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
- // @todo: add more tests.
- 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
- // @ref: http://hclmetablet.com/India/index.php
- 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
- // @ref: http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
- 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
- // @ref: http://www.visture.com/index.asp
- 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
- // @ref: http://www.mijncresta.nl/tablet
- 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
- // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
- 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
- // Concorde tab
- 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
- // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
- 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
- // Modecom Tablets - http://www.modecom.eu/tablets/portal/
- 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
- // Vonino Tablets - http://www.vonino.eu/tablets
- 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
- // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
- 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
- // Storex Tablets - http://storex.fr/espace_client/support.html
- // @note: no need to add all the tablet codes since they are guided by the first regex.
- 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
- // Generic Vodafone tablets.
- 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10',
- // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
- // Aka: http://www.essentielb.fr/
- 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
- // Ross & Moor - http://ross-moor.ru/
- 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
- // i-mobile http://product.i-mobilephone.com/Mobile_Device
- 'iMobileTablet' => 'i-mobile i-note',
- // @ref: http://www.tolino.de/de/vergleichen/
- 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
- // AudioSonic - a Kmart brand
- // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72¤tPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
- 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
- // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
- // @todo: add them gradually to avoid conflicts.
- 'AMPETablet' => 'Android.* A78 ',
- // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
- 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
- // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
- 'TecnoTablet' => 'TECNO P9',
- // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
- 'JXDTablet' => 'Android.*\b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
- // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
- 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
- // http://www.intracon.eu/tablet
- 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
- // http://www.xoro.de/produkte/
- // @note: Might be the same brand with 'Simply tablets'
- 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
- // http://www1.viewsonic.com/products/computing/tablets/
- 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
- // http://www.odys.de/web/internet-tablet_en.html
- 'OdysTablet' => 'LOOX|XENO10|ODYS Space',
- // http://www.captiva-power.de/products.html#tablets-en
- 'CaptivaTablet' => 'CAPTIVA PAD',
- // IconBIT - http://www.iconbit.com/products/tablets/
- 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
- // @ref: http://www.tesco.com/direct/hudl/
- 'Hudl' => 'Hudl HT7S3',
- // @ref: http://www.telstra.com.au/home-phone/thub-2/
- 'TelstraTablet' => 'T-Hub2',
- 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4',
- );
-
- /**
- * List of mobile Operating Systems.
- *
- * @var array
- */
- protected static $operatingSystems = array(
- 'AndroidOS' => 'Android',
- 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
- 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
- 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
- // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
- 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
- // @reference: http://en.wikipedia.org/wiki/Windows_Phone
- // http://wifeng.cn/?r=blog&a=view&id=106
- // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
- 'WindowsPhoneOS' => 'Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7',
- 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
- // http://en.wikipedia.org/wiki/MeeGo
- // @todo: research MeeGo in UAs
- 'MeeGoOS' => 'MeeGo',
- // http://en.wikipedia.org/wiki/Maemo
- // @todo: research Maemo in UAs
- 'MaemoOS' => 'Maemo',
- 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
- 'webOS' => 'webOS|hpwOS',
- 'badaOS' => '\bBada\b',
- 'BREWOS' => 'BREW',
- );
-
- /**
- * List of mobile User Agents.
- *
- * @var array
- */
- protected static $browsers = array(
- // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
- 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
- 'Dolfin' => '\bDolfin\b',
- 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
- 'Skyfire' => 'Skyfire',
- 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
- 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
- 'Bolt' => 'bolt',
- 'TeaShark' => 'teashark',
- 'Blazer' => 'Blazer',
- // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
- 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile',
- // @ref: http://en.wikipedia.org/wiki/Midori_(web_browser)
- //'Midori' => 'midori',
- 'Tizen' => 'Tizen',
- 'UCBrowser' => 'UC.*Browser|UCWEB',
- // @ref: https://github.com/serbanghita/Mobile-Detect/issues/7
- 'DiigoBrowser' => 'DiigoBrowser',
- // http://www.puffinbrowser.com/index.php
- 'Puffin' => 'Puffin',
- // @ref: http://mercury-browser.com/index.html
- 'Mercury' => '\bMercury\b',
- // @reference: http://en.wikipedia.org/wiki/Minimo
- // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
- 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger'
- );
-
- /**
- * Utilities.
- *
- * @var array
- */
- protected static $utilities = array(
- // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
- // @ref: http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
- // @ref: https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
- 'DesktopMode' => 'WPDesktop',
- 'TV' => 'SonyDTV|HbbTV', // experimental
- 'WebKit' => '(webkit)[ /]([\w.]+)',
- 'Bot' => 'Googlebot|DoCoMo|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
- 'MobileBot' => 'Googlebot-Mobile|DoCoMo|YahooSeeker/M1A1-R2D2',
- // @todo: Include JXD consoles.
- 'Console' => '\b(Nintendo|Nintendo WiiU|PLAYSTATION|Xbox)\b',
- 'Watch' => 'SM-V700',
- );
-
- /**
- * All possible HTTP headers that represent the
- * User-Agent string.
- *
- * @var array
- */
- protected static $uaHttpHeaders = array(
- // The default User-Agent string.
- 'HTTP_USER_AGENT',
- // Header can occur on devices using Opera Mini.
- 'HTTP_X_OPERAMINI_PHONE_UA',
- // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
- 'HTTP_X_DEVICE_USER_AGENT',
- 'HTTP_X_ORIGINAL_USER_AGENT',
- 'HTTP_X_SKYFIRE_PHONE',
- 'HTTP_X_BOLT_PHONE_UA',
- 'HTTP_DEVICE_STOCK_UA',
- 'HTTP_X_UCBROWSER_DEVICE_UA'
- );
-
- /**
- * The individual segments that could exist in a User-Agent string. VER refers to the regular
- * expression defined in the constant self::VER.
- *
- * @var array
- */
- protected static $properties = array(
-
- // Build
- 'Mobile' => 'Mobile/[VER]',
- 'Build' => 'Build/[VER]',
- 'Version' => 'Version/[VER]',
- 'VendorID' => 'VendorID/[VER]',
-
- // Devices
- 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
- 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
- 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
- //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
- 'Kindle' => 'Kindle/[VER]',
-
- // Browser
- 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
- 'Coast' => array('Coast/[VER]'),
- 'Dolfin' => 'Dolfin/[VER]',
- // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference
- 'Firefox' => 'Firefox/[VER]',
- 'Fennec' => 'Fennec/[VER]',
- // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
- 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'),
- // http://en.wikipedia.org/wiki/NetFront
- 'NetFront' => 'NetFront/[VER]',
- 'NokiaBrowser' => 'NokiaBrowser/[VER]',
- 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
- 'Opera Mini' => 'Opera Mini/[VER]',
- 'Opera Mobi' => 'Version/[VER]',
- 'UC Browser' => 'UC Browser[VER]',
- 'MQQBrowser' => 'MQQBrowser/[VER]',
- 'MicroMessenger' => 'MicroMessenger/[VER]',
- // @note: Safari 7534.48.3 is actually Version 5.1.
- // @note: On BlackBerry the Version is overwriten by the OS.
- 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
- 'Skyfire' => 'Skyfire/[VER]',
- 'Tizen' => 'Tizen/[VER]',
- 'Webkit' => 'webkit[ /][VER]',
-
- // Engine
- 'Gecko' => 'Gecko/[VER]',
- 'Trident' => 'Trident/[VER]',
- 'Presto' => 'Presto/[VER]',
-
- // OS
- 'iOS' => ' \bOS\b [VER] ',
- 'Android' => 'Android [VER]',
- 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
- 'BREW' => 'BREW [VER]',
- 'Java' => 'Java/[VER]',
- // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
- // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
- 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
- 'Windows Phone' => 'Windows Phone [VER]',
- 'Windows CE' => 'Windows CE/[VER]',
- // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
- 'Windows NT' => 'Windows NT [VER]',
- 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
- 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
- );
-
- /**
- * Construct an instance of this class.
- *
- * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
- * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
- * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
- * from the $headers array instead.
- */
- public function __construct(
- array $headers = null,
- $userAgent = null
- ){
- $this->setHttpHeaders($headers);
- $this->setUserAgent($userAgent);
- }
-
- /**
- * Get the current script version.
- * This is useful for the demo.php file,
- * so people can check on what version they are testing
- * for mobile devices.
- *
- * @return string The version number in semantic version format.
- */
- public static function getScriptVersion()
- {
- return self::VERSION;
- }
-
- /**
- * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
- *
- * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
- * the headers. The default null is left for backwards compatibilty.
- */
- public function setHttpHeaders($httpHeaders = null)
- {
- //use global _SERVER if $httpHeaders aren't defined
- if (!is_array($httpHeaders) || !count($httpHeaders)) {
- $httpHeaders = $_SERVER;
- }
-
- //clear existing headers
- $this->httpHeaders = array();
-
- //Only save HTTP headers. In PHP land, that means only _SERVER vars that
- //start with HTTP_.
- foreach ($httpHeaders as $key => $value) {
- if (substr($key,0,5) == 'HTTP_') {
- $this->httpHeaders[$key] = $value;
- }
- }
- }
-
- /**
- * Retrieves the HTTP headers.
- *
- * @return array
- */
- public function getHttpHeaders()
- {
- return $this->httpHeaders;
- }
-
- /**
- * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
- * Simply null is returned.
- *
- * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
- * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
- * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
- *
- * @return string|null The value of the header.
- */
- public function getHttpHeader($header)
- {
- //are we using PHP-flavored headers?
- if (strpos($header, '_') === false) {
- $header = str_replace('-', '_', $header);
- $header = strtoupper($header);
- }
-
- //test the alternate, too
- $altHeader = 'HTTP_' . $header;
-
- //Test both the regular and the HTTP_ prefix
- if (isset($this->httpHeaders[$header])) {
- return $this->httpHeaders[$header];
- } elseif (isset($this->httpHeaders[$altHeader])) {
- return $this->httpHeaders[$altHeader];
- }
-
- return null;
- }
-
- public function getMobileHeaders()
- {
- return self::$mobileHeaders;
- }
-
- /**
- * Get all possible HTTP headers that
- * can contain the User-Agent string.
- *
- * @return array List of HTTP headers.
- */
- public function getUaHttpHeaders()
- {
- return self::$uaHttpHeaders;
- }
-
- /**
- * Set the User-Agent to be used.
- *
- * @param string $userAgent The user agent string to set.
- *
- * @return string|null
- */
- public function setUserAgent($userAgent = null)
- {
- if (!empty($userAgent)) {
- return $this->userAgent = $userAgent;
- } else {
-
- $this->userAgent = null;
-
- foreach($this->getUaHttpHeaders() as $altHeader){
- if(!empty($this->httpHeaders[$altHeader])){ // @todo: should use getHttpHeader(), but it would be slow. (Serban)
- $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
- }
- }
-
- return $this->userAgent = (!empty($this->userAgent) ? trim($this->userAgent) : null);
-
- }
- }
-
- /**
- * Retrieve the User-Agent.
- *
- * @return string|null The user agent if it's set.
- */
- public function getUserAgent()
- {
- return $this->userAgent;
- }
-
- /**
- * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
- * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
- *
- * @deprecated since version 2.6.9
- *
- * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
- * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
- */
- public function setDetectionType($type = null)
- {
- if ($type === null) {
- $type = self::DETECTION_TYPE_MOBILE;
- }
-
- if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) {
- return;
- }
-
- $this->detectionType = $type;
- }
-
- /**
- * Retrieve the list of known phone devices.
- *
- * @return array List of phone devices.
- */
- public static function getPhoneDevices()
- {
- return self::$phoneDevices;
- }
-
- /**
- * Retrieve the list of known tablet devices.
- *
- * @return array List of tablet devices.
- */
- public static function getTabletDevices()
- {
- return self::$tabletDevices;
- }
-
- /**
- * Alias for getBrowsers() method.
- *
- * @return array List of user agents.
- */
- public static function getUserAgents()
- {
- return self::getBrowsers();
- }
-
- /**
- * Retrieve the list of known browsers. Specifically, the user agents.
- *
- * @return array List of browsers / user agents.
- */
- public static function getBrowsers()
- {
- return self::$browsers;
- }
-
- /**
- * Retrieve the list of known utilities.
- *
- * @return array List of utilities.
- */
- public static function getUtilities()
- {
- return self::$utilities;
- }
-
- /**
- * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
- *
- * @deprecated since version 2.6.9
- *
- * @return array All the rules (but not extended).
- */
- public static function getMobileDetectionRules()
- {
- static $rules;
-
- if (!$rules) {
- $rules = array_merge(
- self::$phoneDevices,
- self::$tabletDevices,
- self::$operatingSystems,
- self::$browsers
- );
- }
-
- return $rules;
-
- }
-
- /**
- * Method gets the mobile detection rules + utilities.
- * The reason this is separate is because utilities rules
- * don't necessary imply mobile. This method is used inside
- * the new $detect->is('stuff') method.
- *
- * @deprecated since version 2.6.9
- *
- * @return array All the rules + extended.
- */
- public function getMobileDetectionRulesExtended()
- {
- static $rules;
-
- if (!$rules) {
- // Merge all rules together.
- $rules = array_merge(
- self::$phoneDevices,
- self::$tabletDevices,
- self::$operatingSystems,
- self::$browsers,
- self::$utilities
- );
- }
-
- return $rules;
- }
-
- /**
- * Retrieve the current set of rules.
- *
- * @deprecated since version 2.6.9
- *
- * @return array
- */
- public function getRules()
- {
- if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
- return self::getMobileDetectionRulesExtended();
- } else {
- return self::getMobileDetectionRules();
- }
- }
-
- /**
- * Retrieve the list of mobile operating systems.
- *
- * @return array The list of mobile operating systems.
- */
- public static function getOperatingSystems()
- {
- return self::$operatingSystems;
- }
-
- /**
- * Check the HTTP headers for signs of mobile.
- * This is the fastest mobile check possible; it's used
- * inside isMobile() method.
- *
- * @return bool
- */
- public function checkHttpHeadersForMobile()
- {
-
- foreach($this->getMobileHeaders() as $mobileHeader => $matchType){
- if( isset($this->httpHeaders[$mobileHeader]) ){
- if( is_array($matchType['matches']) ){
- foreach($matchType['matches'] as $_match){
- if( strpos($this->httpHeaders[$mobileHeader], $_match) !== false ){
- return true;
- }
- }
- return false;
- } else {
- return true;
- }
- }
- }
-
- return false;
-
- }
-
- /**
- * Magic overloading method.
- *
- * @method boolean is[...]()
- * @param string $name
- * @param array $arguments
- * @return mixed
- * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
- */
- public function __call($name, $arguments)
- {
- //make sure the name starts with 'is', otherwise
- if (substr($name, 0, 2) != 'is') {
- throw new BadMethodCallException("No such method exists: $name");
- }
-
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
-
- $key = substr($name, 2);
-
- return $this->matchUAAgainstKey($key);
- }
-
- /**
- * Find a detection rule that matches the current User-agent.
- *
- * @param null $userAgent deprecated
- * @return boolean
- */
- protected function matchDetectionRulesAgainstUA($userAgent = null)
- {
- // Begin general search.
- foreach ($this->getRules() as $_regex) {
- if (empty($_regex)) {
- continue;
- }
- if ($this->match($_regex, $userAgent)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Search for a certain key in the rules array.
- * If the key is found the try to match the corresponding
- * regex agains the User-Agent.
- *
- * @param string $key
- * @param null $userAgent deprecated
- * @return mixed
- */
- protected function matchUAAgainstKey($key, $userAgent = null)
- {
- // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
- $key = strtolower($key);
-
- //change the keys to lower case
- $_rules = array_change_key_case($this->getRules());
-
- if (array_key_exists($key, $_rules)) {
- if (empty($_rules[$key])) {
- return null;
- }
-
- return $this->match($_rules[$key], $userAgent);
- }
-
- return false;
- }
-
- /**
- * Check if the device is mobile.
- * Returns true if any type of mobile device detected, including special ones
- * @param null $userAgent deprecated
- * @param null $httpHeaders deprecated
- * @return bool
- */
- public function isMobile($userAgent = null, $httpHeaders = null)
- {
-
- if ($httpHeaders) {
- $this->setHttpHeaders($httpHeaders);
- }
-
- if ($userAgent) {
- $this->setUserAgent($userAgent);
- }
-
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
-
- if ($this->checkHttpHeadersForMobile()) {
- return true;
- } else {
- return $this->matchDetectionRulesAgainstUA();
- }
-
- }
-
- /**
- * Check if the device is a tablet.
- * Return true if any type of tablet device is detected.
- *
- * @param string $userAgent deprecated
- * @param array $httpHeaders deprecated
- * @return bool
- */
- public function isTablet($userAgent = null, $httpHeaders = null)
- {
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
-
- foreach (self::$tabletDevices as $_regex) {
- if ($this->match($_regex, $userAgent)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * This method checks for a certain property in the
- * userAgent.
- * @todo: The httpHeaders part is not yet used.
- *
- * @param string $key
- * @param string $userAgent deprecated
- * @param string $httpHeaders deprecated
- * @return bool|int|null
- */
- public function is($key, $userAgent = null, $httpHeaders = null)
- {
- // Set the UA and HTTP headers only if needed (eg. batch mode).
- if ($httpHeaders) {
- $this->setHttpHeaders($httpHeaders);
- }
-
- if ($userAgent) {
- $this->setUserAgent($userAgent);
- }
-
- $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
-
- return $this->matchUAAgainstKey($key);
- }
-
- /**
- * Some detection rules are relative (not standard),
- * because of the diversity of devices, vendors and
- * their conventions in representing the User-Agent or
- * the HTTP headers.
- *
- * This method will be used to check custom regexes against
- * the User-Agent string.
- *
- * @param $regex
- * @param string $userAgent
- * @return bool
- *
- * @todo: search in the HTTP headers too.
- */
- public function match($regex, $userAgent = null)
- {
- // Escape the special character which is the delimiter.
- $regex = str_replace('/', '\/', $regex);
-
- return (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent));
- }
-
- /**
- * Get the properties array.
- *
- * @return array
- */
- public static function getProperties()
- {
- return self::$properties;
- }
-
- /**
- * Prepare the version number.
- *
- * @todo Remove the error supression from str_replace() call.
- *
- * @param string $ver The string version, like "2.6.21.2152";
- *
- * @return float
- */
- public function prepareVersionNo($ver)
- {
- $ver = str_replace(array('_', ' ', '/'), '.', $ver);
- $arrVer = explode('.', $ver, 2);
-
- if (isset($arrVer[1])) {
- $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
- }
-
- return (float) implode('.', $arrVer);
- }
-
- /**
- * Check the version of the given property in the User-Agent.
- * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
- *
- * @param string $propertyName The name of the property. See self::getProperties() array
- * keys for all possible properties.
- * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
- * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
- * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
- * invalid parameter will default to the this type as well.
- *
- * @return string|float The version of the property we are trying to extract.
- */
- public function version($propertyName, $type = self::VERSION_TYPE_STRING)
- {
- if (empty($propertyName)) {
- return false;
- }
-
- //set the $type to the default if we don't recognize the type
- if ($type != self::VERSION_TYPE_STRING && $type != self::VERSION_TYPE_FLOAT) {
- $type = self::VERSION_TYPE_STRING;
- }
-
- $properties = self::getProperties();
-
- // Check if the property exists in the properties array.
- if (array_key_exists($propertyName, $properties)) {
-
- // Prepare the pattern to be matched.
- // Make sure we always deal with an array (string is converted).
- $properties[$propertyName] = (array) $properties[$propertyName];
-
- foreach ($properties[$propertyName] as $propertyMatchString) {
-
- $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
-
- // Escape the special character which is the delimiter.
- $propertyPattern = str_replace('/', '\/', $propertyPattern);
-
- // Identify and extract the version.
- preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);
-
- if (!empty($match[1])) {
- $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1] );
-
- return $version;
- }
-
- }
-
- }
-
- return false;
- }
-
- /**
- * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
- *
- * @return string One of the self::MOBILE_GRADE_* constants.
- */
- public function mobileGrade()
- {
- $isMobile = $this->isMobile();
-
- if (
- // Apple iOS 3.2-5.1 - Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3), iPad 3 (5.1), original iPhone (3.1), iPhone 3 (3.2), 3GS (4.3), 4 (4.3 / 5.0), and 4S (5.1)
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)>=4.3 ||
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)>=3.1 ||
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)>=3.1 ||
-
- // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
- // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
- // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
- // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
- ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
-
- // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800
- $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT)>=7.0 ||
-
- // Blackberry 7 - Tested on BlackBerry Torch 9810
- // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670
- $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=6.0 ||
- // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
- $this->match('Playbook.*Tablet') ||
-
- // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0)
- ( $this->version('webOS', self::VERSION_TYPE_FLOAT)>=1.4 && $this->match('Palm|Pre|Pixi') ) ||
- // Palm WebOS 3.0 - Tested on HP TouchPad
- $this->match('hp.*TouchPad') ||
-
- // Firefox Mobile (12 Beta) - Tested on Android 2.3 device
- ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=12 ) ||
-
- // Chrome for Android - Tested on Android 4.0, 4.1 device
- ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=4.0 ) ||
-
- // Skyfire 4.1 - Tested on Android 2.3 device
- ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT)>=4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
-
- // Opera Mobile 11.5-12: Tested on Android 2.3
- ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>11 && $this->is('AndroidOS') ) ||
-
- // Meego 1.2 - Tested on Nokia 950 and N9
- $this->is('MeeGoOS') ||
-
- // Tizen (pre-release) - Tested on early hardware
- $this->is('Tizen') ||
-
- // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
- // @todo: more tests here!
- $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT)>=2.0 ||
-
- // UC Browser - Tested on Android 2.3 device
- ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
-
- // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
- ( $this->match('Kindle Fire') ||
- $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT)>=3.0 ) ||
-
- // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
- $this->is('AndroidOS') && $this->is('NookTablet') ||
-
- // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7
- $this->version('Chrome', self::VERSION_TYPE_FLOAT)>=11 && !$isMobile ||
-
- // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7
- $this->version('Safari', self::VERSION_TYPE_FLOAT)>=5.0 && !$isMobile ||
-
- // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7
- $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=4.0 && !$isMobile ||
-
- // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
- $this->version('MSIE', self::VERSION_TYPE_FLOAT)>=7.0 && !$isMobile ||
-
- // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
- // @reference: http://my.opera.com/community/openweb/idopera/
- $this->version('Opera', self::VERSION_TYPE_FLOAT)>=10 && !$isMobile
-
- ){
- return self::MOBILE_GRADE_A;
- }
-
- if (
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<3.1 ||
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)<3.1 ||
-
- // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
- $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
-
- //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
- ( $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)>=5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)<=6.5 &&
- ($this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 || $this->is('iOS')) ) ||
-
- // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
- $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
-
- // @todo: report this (tested on Nokia N71)
- $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11 && $this->is('SymbianOS')
- ){
- return self::MOBILE_GRADE_B;
- }
-
- if (
- // Blackberry 4.x - Tested on the Curve 8330
- $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<5.0 ||
- // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
- $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT)<=5.2
-
- ){
- return self::MOBILE_GRADE_C;
- }
-
- //All older smartphone platforms and featurephones - Any device that doesn't support media queries
- //will receive the basic, C grade experience.
- return self::MOBILE_GRADE_C;
- }
-}
diff --git a/data/module/Net/UserAgent/Mobile.php b/data/module/Net/UserAgent/Mobile.php
deleted file mode 100644
index 2f5b227412..0000000000
--- a/data/module/Net/UserAgent/Mobile.php
+++ /dev/null
@@ -1,457 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @since File available since Release 0.1
- */
-
-require_once dirname(__FILE__) . '/../../PEAR.php';
-require_once dirname(__FILE__) . '/Mobile/Error.php';
-
-// {{{ GLOBALS
-
-/**
- * globals for fallback on no match
- *
- * @global boolean $GLOBALS['NET_USERAGENT_MOBILE_FallbackOnNomatch']
- */
-$GLOBALS['NET_USERAGENT_MOBILE_FallbackOnNomatch'] = false;
-
-// }}}
-// {{{ Net_UserAgent_Mobile
-
-/**
- * HTTP mobile user agent string parser
- *
- * Net_UserAgent_Mobile parses HTTP_USER_AGENT strings of (mainly Japanese) mobile
- * HTTP user agents. It'll be useful in page dispatching by user agents.
- * This package was ported from Perl's HTTP::MobileAgent.
- * See {@link http://search.cpan.org/search?mode=module&query=HTTP-MobileAgent}
- *
- * SYNOPSIS:
- *
- * require_once 'Net/UserAgent/Mobile.php';
- *
- * $agent = &Net_UserAgent_Mobile::factory($agent_string);
- * // or $agent = &Net_UserAgent_Mobile::factory(); // to get from $_SERVER
- *
- * if ($agent->isDoCoMo()) {
- * // or if ($agent->getName() == 'DoCoMo')
- * // or if (strtolower(get_class($agent)) == 'http_mobileagent_docomo')
- * // it's NTT DoCoMo i-mode
- * // see what's available in Net_UserAgent_Mobile_DoCoMo
- * } elseif ($agent->isSoftBank()) {
- * // it's SoftBank
- * // see what's available in Net_UserAgent_Mobile_SoftBank
- * } elseif ($agent->isEZweb()) {
- * // it's KDDI/EZWeb
- * // see what's available in Net_UserAgent_Mobile_EZweb
- * } else {
- * // may be PC
- * // $agent is Net_UserAgent_Mobile_NonMobile
- * }
- *
- * $display = $agent->getDisplay(); // Net_UserAgent_Mobile_Display
- * if ($display->isColor()) {
- * ...
- * }
- *
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.0.0
- * @since Class available since Release 0.1
- */
-class Net_UserAgent_Mobile
-{
-
- // {{{ properties
-
- /**#@+
- * @access public
- */
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- /**#@+
- * @access public
- * @static
- */
-
- // }}}
- // {{{ factory()
-
- /**
- * create a new {@link Net_UserAgent_Mobile_Common} subclass instance
- *
- * parses HTTP headers and constructs {@link Net_UserAgent_Mobile_Common}
- * subclass instance.
- * If no argument is supplied, $_SERVER{'HTTP_*'} is used.
- *
- * @param string $userAgent User-Agent string
- * @return Net_UserAgent_Mobile_Common a newly created or an existing
- * Net_UserAgent_Mobile_Common object
- * @throws Net_UserAgent_Mobile_Error
- */
- function &factory($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- // parse User-Agent string
- if (Net_UserAgent_Mobile::isDoCoMo($userAgent)) {
- $driver = 'DoCoMo';
- } elseif (Net_UserAgent_Mobile::isEZweb($userAgent)) {
- $driver = 'EZweb';
- } elseif (Net_UserAgent_Mobile::isSoftBank($userAgent)) {
- $driver = 'SoftBank';
- } elseif (Net_UserAgent_Mobile::isWillcom($userAgent)) {
- $driver = 'Willcom';
- } else {
- $driver = 'NonMobile';
- }
-
- $class = "Net_UserAgent_Mobile_$driver";
-
- if (!class_exists($class)) {
- $file = dirname(__FILE__) . "/Mobile/{$driver}.php";
- if (!include_once $file) {
- return PEAR::raiseError(null,
- NET_USERAGENT_MOBILE_ERROR_NOT_FOUND,
- null, null,
- "Unable to include the $file file",
- 'Net_UserAgent_Mobile_Error', true
- );
- }
- }
-
- PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
- $instance = new $class($userAgent);
- PEAR::staticPopErrorHandling();
- $error = &$instance->getError();
- if (Net_UserAgent_Mobile::isError($error)) {
- if ($GLOBALS['NET_USERAGENT_MOBILE_FallbackOnNomatch']
- && $error->getCode() == NET_USERAGENT_MOBILE_ERROR_NOMATCH
- ) {
- $instance = &Net_UserAgent_Mobile::factory('Net_UserAgent_Mobile_Fallback_On_NoMatch');
- return $instance;
- }
-
- return PEAR::raiseError($error);
- }
-
- return $instance;
- }
-
- // }}}
- // {{{ singleton()
-
- /**
- * creates a new {@link Net_UserAgent_Mobile_Common} subclass instance or returns
- * a instance from existent ones
- *
- * @param string $userAgent User-Agent string
- * @return Net_UserAgent_Mobile_Common a newly created or an existing
- * Net_UserAgent_Mobile_Common object
- * @throws Net_UserAgent_Mobile_Error
- */
- function &singleton($userAgent = null)
- {
- static $instances;
-
- if (!isset($instances)) {
- $instances = array();
- }
-
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (!array_key_exists($userAgent, $instances)) {
- $instances[$userAgent] = Net_UserAgent_Mobile::factory($userAgent);
- }
-
- return $instances[$userAgent];
- }
-
- // }}}
- // {{{ isError()
-
- /**
- * tell whether a result code from a Net_UserAgent_Mobile method is an error
- *
- * @param integer $value result code
- * @return boolean whether $value is an {@link Net_UserAgent_Mobile_Error}
- */
- function isError($value)
- {
- return is_object($value)
- && (strtolower(get_class($value)) == strtolower('Net_UserAgent_Mobile_Error')
- || is_subclass_of($value, 'Net_UserAgent_Mobile_Error'));
- }
-
- // }}}
- // {{{ errorMessage()
-
- /**
- * return a textual error message for a Net_UserAgent_Mobile error code
- *
- * @param integer $value error code
- * @return string error message, or null if the error code was not recognized
- */
- function errorMessage($value)
- {
- static $errorMessages;
- if (!isset($errorMessages)) {
- $errorMessages = array(
- NET_USERAGENT_MOBILE_ERROR => 'unknown error',
- NET_USERAGENT_MOBILE_ERROR_NOMATCH => 'no match',
- NET_USERAGENT_MOBILE_ERROR_NOT_FOUND => 'not found',
- NET_USERAGENT_MOBILE_OK => 'no error'
- );
- }
-
- if (Net_UserAgent_Mobile::isError($value)) {
- $value = $value->getCode();
- }
-
- return isset($errorMessages[$value]) ?
- $errorMessages[$value] :
- $errorMessages[NET_USERAGENT_MOBILE_ERROR];
- }
-
- // }}}
- // {{{ isMobile()
-
- /**
- * Checks whether or not the user agent is mobile by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isMobile($userAgent = null)
- {
- if (Net_UserAgent_Mobile::isDoCoMo($userAgent)) {
- return true;
- } elseif (Net_UserAgent_Mobile::isEZweb($userAgent)) {
- return true;
- } elseif (Net_UserAgent_Mobile::isSoftBank($userAgent)) {
- return true;
- } elseif (Net_UserAgent_Mobile::isWillcom($userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isDoCoMo()
-
- /**
- * Checks whether or not the user agent is DoCoMo by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isDoCoMo($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^DoCoMo!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isEZweb()
-
- /**
- * Checks whether or not the user agent is EZweb by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isEZweb($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^KDDI-!', $userAgent)) {
- return true;
- } elseif (preg_match('!^UP\.Browser!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isSoftBank()
-
- /**
- * Checks whether or not the user agent is SoftBank by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSoftBank($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^SoftBank!', $userAgent)) {
- return true;
- } elseif (preg_match('!^Semulator!', $userAgent)) {
- return true;
- } elseif (preg_match('!^Vodafone!', $userAgent)) {
- return true;
- } elseif (preg_match('!^Vemulator!', $userAgent)) {
- return true;
- } elseif (preg_match('!^MOT-!', $userAgent)) {
- return true;
- } elseif (preg_match('!^MOTEMULATOR!', $userAgent)) {
- return true;
- } elseif (preg_match('!^J-PHONE!', $userAgent)) {
- return true;
- } elseif (preg_match('!^J-EMULATOR!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isWillcom()
-
- /**
- * Checks whether or not the user agent is Willcom by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isWillcom($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^Mozilla/3\.0\((?:DDIPOCKET|WILLCOM);!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isSmartphone()
-
- /**
- * Checks whether or not the user agent is Smartphone by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSmartphone($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- $useragents = array(
- 'iPhone', // Apple iPhone
- 'iPod', // Apple iPod touch
- 'Android', // 1.5+ Android
- 'dream', // Pre 1.5 Android
- 'CUPCAKE', // 1.5+ Android
- 'blackberry9500', // Storm
- 'blackberry9530', // Storm
- 'blackberry9520', // Storm v2
- 'blackberry9550', // Storm v2
- 'blackberry9800', // Torch
- 'webOS', // Palm Pre Experimental
- 'incognito', // Other iPhone browser
- 'webmate', // Other iPhone browser
- 'Windows Phone OS' // Windows Phone
- );
-
- $pattern = implode("|", $useragents);
- return preg_match('/'.$pattern.'/', $userAgent);
- }
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- // }}}
-}
-
-// }}}
-
-/*
- * Local Variables:
- * mode: php
- * coding: iso-8859-1
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/data/module/Net/UserAgent/Mobile/Common.php b/data/module/Net/UserAgent/Mobile/Common.php
deleted file mode 100644
index dc8c8ee261..0000000000
--- a/data/module/Net/UserAgent/Mobile/Common.php
+++ /dev/null
@@ -1,528 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @since File available since Release 0.1
- */
-
-require_once dirname(__FILE__) . '/Error.php';
-require_once dirname(__FILE__) . '/../../../PEAR.php';
-
-// {{{ Net_UserAgent_Mobile_Common
-
-/**
- * Base class that is extended by each user agents implementor
- *
- * Net_UserAgent_Mobile_Common is a class for mobile user agent
- * abstraction layer on Net_UserAgent_Mobile.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.0.0
- * @since Class available since Release 0.1
- */
-class Net_UserAgent_Mobile_Common
-{
-
- // {{{ properties
-
- /**#@+
- * @access public
- */
-
- /**
- * User-Agent name like 'DoCoMo'
- * @var string
- */
- var $name;
-
- /**
- * User-Agent version number like '1.0'
- * @var string
- */
- var $version;
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**
- * {@link Net_UserAgent_Mobile_Display} object
- * @var object {@link Net_UserAgent_Mobile_Display}
- */
- var $_display;
-
- /**
- * {@link Net_UserAgent_Mobile_Error} object for error handling in the constructor
- * @var object
- **/
- var $_error;
-
- /**
- * The User-Agent string.
- * @var string
- * @since Property available since Release 0.31.0
- **/
- var $_userAgent;
-
- /**
- * The model name of the user agent.
- *
- * @var string
- * @since Property available since Release 0.31.0
- */
- var $_model;
-
- /**
- * The raw model name of the user agent.
- *
- * @var string
- * @since Property available since Release 0.31.0
- */
- var $_rawModel;
-
- /**#@-*/
-
- /**#@+
- * @access public
- */
-
- // }}}
- // {{{ constructor
-
- /**
- * constructor
- *
- * @param string $userAgent User-Agent string
- */
- function Net_UserAgent_Mobile_Common($userAgent)
- {
- $this->_userAgent = $userAgent;
-
- $result = $this->parse($userAgent);
- if (PEAR::isError($result)) {
- $this->_error = &$result;
- }
- }
-
- // }}}
- // {{{ getError
-
- /**
- * Gets a Net_UserAgent_Mobile_Error object.
- *
- * @param object {@link Net_UserAgent_Mobile_Error} object when setting an error
- * @return Net_UserAgent_Mobile_Error
- * @since Method available since Release 1.0.0RC2
- */
- function &getError()
- {
- if (is_null($this->_error)) {
- $return = null;
- return $return;
- }
-
- return $this->_error;
- }
-
- // }}}
- // {{{ getUserAgent()
-
- /**
- * returns User-Agent string
- *
- * @return string
- */
- function getUserAgent()
- {
- return $this->_userAgent;
- }
-
- // }}}
- // {{{ getHeader()
-
- /**
- * returns a specified HTTP header
- *
- * @param string $header
- * @return string
- */
- function getHeader($header)
- {
- return @$_SERVER[ 'HTTP_' . str_replace('-', '_', $header) ];
- }
-
- // }}}
- // {{{ getName()
-
- /**
- * returns User-Agent name like 'DoCoMo'
- *
- * @return string
- */
- function getName()
- {
- return $this->name;
- }
-
- // }}}
- // {{{ getDisplay()
-
- /**
- * returns {@link Net_UserAgent_Mobile_Disply} object
- *
- * @return Net_UserAgent_Mobile_Display
- */
- function getDisplay()
- {
- if (is_null($this->_display)) {
- $this->_display = $this->makeDisplay();
- }
-
- return $this->_display;
- }
-
- // }}}
- // {{{ getVersion()
-
- /**
- * returns User-Agent version number like '1.0'
- *
- * @return string
- */
- function getVersion()
- {
- return $this->version;
- }
-
- // }}}
- // {{{ noMatch()
-
- /**
- * generates a warning message for new variants
- *
- * @throws Net_UserAgent_Mobile_Error
- */
- function noMatch()
- {
- return PEAR::raiseError($this->getUserAgent() . ': might be new variants. Please contact the author of Net_UserAgent_Mobile!',
- NET_USERAGENT_MOBILE_ERROR_NOMATCH,
- null,
- null,
- null,
- 'Net_UserAgent_Mobile_Error'
- );
- }
-
- // }}}
- // {{{ parse()
-
- /**
- * Parses HTTP_USER_AGENT string.
- *
- * @param string $userAgent User-Agent string
- * @abstract
- */
- function parse($userAgent) {}
-
- // }}}
- // {{{ makeDisplay()
-
- /**
- * create a new Net_UserAgent_Mobile_Display class instance (should be
- * implemented in subclasses)
- *
- * @return Net_UserAgent_Mobile_Display
- * @abstract
- */
- function makeDisplay() {}
-
- // }}}
- // {{{ isDoCoMo()
-
- /**
- * returns true if the agent is DoCoMo
- *
- * @return boolean
- */
- function isDoCoMo()
- {
- return false;
- }
-
- // }}}
- // {{{ isJPhone()
-
- /**
- * returns true if the agent is J-PHONE
- *
- * @return boolean
- */
- function isJPhone()
- {
- return false;
- }
-
- // }}}
- // {{{ isVodafone()
-
- /**
- * returns true if the agent is Vodafone
- *
- * @return boolean
- */
- function isVodafone()
- {
- return false;
- }
-
- // }}}
- // {{{ isEZweb()
-
- /**
- * returns true if the agent is EZweb
- *
- * @return boolean
- */
- function isEZweb()
- {
- return false;
- }
-
- // }}}
- // {{{ isAirHPhone()
-
- /**
- * returns true if the agent is AirH"PHONE
- *
- * @return boolean
- */
- function isAirHPhone()
- {
- return false;
- }
-
- // }}}
- // {{{ isNonMobile()
-
- /**
- * returns true if the agent is NonMobile
- *
- * @return boolean
- */
- function isNonMobile()
- {
- return false;
- }
-
- // }}}
- // {{{ isTUKa()
-
- /**
- * returns true if the agent is TU-Ka
- *
- * @return boolean
- */
- function isTUKa()
- {
- return false;
- }
-
- // }}}
- // {{{ isWAP1()
-
- /**
- * returns true if the agent can speak WAP1 protocol
- *
- * @return boolean
- */
- function isWAP1()
- {
- return $this->isEZweb() && !$this->isWAP2();
- }
-
- // }}}
- // {{{ isWAP2()
-
- /**
- * returns true if the agent can speak WAP2 protocol
- *
- * @return boolean
- */
- function isWAP2()
- {
- return $this->isEZweb() && $this->isXHTMLCompliant();
- }
-
- // }}}
- // {{{ getCarrierShortName()
-
- /**
- * returns the short name of the carrier
- *
- * @abstract
- */
- function getCarrierShortName()
- {
- die();
- }
-
- // }}}
- // {{{ getCarrierLongName()
-
- /**
- * returns the long name of the carrier
- *
- * @abstract
- */
- function getCarrierLongName()
- {
- die();
- }
-
- // }}}
- // {{{ isSoftBank()
-
- /**
- * Returns whether the agent is SoftBank or not.
- *
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSoftBank()
- {
- return false;
- }
-
- // }}}
- // {{{ isWillcom()
-
- /**
- * Returns whether the agent is Willcom or not.
- *
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isWillcom()
- {
- return false;
- }
-
- // }}}
- // {{{ isSmartphone()
-
- /**
- * Returns whether the agent is Smartphone or not.
- *
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSmartphone()
- {
- return false;
- }
-
-
- // }}}
- // {{{ getModel()
-
- /**
- * Returns the model name of the user agent.
- *
- * @return string
- * @since Method available since Release 0.31.0
- */
- function getModel()
- {
- if (is_null($this->_model)) {
- return $this->_rawModel;
- } else {
- return $this->_model;
- }
- }
-
- // }}}
- // {{{ getRawModel()
-
- /**
- * Returns the raw model name of the user agent.
- *
- * @return string
- * @since Method available since Release 0.31.0
- */
- function getRawModel()
- {
- return $this->_rawModel;
- }
-
- // }}}
- // {{{ getUID()
-
- /**
- * Gets the UID of a subscriber.
- *
- * @return string
- * @since Method available since Release 1.0.0RC1
- */
- function getUID() {}
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- // }}}
-}
-
-// }}}
-
-/*
- * Local Variables:
- * mode: php
- * coding: iso-8859-1
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/data/module/Net/UserAgent/Mobile/Display.php b/data/module/Net/UserAgent/Mobile/Display.php
deleted file mode 100644
index 41c03b0a7b..0000000000
--- a/data/module/Net/UserAgent/Mobile/Display.php
+++ /dev/null
@@ -1,285 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @since File available since Release 0.1
- */
-
-// {{{ Net_UserAgent_Mobile_Display
-
-/**
- * Display information for Net_UserAgent_Mobile
- *
- * Net_UserAgent_Mobile_Display is a class for display information on
- * {@link Net_UserAgent_Mobile}. Handy for image resizing or dispatching.
- *
- * SYNOPSIS:
- *
- * require_once 'Net/UserAgent/Mobile.php';
- *
- * $agent = &Net_UserAgent_Mobile::factory();
- * $display = $agent->getDisplay();
- *
- * $width = $display->getWidth();
- * $height = $display->getHeight();
- * list($width, $height) = $display->getSize();
- *
- * if ($display->isColor()) {
- * $depth = $display->getDepth();
- * }
- *
- * // only available in DoCoMo 505i
- * $width_bytes = $display->getWidthBytes();
- * $height_bytes = $display->getHeightBytes();
- *
- *
- * USING EXTERNAL MAP FILE:
- * If the environment variable DOCOMO_MAP exists, the specified XML data will be used
- * for DoCoMo display information.
- *
- * ex) Please add the following code.
- * $_SERVER['DOCOMO_MAP'] = '/path/to/DoCoMoMap.xml';
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.0.0
- * @since Class available since Release 0.1
- */
-class Net_UserAgent_Mobile_Display
-{
-
- // {{{ properties
-
- /**#@+
- * @access public
- */
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**
- * width of the display
- * @var integer
- */
- var $_width;
-
- /**
- * height of the display
- * @var integer
- */
- var $_height;
-
- /**
- * depth of the display
- * @var integer
- */
- var $_depth;
-
- /**
- * color capability of the display
- * @var boolean
- */
- var $_color;
-
- /**
- * width (bytes) of the display
- * @var integer
- */
- var $_widthBytes;
-
- /**
- * height (bytes) of the display
- * @var integer
- */
- var $_heightBytes;
-
- /**#@-*/
-
- /**#@+
- * @access public
- */
-
- // }}}
- // {{{ constructor
-
- /**
- * constructor
- *
- * @param array $data display infomation
- */
- function Net_UserAgent_Mobile_Display($data)
- {
- $this->_width = (integer)@$data['width'];
- $this->_height = (integer)@$data['height'];
- $this->_depth = (integer)@$data['depth'];
- $this->_color = (boolean)@$data['color'];
-
- $this->_widthBytes = (integer)@$data['width_bytes'];
- $this->_heightBytes = (integer)@$data['height_bytes'];
- }
-
- // }}}
- // {{{ calcSize()
-
- /**
- * returns width * height of the display
- *
- * @return integer
- */
- function calcSize()
- {
- return $this->_width * $this->_height;
- }
-
- // }}}
- // {{{ getSize()
-
- /**
- * returns width with height of the display
- *
- * @return array
- */
- function getSize()
- {
- return array($this->_width, $this->_height);
- }
-
- // }}}
- // {{{ getWidth()
-
- /**
- * returns width of the display
- *
- * @return integer
- */
- function getWidth()
- {
- return $this->_width;
- }
-
- // }}}
- // {{{ getHeight()
-
- /**
- * returns height of the display
- *
- * @return integer
- */
- function getHeight()
- {
- return $this->_height;
- }
-
- // }}}
- // {{{ getDepth()
-
- /**
- * returns depth of the display
- *
- * @return integer
- */
- function getDepth()
- {
- return $this->_depth;
- }
-
- // }}}
- // {{{ isColor()
-
- /**
- * returns true if the display has color capability
- *
- * @return boolean
- */
- function isColor()
- {
- return $this->_color;
- }
-
- // }}}
- // {{{ getWidthBytes()
-
- /**
- * returns width (bytes) of the display
- *
- * @return integer
- */
- function getWidthBytes()
- {
- return $this->_widthBytes;
- }
-
- // }}}
- // {{{ getHeightBytes()
-
- /**
- * returns height (bytes) of the display
- *
- * @return integer
- */
- function getHeightBytes()
- {
- return $this->_heightBytes;
- }
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- // }}}
-}
-
-// }}}
-
-/*
- * Local Variables:
- * mode: php
- * coding: iso-8859-1
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/data/module/Net/UserAgent/Mobile/DoCoMo.php b/data/module/Net/UserAgent/Mobile/DoCoMo.php
deleted file mode 100644
index ada57a5f36..0000000000
--- a/data/module/Net/UserAgent/Mobile/DoCoMo.php
+++ /dev/null
@@ -1,988 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://www.nttdocomo.co.jp/service/imode/make/content/spec/useragent/index.html
- * @link http://www.nttdocomo.co.jp/service/imode/make/content/browser/browser2/useragent/index.html
- * @since File available since Release 0.1
- */
-
-require_once dirname(__FILE__) . '/Common.php';
-require_once dirname(__FILE__) . '/Display.php';
-require_once dirname(__FILE__) . '/../Mobile.php';
-
-// {{{ Net_UserAgent_Mobile_DoCoMo
-
-/**
- * NTT DoCoMo implementation
- *
- * Net_UserAgent_Mobile_DoCoMo is a subclass of {@link Net_UserAgent_Mobile_Common},
- * which implements NTT docomo i-mode user agents.
- *
- * SYNOPSIS:
- *
- * require_once 'Net/UserAgent/Mobile.php';
- *
- * $_SERVER['HTTP_USER_AGENT'] = 'DoCoMo/1.0/P502i/c10';
- * $agent = &Net_UserAgent_Mobile::factory();
- *
- * printf("Name: %s\n", $agent->getName()); // 'DoCoMo'
- * printf("Version: %s\n", $agent->getVersion()); // 1.0
- * printf("HTML version: %s\n", $agent->getHTMLVersion()); // 2.0
- * printf("Model: %s\n", $agent->getModel()); // 'P502i'
- * printf("Cache: %dk\n", $agent->getCacheSize()); // 10
- * if ($agent->isFOMA()) {
- * print "FOMA\n"; // false
- * }
- * printf("Vendor: %s\n", $agent->getVendor()); // 'P'
- * printf("Series: %s\n", $agent->getSeries()); // '502i'
- *
- * // only available with
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.0.0
- * @link http://www.nttdocomo.co.jp/service/imode/make/content/spec/useragent/index.html
- * @link http://www.nttdocomo.co.jp/service/imode/make/content/browser/browser2/useragent/index.html
- * @since Class available since Release 0.1
- */
-class Net_UserAgent_Mobile_DoCoMo extends Net_UserAgent_Mobile_Common
-{
-
- // {{{ properties
-
- /**#@+
- * @access public
- */
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**
- * status of the cache (TC, TB, TD, TJ)
- * @var string
- */
- var $_status;
-
- /**
- * bandwidth like 32 as kilobytes unit
- * @var integer
- */
- var $_bandwidth;
-
- /**
- * hardware unique serial number
- * @var string
- */
- var $_serialNumber;
-
- /**
- * whether it's FOMA or not
- * @var boolean
- */
- var $_isFOMA = false;
-
- /**
- * FOMA Card ID (20 digit alphanumeric)
- * @var string
- */
- var $_cardID;
-
- /**
- * comment on user agent string like 'Google Proxy'
- * @var string
- */
- var $_comment;
-
- /**
- * cache size as killobytes unit
- * @var integer
- */
- var $_cacheSize;
-
- /**
- * width and height of the display
- * @var string
- */
- var $_displayBytes;
-
- /**
- * The model names which have GPS capability.
- *
- * @var array
- * @since Property available since Release 1.0.0RC1
- */
- var $_gpsModels = array('F884i',
- 'F801i',
- 'F905iBiz',
- 'SO905iCS',
- 'N905iBiz',
- 'N905imyu',
- 'SO905i',
- 'F905i',
- 'P905i',
- 'N905i',
- 'D905i',
- 'SH905i',
- 'P904i',
- 'D904i',
- 'F904i',
- 'N904i',
- 'SH904i',
- 'F883iESS',
- 'F883iES',
- 'F903iBSC',
- 'SO903i',
- 'F903i',
- 'D903i',
- 'N903i',
- 'P903i',
- 'SH903i',
- 'SA800i',
- 'SA702i',
- 'SA700iS',
- 'F505iGPS',
- 'F661i',
- 'F884iES',
- 'N906iL',
- 'P906i',
- 'SO906i',
- 'SH906i',
- 'N906imyu',
- 'F906i',
- 'N906i',
- 'F01A',
- 'F03A',
- 'F06A',
- 'F05A',
- 'P01A',
- 'P02A',
- 'SH01A',
- 'SH02A',
- 'SH03A',
- 'SH04A',
- 'N01A',
- 'N02A',
- 'P07A3',
- 'N06A3',
- 'N08A3',
- 'P08A3',
- 'P09A3',
- 'N09A3',
- 'F09A3',
- 'SH05A3',
- 'SH06A3',
- 'SH07A3'
- );
-
- /**
- * The HTML versions which maps models to HTML versions.
- *
- * @var array
- * @since Property available since Release 1.0.0RC1
- */
- var $_htmlVersions = array(
- 'D501i' => '1.0',
- 'F501i' => '1.0',
- 'N501i' => '1.0',
- 'P501i' => '1.0',
- 'D502i' => '2.0',
- 'F502i' => '2.0',
- 'N502i' => '2.0',
- 'P502i' => '2.0',
- 'NM502i' => '2.0',
- 'SO502i' => '2.0',
- 'F502it' => '2.0',
- 'N502it' => '2.0',
- 'SO502iWM' => '2.0',
- 'SH821i' => '2.0',
- 'N821i' => '2.0',
- 'P821i' => '2.0',
- 'D209i' => '2.0',
- 'ER209i' => '2.0',
- 'F209i' => '2.0',
- 'KO209i' => '2.0',
- 'N209i' => '2.0',
- 'P209i' => '2.0',
- 'P209iS' => '2.0',
- 'R209i' => '2.0',
- 'P651ps' => '2.0',
- 'R691i' => '2.0',
- 'F210i' => '2.0',
- 'N210i' => '2.0',
- 'P210i' => '2.0',
- 'KO210i' => '2.0',
- 'F671i' => '2.0',
- 'D210i' => '3.0',
- 'SO210i' => '3.0',
- 'F503i' => '3.0',
- 'F503iS' => '3.0',
- 'P503i' => '3.0',
- 'P503iS' => '3.0',
- 'N503i' => '3.0',
- 'N503iS' => '3.0',
- 'SO503i' => '3.0',
- 'SO503iS' => '3.0',
- 'D503i' => '3.0',
- 'D503iS' => '3.0',
- 'F211i' => '3.0',
- 'D211i' => '3.0',
- 'N211i' => '3.0',
- 'N211iS' => '3.0',
- 'P211i' => '3.0',
- 'P211iS' => '3.0',
- 'SO211i' => '3.0',
- 'R211i' => '3.0',
- 'SH251i' => '3.0',
- 'SH251iS' => '3.0',
- 'R692i' => '3.0',
- 'N2001' => '3.0',
- 'N2002' => '3.0',
- 'P2002' => '3.0',
- 'D2101V' => '3.0',
- 'P2101V' => '3.0',
- 'SH2101V' => '3.0',
- 'T2101V' => '3.0',
- 'D504i' => '4.0',
- 'F504i' => '4.0',
- 'F504iS' => '4.0',
- 'N504i' => '4.0',
- 'N504iS' => '4.0',
- 'SO504i' => '4.0',
- 'P504i' => '4.0',
- 'P504iS' => '4.0',
- 'D251i' => '4.0',
- 'D251iS' => '4.0',
- 'F251i' => '4.0',
- 'N251i' => '4.0',
- 'N251iS' => '4.0',
- 'P251iS' => '4.0',
- 'F671iS' => '4.0',
- 'F212i' => '4.0',
- 'SO212i' => '4.0',
- 'F661i' => '4.0',
- 'F672i' => '4.0',
- 'SO213i' => '4.0',
- 'SO213iS' => '4.0',
- 'SO213iWR' => '4.0',
- 'F2051' => '4.0',
- 'N2051' => '4.0',
- 'P2102V' => '4.0',
- 'F2102V' => '4.0',
- 'N2102V' => '4.0',
- 'N2701' => '4.0',
- 'NM850iG' => '4.0',
- 'NM705i' => '4.0',
- 'NM706i' => '4.0',
- 'D505i' => '5.0',
- 'SO505i' => '5.0',
- 'SH505i' => '5.0',
- 'N505i' => '5.0',
- 'F505i' => '5.0',
- 'P505i' => '5.0',
- 'D505iS' => '5.0',
- 'P505iS' => '5.0',
- 'N505iS' => '5.0',
- 'SO505iS' => '5.0',
- 'SH505iS' => '5.0',
- 'F505iGPS' => '5.0',
- 'D252i' => '5.0',
- 'SH252i' => '5.0',
- 'P252i' => '5.0',
- 'N252i' => '5.0',
- 'P252iS' => '5.0',
- 'D506i' => '5.0',
- 'F506i' => '5.0',
- 'N506i' => '5.0',
- 'P506iC' => '5.0',
- 'SH506iC' => '5.0',
- 'SO506iC' => '5.0',
- 'N506iS' => '5.0',
- 'SO506i' => '5.0',
- 'SO506iS' => '5.0',
- 'N506iS2' => '5.0',
- 'D253i' => '5.0',
- 'N253i' => '5.0',
- 'P253i' => '5.0',
- 'D253iWM' => '5.0',
- 'P253iS' => '5.0',
- 'P213i' => '5.0',
- 'F900i' => '5.0',
- 'N900i' => '5.0',
- 'P900i' => '5.0',
- 'SH900i' => '5.0',
- 'F900iT' => '5.0',
- 'P900iV' => '5.0',
- 'N900iS' => '5.0',
- 'D900i' => '5.0',
- 'F900iC' => '5.0',
- 'N900iL' => '5.0',
- 'N900iG' => '5.0',
- 'F880iES' => '5.0',
- 'SH901iC' => '5.0',
- 'F901iC' => '5.0',
- 'N901iC' => '5.0',
- 'D901i' => '5.0',
- 'P901i' => '5.0',
- 'SH901iS' => '5.0',
- 'F901iS' => '5.0',
- 'D901iS' => '5.0',
- 'P901iS' => '5.0',
- 'N901iS' => '5.0',
- 'P901iTV' => '5.0',
- 'F700i' => '5.0',
- 'SH700i' => '5.0',
- 'N700i' => '5.0',
- 'P700i' => '5.0',
- 'F700iS' => '5.0',
- 'SH700iS' => '5.0',
- 'SA700iS' => '5.0',
- 'SH851i' => '5.0',
- 'P851i' => '5.0',
- 'F881iES' => '5.0',
- 'D701i' => '5.0',
- 'N701i' => '5.0',
- 'P701iD' => '5.0',
- 'D701iWM' => '5.0',
- 'N701iECO' => '5.0',
- 'SA800i' => '5.0',
- 'L600i' => '5.0',
- 'N600i' => '5.0',
- 'L601i' => '5.0',
- 'M702iS' => '5.0',
- 'M702iG' => '5.0',
- 'L602i' => '5.0',
- 'F902i' => '6.0',
- 'D902i' => '6.0',
- 'N902i' => '6.0',
- 'P902i' => '6.0',
- 'SH902i' => '6.0',
- 'SO902i' => '6.0',
- 'SH902iS' => '6.0',
- 'P902iS' => '6.0',
- 'N902iS' => '6.0',
- 'D902iS' => '6.0',
- 'F902iS' => '6.0',
- 'SO902iWP+' => '6.0',
- 'SH902iSL' => '6.0',
- 'N902iX' => '6.0',
- 'N902iL' => '6.0',
- 'P702i' => '6.0',
- 'N702iD' => '6.0',
- 'F702iD' => '6.0',
- 'SH702iD' => '6.0',
- 'D702i' => '6.0',
- 'SO702i' => '6.0',
- 'D702iBCL' => '6.0',
- 'SA702i' => '6.0',
- 'SH702iS' => '6.0',
- 'N702iS' => '6.0',
- 'P702iD' => '6.0',
- 'D702iF' => '6.0',
- 'D851iWM' => '6.0',
- 'F882iES' => '6.0',
- 'N601i' => '6.0',
- 'D800iDS' => '6.0',
- 'P703imyu' => '6.0',
- 'F883i' => '6.0',
- 'F883iS' => '6.0',
- 'P704imyu' => '6.0',
- 'L704i' => '6.0',
- 'L705i' => '6.0',
- 'L705iX' => '6.0',
- 'L852i' => '6.0',
- 'L706ie' => '6.0',
- 'L01A' => '6.0',
- 'L03A' => '6.0',
- 'SH903i' => '7.0',
- 'P903i' => '7.0',
- 'N903i' => '7.0',
- 'D903i' => '7.0',
- 'F903i' => '7.0',
- 'SO903i' => '7.0',
- 'D903iTV' => '7.0',
- 'F903iX' => '7.0',
- 'P903iTV' => '7.0',
- 'SH903iTV' => '7.0',
- 'F903iBSC' => '7.0',
- 'P903iX' => '7.0',
- 'SO903iTV' => '7.0',
- 'N703iD' => '7.0',
- 'F703i' => '7.0',
- 'P703i' => '7.0',
- 'D703i' => '7.0',
- 'SH703i' => '7.0',
- 'N703imyu' => '7.0',
- 'SO703i' => '7.0',
- 'SH904i' => '7.0',
- 'N904i' => '7.0',
- 'F904i' => '7.0',
- 'D904i' => '7.0',
- 'P904i' => '7.0',
- 'SO704i' => '7.0',
- 'F704i' => '7.0',
- 'N704imyu' => '7.0',
- 'SH704i' => '7.0',
- 'D704i' => '7.0',
- 'P704i' => '7.0',
- 'F883iES' => '7.0',
- 'F883iESS' => '7.0',
- 'F801i' => '7.0',
- 'F705i' => '7.0',
- 'D705i' => '7.0',
- 'D705imyu' => '7.0',
- 'SH705i' => '7.0',
- 'SH705i2' => '7.0',
- 'SH706ie' => '7.0',
- 'F05A' => '7.0',
- 'SH905i' => '7.1',
- 'D905i' => '7.1',
- 'N905i' => '7.1',
- 'P905i' => '7.1',
- 'F905i' => '7.1',
- 'SO905i' => '7.1',
- 'N905imyu' => '7.1',
- 'N905iBiz' => '7.1',
- 'SH905iTV' => '7.1',
- 'SO905iCS' => '7.1',
- 'F905iBiz' => '7.1',
- 'P905iTV' => '7.1',
- 'P705i' => '7.1',
- 'N705i' => '7.1',
- 'N705imyu' => '7.1',
- 'P705imyu' => '7.1',
- 'SO705i' => '7.1',
- 'P705iCL' => '7.1',
- 'F884i' => '7.1',
- 'F884iES' => '7.1',
- 'N906iL' => '7.1',
- 'N706i' => '7.1',
- 'SO706i' => '7.1',
- 'P706imyu' => '7.1',
- 'N706ie' => '7.1',
- 'N706i2' => '7.1',
- 'N03A' => '7.1',
- 'N05A' => '7.1',
- 'F07A' => '7.1',
- 'P906i' => '7.2',
- 'SO906i' => '7.2',
- 'SH906i' => '7.2',
- 'N906imyu' => '7.2',
- 'F906i' => '7.2',
- 'N906i' => '7.2',
- 'SH906iTV' => '7.2',
- 'F706i' => '7.2',
- 'SH706i' => '7.2',
- 'P706ie' => '7.2',
- 'SH706iw' => '7.2',
- 'F01A' => '7.2',
- 'F02A' => '7.2',
- 'F03A' => '7.2',
- 'F04A' => '7.2',
- 'F06A' => '7.2',
- 'P01A' => '7.2',
- 'P02A' => '7.2',
- 'P03A' => '7.2',
- 'P04A' => '7.2',
- 'P05A' => '7.2',
- 'P06A' => '7.2',
- 'SH01A' => '7.2',
- 'SH02A' => '7.2',
- 'SH03A' => '7.2',
- 'SH04A' => '7.2',
- 'N01A' => '7.2',
- 'N02A' => '7.2',
- 'N04A' => '7.2',
- 'P10A' => '7.2',
- );
-
- /**#@-*/
-
- /**#@+
- * @access public
- */
-
- // }}}
- // {{{ isDoCoMo()
-
- /**
- * returns true
- *
- * @return boolean
- */
- function isDoCoMo()
- {
- return true;
- }
-
- // }}}
- // {{{ parse()
-
- /**
- * Parses HTTP_USER_AGENT string.
- *
- * @param string $userAgent User-Agent string
- * @throws Net_UserAgent_Mobile_Error
- */
- function parse($userAgent)
- {
- @list($main, $foma_or_comment) = explode(' ', $userAgent, 2);
-
- if ($foma_or_comment
- && preg_match('/^\((.*)\)$/', $foma_or_comment, $matches)
- ) {
-
- // DoCoMo/1.0/P209is (Google CHTML Proxy/1.0)
- $this->_comment = $matches[1];
- $result = $this->_parseMain($main);
- } elseif ($foma_or_comment) {
-
- // DoCoMo/2.0 N2001(c10;ser0123456789abcde;icc01234567890123456789)
- $this->_isFOMA = true;
- @list($this->name, $this->version) = explode('/', $main);
- $result = $this->_parseFOMA($foma_or_comment);
- } else {
-
- // DoCoMo/1.0/R692i/c10
- $result = $this->_parseMain($main);
- }
-
- if (Net_UserAgent_Mobile::isError($result)) {
- return $result;
- }
- }
-
- // }}}
- // {{{ makeDisplay()
-
- /**
- * create a new {@link Net_UserAgent_Mobile_Display} class instance
- *
- * @return Net_UserAgent_Mobile_Display
- */
- function makeDisplay()
- {
- include_once dirname(__FILE__) . '/DoCoMo/ScreenInfo.php';
-
- $screenInfo = &Net_UserAgent_Mobile_DoCoMo_ScreenInfo::singleton();
- $display = $screenInfo->get($this->getModel());
- if (!is_null($this->_displayBytes)) {
- @list($widthBytes, $heightBytes) = explode('*', $this->_displayBytes);
- $display['width_bytes'] = $widthBytes;
- $display['height_bytes'] = $heightBytes;
- }
-
- return new Net_UserAgent_Mobile_Display($display);
- }
-
- // }}}
- // {{{ getHTMLVersion()
-
- /**
- * Gets the HTML version like '3.0'. Returns null if unknown.
- *
- * @return string
- */
- function getHTMLVersion()
- {
- return @$this->_htmlVersions[ $this->getModel() ];
- }
-
- // }}}
- // {{{ getCacheSize()
-
- /**
- * returns cache size as kilobytes unit. returns 5 if unknown.
- *
- * @return integer
- */
- function getCacheSize()
- {
- if ($this->_cacheSize) {
- return $this->_cacheSize;
- }
-
- return 5;
- }
-
- // }}}
- // {{{ getSeries()
-
- /**
- * returns series name like '502i'. returns null if unknown.
- *
- * @return string
- */
- function getSeries()
- {
- if (preg_match('/(\d{4})/', $this->_rawModel)) {
- return 'FOMA';
- }
-
- if (preg_match('/(\d{3}i)/', $this->_rawModel, $matches)) {
- return $matches[1];
- }
-
- if ($this->_rawModel == 'P651ps') {
- return '651';
- }
- }
-
- // }}}
- // {{{ getVendor()
-
- /**
- * returns vender code like 'SO' for Sony. returns null if unknown.
- *
- * @return string
- */
- function getVendor()
- {
- if (preg_match('/([A-Z]+)\d/', $this->_rawModel, $matches)) {
- return $matches[1];
- }
- }
-
- // }}}
- // {{{ getStatus()
-
- /**
- * returns status like "TB", "TC", "TD" or "TJ", which means:
- *
- * TB | Browsers
- * TC | Browsers with image off (only Available in HTML 5.0)
- * TD | Fetching JAR
- * TJ | i-Appli
- *
- * @return string
- */
- function getStatus()
- {
- return $this->_status;
- }
-
- // }}}
- // {{{ getBandwidth()
-
- /**
- * returns bandwidth like 32 as killobytes unit. Only vailable in eggy,
- * returns null otherwise.
- *
- * @return integer
- */
- function getBandwidth()
- {
- return $this->_bandwidth;
- }
-
- // }}}
- // {{{ getSerialNumber()
-
- /**
- * returns hardware unique serial number (15 digit in FOMA, 11 digit
- * otherwise alphanumeric). Only available with form utn attribute.
- * returns null otherwise.
- *
- * @return string
- */
- function getSerialNumber()
- {
- return $this->_serialNumber;
- }
-
- // }}}
- // {{{ isFOMA()
-
- /**
- * retuns whether it's FOMA or not
- *
- * @return boolean
- */
- function isFOMA()
- {
- return $this->_isFOMA;
- }
-
- // }}}
- // {{{ getComment()
-
- /**
- * returns comment on user agent string like 'Google Proxy'. returns null
- * otherwise.
- *
- * @return string
- */
- function getComment()
- {
- return $this->_comment;
- }
-
- // }}}
- // {{{ getCardID()
-
- /**
- * returns FOMA Card ID (20 digit alphanumeric). Only available in FOMA
- * with |