mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-09-02 19:28:55 +00:00
Merge branch 'dev-composer' into dev-regexless
This commit is contained in:
Executable
+36
@@ -0,0 +1,36 @@
|
||||
* binary
|
||||
*.eot binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.jpg binary
|
||||
*.otf binary
|
||||
*.png binary
|
||||
*.swf binary
|
||||
*.ttf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
|
||||
*.ai eol=crlf -whitespace
|
||||
*.bat -binary text eol=crlf
|
||||
*.css -binary text eol=lf -whitespace
|
||||
*.html -binary text eol=lf
|
||||
*.js -binary text -whitespace
|
||||
*.json -binary text eol=lf
|
||||
*.less -binary text eol=lf
|
||||
*.md -binary text eol=lf conflict-marker-size=100
|
||||
*.php -binary text eol=lf
|
||||
*.sh -binary text eol=lf
|
||||
*.sql -binary text eol=lf
|
||||
*.svg -binary text eol=lf
|
||||
*.tpl -binary text eol=lf -whitespace
|
||||
*.tsv -binary text eol=lf -whitespace
|
||||
*.txt -binary text eol=lf conflict-marker-size=100
|
||||
*.vcproj -binary text eol=crlf
|
||||
*.xml -binary text eol=lf
|
||||
|
||||
libs/* -whitespace
|
||||
|
||||
Changelog -binary text eol=lf
|
||||
.gitignore -binary text
|
||||
.gitattributes -binary text
|
||||
composer.lock -binary text
|
||||
+27
-3
@@ -1,3 +1,27 @@
|
||||
fix.sh
|
||||
misc/update/nix/tmux/powerline/powerline/config/defaults.sh
|
||||
.idea
|
||||
.DS_Store
|
||||
config.php
|
||||
error_log
|
||||
failed-login.log
|
||||
php_errors.log
|
||||
php-errors.log
|
||||
test.php
|
||||
|
||||
# Editor temp files
|
||||
*#
|
||||
*~
|
||||
*.orig
|
||||
|
||||
/.idea/
|
||||
/newznab/config/config.php
|
||||
/newznab/config/settings.php
|
||||
/newznab/config/ircscraper_settings.php
|
||||
/newznab/config/ircscraper.php
|
||||
/newznab/config/opensssl.php
|
||||
|
||||
/nbproject/
|
||||
/nbproject/private/
|
||||
/resources/covers/*
|
||||
/resources/nzb/*
|
||||
/resources/tmp/*
|
||||
/templates_c/*
|
||||
/vendor
|
||||
|
||||
+2
-6
@@ -73,9 +73,5 @@ coding_style:
|
||||
|
||||
filter:
|
||||
excluded_paths:
|
||||
- libs/smarty/*
|
||||
- libs/Net_NNTP/*
|
||||
- libs/rarinfo/*
|
||||
- libs/PHPMailer/*
|
||||
- libs/getid3/*
|
||||
- libs/forkdaemon-php/*
|
||||
- libs/PEAR/Net_NNTP/*
|
||||
- libs/zeebinz/rarinfo/*
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
2016-03-18 DariusIII
|
||||
* Upd: Add post-merge hook to handle composer updates, update README.md
|
||||
* Upd: Add back TV processing to NFO processing.
|
||||
* Chg: Add match_prefiles to tmux.
|
||||
2016-03-17 DariusIII
|
||||
* Chg: Replace 2 occurences of array_push with $array[] in NZB.php to reduce overhead.
|
||||
* Upd: Change semantics for failed download handling in themes.
|
||||
2016-03-16 DariusIII
|
||||
* Upd: Update composer.lock with latest TVMaze update
|
||||
* Fix: Fix missing use statement for Category class in www/pages/anime
|
||||
2016-03-15 DariusIII
|
||||
* Fix: Fix max headers iteration for binaries update
|
||||
* Chg: Change function used to check for empty NZBGet url field in profile edit
|
||||
2016-03-14 DariusIII
|
||||
* Upd: Update composer.lock with new TVMaze update
|
||||
2016-03-12 DariusIII
|
||||
* Upd: Fix TVMaze processing
|
||||
2016-03-10 DariusIII
|
||||
* Fix: Fix object to string conversion in processing/tv/TVDB.php
|
||||
* Upd: Update composer.json of the project.
|
||||
* Chg: Move smarty template and cache files to resources folder
|
||||
2016-03-09 DariusIII
|
||||
* Fix: Fix typo in serverroot and fix getID3 error in Nfo class.
|
||||
2016-03-08 DariusIII
|
||||
* Upd: Many changes related to composer
|
||||
* Upd: Update smarty handling in composer.json
|
||||
* Fix: Remove require for GiantBomb as it should be handled by composer
|
||||
* Fix: Fix errors related to changes to libraries.
|
||||
* Fix: Remove require for getid3 from Nfo class, it is handled by composer autoload now
|
||||
* Upd: Update Readme.md with composer info.
|
||||
* Add: Add project composer.lock file to git, remove Git folder from libs.
|
||||
* Chg: Remove dependencies handled by composer
|
||||
* Chg: Remove libraries handled by composer, move others to their respective folders
|
||||
* Add: Add composer.json
|
||||
* Upd: Update .gitignore
|
||||
2016-03-07 DariusIII
|
||||
* Fix: Fix another instantiation in Groups
|
||||
* Fix: Fix instantiation of Binaries Class in Groups.php
|
||||
|
||||
@@ -10,8 +10,8 @@ I started adapting some of more interesting scripts from nZEDb, but they require
|
||||
|
||||
CD to the root of your newznab install, ie. cd /var/www/newznab
|
||||
Next steps are very important:
|
||||
|
||||
git init
|
||||
|
||||
git init
|
||||
git remote add origin https://github.com/DariusIII/newznab-tmux.git
|
||||
git fetch
|
||||
git reset --hard origin/your_wanted_branch, ie. git reset --hard origin/master
|
||||
@@ -20,18 +20,32 @@ I started adapting some of more interesting scripts from nZEDb, but they require
|
||||
Schema for first database update is located in resources/db/schema/ folder. Import it to your database.
|
||||
There is another file in that folder nntmux_fi_schema.sql, use that if you don't have any releases and users on your site, AKA, completely fresh install of newznab+.
|
||||
BE WARNED: If you import this schema it WILL NUKE YOUR DATABASE.
|
||||
If you are updating from latest newznab svn (aka tvmaze version), you need to rename back tvinfoID columns into rageid
|
||||
If you are updating from latest newznab svn (aka tvmaze version), you need to rename back tvinfoID columns into rageid
|
||||
(located in releases and userseries tables, maybe some more), before you import the schema.sql.
|
||||
After that you update your database by running update_db.php from cli folder (ie. php cli/update_db.php true)
|
||||
|
||||
You need to chmod to 777 following folders now:
|
||||
resources/*
|
||||
libs/smarty/templates_c
|
||||
nzbfiles/
|
||||
nzbfiles/
|
||||
|
||||
You need to add an alias to your apache/nginx conf of your indexer:
|
||||
Alias /covers /path/to/newznab/resources/covers
|
||||
|
||||
# Composer
|
||||
|
||||
Note: Newznab-tmux uses composer to install required libraries. To install composer
|
||||
follow instructons located at: https://getcomposer.org/download/
|
||||
When you have downloaded and installed composer,
|
||||
run "php composer.phar install" to install dependencies and create required
|
||||
folders and autoloader for them.
|
||||
Next: sudo cp composer.phar /usr/local/bin/composer
|
||||
sudo chmod a+x /usr/local/bin/composer
|
||||
|
||||
# Git hooks
|
||||
|
||||
Note: run addHooks.sh from build/git-hooks folder to add required git hooks.
|
||||
|
||||
# yEnc:
|
||||
|
||||
Note: You have 3 choices,
|
||||
|
||||
+5
-4
@@ -18,14 +18,14 @@
|
||||
* @author niel
|
||||
* @copyright 2014 nZEDb
|
||||
*/
|
||||
|
||||
/*
|
||||
spl_autoload_register(
|
||||
function ($class) {
|
||||
// Only continue if the class is in our namespace.
|
||||
if (strpos($class, 'newznab\\') === 0) {
|
||||
if (strpos($class, 'nzedb\\') === 0) {
|
||||
// Replace namespace separators with directory separators in the class name, append
|
||||
// with .php
|
||||
$file = NN_ROOT . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
|
||||
$file = nZEDb_ROOT . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
|
||||
|
||||
// if the file exists, require it
|
||||
if (file_exists($file)) {
|
||||
@@ -34,5 +34,6 @@ spl_autoload_register(
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
*/
|
||||
require_once 'vendor/autoload.php'
|
||||
?>
|
||||
|
||||
@@ -4,6 +4,7 @@ NNTMUX=`pwd`
|
||||
HOOKS=/build/git-hooks
|
||||
GIT=/.git/hooks
|
||||
PC=/pre-commit
|
||||
PM=/post-merge
|
||||
|
||||
NNTMUX=${NNTMUX%${HOOKS}}
|
||||
|
||||
@@ -13,5 +14,11 @@ then
|
||||
rm "${NNTMUX}${GIT}${PC}"
|
||||
echo .
|
||||
fi
|
||||
if [ -x "${NNTMUX}${GIT}${PM}" ]
|
||||
then
|
||||
rm "${NNTMUX}${GIT}${PM}"
|
||||
echo .
|
||||
fi
|
||||
|
||||
ln -s ${NNTMUX}${HOOKS}${PC} ${NNTMUX}${GIT}${PC}
|
||||
ln -s ${NNTMUX}${HOOKS}${PM} ${NNTMUX}${GIT}${PM}
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
# MIT © Sindre Sorhus - sindresorhus.com
|
||||
# forked by Gianluca Guarini
|
||||
# phponly by Ivo Bathke ;)
|
||||
|
||||
changed_files="$(git diff-tree -r --name-only --no-commit-id ORIG_HEAD HEAD)"
|
||||
|
||||
check_run() {
|
||||
echo "$changed_files" | grep --quiet "$1" && eval "$2"
|
||||
}
|
||||
|
||||
# `composer install` if the `composer.lock` file gets changed
|
||||
# to update all the php dependencies
|
||||
check_run composer.lock "composer install --no-dev"
|
||||
@@ -19,7 +19,6 @@
|
||||
* @copyright 2014 nZEDb
|
||||
*/
|
||||
require_once realpath(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'indexer.php');
|
||||
require_once NN_LIBS . DIRECTORY_SEPARATOR . 'smarty' . DIRECTORY_SEPARATOR . 'Smarty.class.php';
|
||||
|
||||
use newznab\db\DbUpdate;
|
||||
use newznab\utility\Utility;
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"authors": [
|
||||
{
|
||||
"name": "DariusIII",
|
||||
"email": "dkrisan@gmail.com",
|
||||
"role": "developer"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/kbjr/Git.php"
|
||||
}
|
||||
],
|
||||
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"newznab\\": "newznab/"
|
||||
},
|
||||
|
||||
"classmap": [
|
||||
"www/pages/",
|
||||
"libs/pixelead0/Tmdb/",
|
||||
"libs/PEAR/Net_NNTP/NNTP/",
|
||||
"libs/zeebinz/rarinfo/",
|
||||
"libs/"
|
||||
]
|
||||
},
|
||||
|
||||
"description": "A Usenet Indexer",
|
||||
|
||||
"license": "GPL-3.0",
|
||||
|
||||
"name": "DariusIII/newznab-tmux",
|
||||
|
||||
"require": {
|
||||
"php": ">=5.6.0",
|
||||
"barracudanetworks/forkdaemon-php": "~1.0",
|
||||
"giantbomb/giantbomb": "@dev",
|
||||
"google/recaptcha": "~1.1",
|
||||
"james-heinrich/getid3": "1.9.*",
|
||||
"joshpinkney/tv-maze-php-api": "dev-master",
|
||||
"kbjr/Git.php": "@dev",
|
||||
"moinax/tvdb": "~1.0",
|
||||
"phpmailer/phpmailer": "~5.2",
|
||||
"exeu/apai-io": "~1.0",
|
||||
"smarty/smarty": "~3.1"
|
||||
},
|
||||
|
||||
"require-dev": {},
|
||||
"type": "project"
|
||||
}
|
||||
Generated
+465
@@ -0,0 +1,465 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "2b602e7d5bb44f9e55ee675cb940ca9c",
|
||||
"content-hash": "7c06c9b0053f5f9790d7d1d99edaeef8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "barracudanetworks/forkdaemon-php",
|
||||
"version": "v1.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/barracudanetworks/forkdaemon-php.git",
|
||||
"reference": "9f9402909a4bd1ac98e5aacb6f15f19056f591f6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/barracudanetworks/forkdaemon-php/zipball/9f9402909a4bd1ac98e5aacb6f15f19056f591f6",
|
||||
"reference": "9f9402909a4bd1ac98e5aacb6f15f19056f591f6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"fork_daemon.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "A library to make setup and management of forking daemons in PHP easy.",
|
||||
"homepage": "https://github.com/barracudanetworks/forkdaemon-php",
|
||||
"keywords": [
|
||||
"daemons",
|
||||
"forking",
|
||||
"php"
|
||||
],
|
||||
"time": "2016-01-12 19:40:56"
|
||||
},
|
||||
{
|
||||
"name": "exeu/apai-io",
|
||||
"version": "1.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Exeu/apai-io.git",
|
||||
"reference": "d8a0009a262d77f96eeb6deb930b3ab0562d1ac3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Exeu/apai-io/zipball/d8a0009a262d77f96eeb6deb930b3ab0562d1ac3",
|
||||
"reference": "d8a0009a262d77f96eeb6deb930b3ab0562d1ac3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mayflower/php-codebrowser": "1.*",
|
||||
"pdepend/pdepend": "2.*",
|
||||
"phploc/phploc": "2.*",
|
||||
"phpmd/phpmd": "2.*",
|
||||
"phpunit/phpunit": "4.5.*",
|
||||
"sebastian/phpcpd": "2.*",
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"ApaiIO": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jan Eichhorn",
|
||||
"email": "exeu65@googlemail.com",
|
||||
"role": "Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Dejan Spasic",
|
||||
"email": "dejan.spasic@bitweise.biz",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Amazon Product Advertising PHP Library",
|
||||
"homepage": "https://github.com/Exeu/apai-io",
|
||||
"keywords": [
|
||||
"ECS",
|
||||
"Product Advertising",
|
||||
"amazon",
|
||||
"products",
|
||||
"rest",
|
||||
"soap"
|
||||
],
|
||||
"time": "2016-03-08 07:37:18"
|
||||
},
|
||||
{
|
||||
"name": "giantbomb/giantbomb",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/amalfra/GiantBomb.git",
|
||||
"reference": "6e5c37fdaff69bc2af089acd39fbc00b1d4f5985"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/amalfra/GiantBomb/zipball/6e5c37fdaff69bc2af089acd39fbc00b1d4f5985",
|
||||
"reference": "6e5c37fdaff69bc2af089acd39fbc00b1d4f5985",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"GiantBomb": "GiantBomb/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Amal Francis",
|
||||
"email": "amalfra@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "koroban",
|
||||
"email": "dev+koroban@novutec.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP wrapper for GiantBomb API",
|
||||
"homepage": "http://www.giantbomb.com/api/",
|
||||
"keywords": [
|
||||
"api",
|
||||
"giantbomb",
|
||||
"php",
|
||||
"wrapper"
|
||||
],
|
||||
"time": "2014-05-10 11:57:09"
|
||||
},
|
||||
{
|
||||
"name": "google/recaptcha",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/google/recaptcha.git",
|
||||
"reference": "2b7e00566afca82a38a1d3adb8e42c118006296e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/google/recaptcha/zipball/2b7e00566afca82a38a1d3adb8e42c118006296e",
|
||||
"reference": "2b7e00566afca82a38a1d3adb8e42c118006296e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.5.*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ReCaptcha\\": "src/ReCaptcha"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Client library for reCAPTCHA, a free service that protect websites from spam and abuse.",
|
||||
"homepage": "http://www.google.com/recaptcha/",
|
||||
"keywords": [
|
||||
"Abuse",
|
||||
"captcha",
|
||||
"recaptcha",
|
||||
"spam"
|
||||
],
|
||||
"time": "2015-09-02 17:23:59"
|
||||
},
|
||||
{
|
||||
"name": "james-heinrich/getid3",
|
||||
"version": "v1.9.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/JamesHeinrich/getID3.git",
|
||||
"reference": "41c05612d532d30f07680cad3a4a6efbec7fc7f5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/41c05612d532d30f07680cad3a4a6efbec7fc7f5",
|
||||
"reference": "41c05612d532d30f07680cad3a4a6efbec7fc7f5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"getid3/getid3.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL"
|
||||
],
|
||||
"description": "PHP script that extracts useful information from popular multimedia file formats",
|
||||
"homepage": "http://www.getid3.org/",
|
||||
"keywords": [
|
||||
"codecs",
|
||||
"php",
|
||||
"tags"
|
||||
],
|
||||
"time": "2016-03-02 13:13:30"
|
||||
},
|
||||
{
|
||||
"name": "joshpinkney/tv-maze-php-api",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/JPinkney/TVMaze-PHP-API-Wrapper.git",
|
||||
"reference": "bf6b5bcf44d607bd2406b0638e86e6b9f1b909fe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/JPinkney/TVMaze-PHP-API-Wrapper/zipball/bf6b5bcf44d607bd2406b0638e86e6b9f1b909fe",
|
||||
"reference": "bf6b5bcf44d607bd2406b0638e86e6b9f1b909fe",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"JPinkney\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Josh Pinkney",
|
||||
"email": "Joshpinkney@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "TVMaze-API-Wrapper",
|
||||
"time": "2016-03-16 14:59:03"
|
||||
},
|
||||
{
|
||||
"name": "kbjr/Git.php",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kbjr/Git.php.git",
|
||||
"reference": "0d1a99625d45bccda222389bbe6135482b407782"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kbjr/Git.php/zipball/0d1a99625d45bccda222389bbe6135482b407782",
|
||||
"reference": "0d1a99625d45bccda222389bbe6135482b407782",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"Git.php"
|
||||
]
|
||||
},
|
||||
"support": {
|
||||
"source": "https://github.com/kbjr/Git.php/tree/master",
|
||||
"issues": "https://github.com/kbjr/Git.php/issues"
|
||||
},
|
||||
"time": "2015-03-31 14:10:29"
|
||||
},
|
||||
{
|
||||
"name": "moinax/tvdb",
|
||||
"version": "v1.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Moinax/TvDb.git",
|
||||
"reference": "68204c72efe99945cd49fe99ac23c8f9b068f2d6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Moinax/TvDb/zipball/68204c72efe99945cd49fe99ac23c8f9b068f2d6",
|
||||
"reference": "68204c72efe99945cd49fe99ac23c8f9b068f2d6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Moinax\\TvDb": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Moinax",
|
||||
"email": "moinax@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "PHPTVDB is a PHP library for accessing TV show information such as episodes, actors, showtimes and descriptions.",
|
||||
"homepage": "http://moinax.github.io/TvDb/",
|
||||
"keywords": [
|
||||
"api"
|
||||
],
|
||||
"time": "2016-03-08 12:37:26"
|
||||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v5.2.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPMailer/PHPMailer.git",
|
||||
"reference": "e774bc9152de85547336e22b8926189e582ece95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/e774bc9152de85547336e22b8926189e582ece95",
|
||||
"reference": "e774bc9152de85547336e22b8926189e582ece95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpdocumentor/phpdocumentor": "*",
|
||||
"phpunit/phpunit": "4.7.*"
|
||||
},
|
||||
"suggest": {
|
||||
"league/oauth2-client": "Needed for XOAUTH2 authentication",
|
||||
"league/oauth2-google": "Needed for Gmail XOAUTH2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"class.phpmailer.php",
|
||||
"class.phpmaileroauth.php",
|
||||
"class.phpmaileroauthgoogle.php",
|
||||
"class.smtp.php",
|
||||
"class.pop3.php",
|
||||
"extras/EasyPeasyICS.php",
|
||||
"extras/ntlm_sasl_client.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jim Jagielski",
|
||||
"email": "jimjag@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Marcus Bointon",
|
||||
"email": "phpmailer@synchromedia.co.uk"
|
||||
},
|
||||
{
|
||||
"name": "Andy Prevost",
|
||||
"email": "codeworxtech@users.sourceforge.net"
|
||||
},
|
||||
{
|
||||
"name": "Brent R. Matzelle"
|
||||
}
|
||||
],
|
||||
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
|
||||
"time": "2015-11-01 10:15:28"
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v3.1.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/smarty-php/smarty.git",
|
||||
"reference": "35480f10e7ce9b0fdaf23d3799d7b79463919b1e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/35480f10e7ce9b0fdaf23d3799d7b79463919b1e",
|
||||
"reference": "35480f10e7ce9b0fdaf23d3799d7b79463919b1e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"libs/Smarty.class.php",
|
||||
"libs/SmartyBC.class.php",
|
||||
"libs/sysplugins/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Monte Ohrt",
|
||||
"email": "monte@ohrt.com"
|
||||
},
|
||||
{
|
||||
"name": "Uwe Tews",
|
||||
"email": "uwe.tews@googlemail.com"
|
||||
},
|
||||
{
|
||||
"name": "Rodney Rehm",
|
||||
"email": "rodney.rehm@medialize.de"
|
||||
}
|
||||
],
|
||||
"description": "Smarty - the compiling PHP template engine",
|
||||
"homepage": "http://www.smarty.net",
|
||||
"keywords": [
|
||||
"templating"
|
||||
],
|
||||
"time": "2015-12-21 01:57:06"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"giantbomb/giantbomb": 20,
|
||||
"joshpinkney/tv-maze-php-api": 20,
|
||||
"kbjr/git.php": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
||||
+2
-1
@@ -20,7 +20,8 @@
|
||||
*/
|
||||
require_once 'constants.php';
|
||||
require_once 'autoloader.php';
|
||||
require_once 'libs/autoloader.php';
|
||||
//require_once 'libs/autoloader.php';
|
||||
//require_once 'vendor/autoload.php';
|
||||
|
||||
use newznab\config\Configure;
|
||||
use newznab\utility\Utility;
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO;
|
||||
|
||||
use libs\ApaiIO\Configuration\ConfigurationInterface;
|
||||
use libs\ApaiIO\Operations\OperationInterface;
|
||||
use libs\ApaiIO\Request\RequestFactory;
|
||||
use libs\ApaiIO\ResponseTransformer\ResponseTransformerFactory;
|
||||
|
||||
/**
|
||||
* ApaiIO Core
|
||||
* Bundles all components
|
||||
*
|
||||
* http://www.amazon.com
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* @see https://github.com/Exeu/apai-io/wiki Wiki
|
||||
* @see https://github.com/Exeu/apai-io Source
|
||||
*/
|
||||
class ApaiIO
|
||||
{
|
||||
const VERSION = "2.0.0-DEV";
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*
|
||||
* @var ConfigurationInterface
|
||||
*/
|
||||
protected $configuration;
|
||||
|
||||
/**
|
||||
* @param ConfigurationInterface $configuration
|
||||
*/
|
||||
public function __construct(ConfigurationInterface $configuration = null)
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given operation
|
||||
*
|
||||
* @param OperationInterface $operation The operationobject
|
||||
* @param ConfigurationInterface $configuration The configurationobject
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function runOperation(OperationInterface $operation, ConfigurationInterface $configuration = null)
|
||||
{
|
||||
$configuration = is_null($configuration) ? $this->configuration : $configuration;
|
||||
|
||||
if (true === is_null($configuration)) {
|
||||
throw new \Exception('No configuration passed.');
|
||||
}
|
||||
|
||||
$requestObject = RequestFactory::createRequest($configuration);
|
||||
|
||||
$response = $requestObject->perform($operation);
|
||||
|
||||
return $this->applyResponseTransformer($response, $configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a responsetransformer
|
||||
*
|
||||
* @param mixed $response The response of the request
|
||||
* @param ConfigurationInterface $configuration The configurationobject
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function applyResponseTransformer($response, ConfigurationInterface $configuration)
|
||||
{
|
||||
if (true === is_null($configuration->getResponseTransformer())) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$responseTransformer = ResponseTransformerFactory::createResponseTransformer($configuration);
|
||||
|
||||
return $responseTransformer->transform($response);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Common;
|
||||
|
||||
/**
|
||||
* This trait allows you to add the basic operation functions to your class.
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
trait OperationTrait
|
||||
{
|
||||
protected $parameter = array();
|
||||
|
||||
/**
|
||||
* Sets the responsegroups for the current operation
|
||||
* Which responsegroups are available depends on the Operation you perform
|
||||
*
|
||||
* @param array $responseGroup The responsegroup as an array
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/CHAP_ResponseGroupsList.html
|
||||
*/
|
||||
public function setResponseGroup(array $responseGroup)
|
||||
{
|
||||
$this->parameter['ResponseGroup'] = $responseGroup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all paramerters belonging to the current operation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOperationParameter()
|
||||
{
|
||||
return $this->parameter;
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Configuration;
|
||||
|
||||
interface ConfigurationInterface
|
||||
{
|
||||
/**
|
||||
* Gets the country
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCountry();
|
||||
|
||||
/**
|
||||
* Gets the accesskey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessKey();
|
||||
|
||||
/**
|
||||
* Gets the secretkey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSecretKey();
|
||||
|
||||
/**
|
||||
* Gets the associatetag
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAssociateTag();
|
||||
|
||||
/**
|
||||
* Gets the requestclass
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequest();
|
||||
|
||||
/**
|
||||
* Gets the responsetransformerclass
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseTransformer();
|
||||
|
||||
/**
|
||||
* Gets the request factory callback if it is set
|
||||
* This callback can be used to manipulate the request before its returned.
|
||||
*
|
||||
* @return \Closure|array|string
|
||||
*/
|
||||
public function getRequestFactory();
|
||||
|
||||
/**
|
||||
* Gets the responsetransformer factory callback if it is set
|
||||
* This callback can be used to manipulate the request before its returned.
|
||||
*
|
||||
* @return \Closure|array|string
|
||||
*/
|
||||
public function getResponseTransformerFactory();
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Configuration;
|
||||
|
||||
/**
|
||||
* Countryvalidation and countrylistings according to the amazonapi
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
final class Country
|
||||
{
|
||||
/**
|
||||
* Possible countries
|
||||
* Important for the requestendpoints
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $countryList = array('de', 'com', 'co.uk', 'ca', 'fr', 'co.jp', 'it', 'cn', 'es', 'in', 'com.br', 'com.mx', 'com.au');
|
||||
|
||||
/**
|
||||
* Gets all possible countries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getCountries()
|
||||
{
|
||||
return self::$countryList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given value is a valid country
|
||||
*
|
||||
* @param string $country
|
||||
* @param string $exception false = throw no exception true = throw an exception
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isValidCountry($country, $exception = true)
|
||||
{
|
||||
$isValid = in_array(strtolower($country), self::$countryList) ? true : false;
|
||||
|
||||
if (true === $exception && false === $isValid) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
"Invalid Country-Code: %s! Possible Country-Codes: %s",
|
||||
$country,
|
||||
implode(', ', self::$countryList)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $isValid;
|
||||
}
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Configuration;
|
||||
|
||||
use libs\ApaiIO\Configuration\Country;
|
||||
|
||||
/**
|
||||
* A generic configurationclass
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class GenericConfiguration implements ConfigurationInterface
|
||||
{
|
||||
/**
|
||||
* The country
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $country;
|
||||
|
||||
/**
|
||||
* The accesskey
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $accessKey;
|
||||
|
||||
/**
|
||||
* The string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secretKey;
|
||||
|
||||
/**
|
||||
* The associate Tag
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $associateTag;
|
||||
|
||||
/**
|
||||
* The requestclass
|
||||
* By default its set to the provided restful request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $request = "\\libs\\ApaiIO\\Request\\Rest\\Request";
|
||||
|
||||
/**
|
||||
* A callback which is called before returning the request by the factory
|
||||
*
|
||||
* @var \Closure|array|string
|
||||
*/
|
||||
protected $requestFactory = null;
|
||||
|
||||
/**
|
||||
* The responsetransformerclass
|
||||
* By default its set to null which means that no transformer will be applied
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $responseTransformer = null;
|
||||
|
||||
/**
|
||||
* A callback which is called before returning the responsetransformer by the factory
|
||||
*
|
||||
* @var \Closure|array|string
|
||||
*/
|
||||
protected $responseTransformerFactory = null;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCountry()
|
||||
{
|
||||
return $this->country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an validates the country
|
||||
*
|
||||
* @param string $country
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setCountry($country)
|
||||
{
|
||||
Country::isValidCountry($country);
|
||||
|
||||
$this->country = strtolower($country);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAccessKey()
|
||||
{
|
||||
return $this->accessKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the accesskey
|
||||
*
|
||||
* @param string $accessKey
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setAccessKey($accessKey)
|
||||
{
|
||||
$this->accessKey = $accessKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSecretKey()
|
||||
{
|
||||
return $this->secretKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the secretkey
|
||||
*
|
||||
* @param string $secretKey
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setSecretKey($secretKey)
|
||||
{
|
||||
$this->secretKey = $secretKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAssociateTag()
|
||||
{
|
||||
return $this->associateTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the associatetag
|
||||
*
|
||||
* @param string $associateTag
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setAssociateTag($associateTag)
|
||||
{
|
||||
$this->associateTag = $associateTag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the requestclass
|
||||
*
|
||||
* @param string $request
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setRequest($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getResponseTransformer()
|
||||
{
|
||||
return $this->responseTransformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the responsetransformerclass
|
||||
*
|
||||
* @param string $responseTransformer
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setResponseTransformer($responseTransformer)
|
||||
{
|
||||
$this->responseTransformer = $responseTransformer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRequestFactory()
|
||||
{
|
||||
return $this->requestFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request factory callback
|
||||
*
|
||||
* @param \Closure|array|string $callback
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setRequestFactory($callback)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new \InvalidArgumentException("Given argument is not callable");
|
||||
}
|
||||
|
||||
$this->requestFactory = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getResponseTransformerFactory()
|
||||
{
|
||||
return $this->responseTransformerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the responsetransformer factory callback
|
||||
*
|
||||
* @param \Closure|array|string $callback
|
||||
*
|
||||
* @return \libs\ApaiIO\Configuration\GenericConfiguration
|
||||
*/
|
||||
public function setResponseTransformerFactory($callback)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new \InvalidArgumentException("Given argument is not callable");
|
||||
}
|
||||
|
||||
$this->responseTransformerFactory = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A base implementation of the OperationInterface
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
abstract class AbstractOperation implements OperationInterface
|
||||
{
|
||||
protected $parameter = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setResponseGroup(array $responseGroup)
|
||||
{
|
||||
$this->parameter['ResponseGroup'] = $responseGroup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOperationParameter()
|
||||
{
|
||||
return $this->parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic setter and getter functions
|
||||
*
|
||||
* @param string $methodName Methodname
|
||||
* @param string $parameter Parameters
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\AbstractOperation
|
||||
*/
|
||||
public function __call($methodName, $parameter)
|
||||
{
|
||||
if (substr($methodName, 0, 3) == 'set') {
|
||||
$this->parameter[substr($methodName, 3)] = array_shift($parameter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (substr($methodName, 0, 3) == 'get') {
|
||||
$keyName = substr($methodName, 3);
|
||||
|
||||
return isset($this->parameter[$keyName]) ? $this->parameter[$keyName] : null;
|
||||
}
|
||||
|
||||
throw new \BadFunctionCallException(sprintf('The function "%s" does not exist!', $methodName));
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A browse node lookup operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/BrowseNodeLookup.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class BrowseNodeLookup extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'BrowseNodeLookup';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nodeid in which should be looked up
|
||||
*
|
||||
* @param string $nodeId
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\BrowseNodeLookup
|
||||
*/
|
||||
public function setNodeId($nodeId)
|
||||
{
|
||||
$this->parameter['BrowseNodeId'] = $nodeId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A cart add operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/CartAdd.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class CartAdd extends CartCreate
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'CartAdd';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cart id
|
||||
*
|
||||
* @param string $cartId
|
||||
*/
|
||||
public function setCartId($cartId)
|
||||
{
|
||||
$this->parameter['CartId'] = $cartId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HMAC
|
||||
*
|
||||
* @param string $HMAC
|
||||
*/
|
||||
public function setHMAC($HMAC)
|
||||
{
|
||||
$this->parameter['HMAC'] = $HMAC;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A cart add operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/CartAdd.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class CartClear extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'CartClear';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cart id
|
||||
*
|
||||
* @param string $cartId
|
||||
*/
|
||||
public function setCartId($cartId)
|
||||
{
|
||||
$this->parameter['CartId'] = $cartId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HMAC
|
||||
*
|
||||
* @param string $HMAC
|
||||
*/
|
||||
public function setHMAC($HMAC)
|
||||
{
|
||||
$this->parameter['HMAC'] = $HMAC;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A cart create operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/CartCreate.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class CartCreate extends AbstractOperation
|
||||
{
|
||||
private $itemCounter = 1;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'CartCreate';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the Cart
|
||||
*
|
||||
* @param string $id The ASIN or OfferListingId Number of the item
|
||||
* @param integer $quantity How much you want to add
|
||||
* @param bool $byAsin If False will use OfferListingId insted of ASIN
|
||||
*/
|
||||
public function addItem($id, $quantity, $byAsin = true)
|
||||
{
|
||||
$itemIdentifier = ($byAsin) ? '.ASIN' : '.OfferListingId';
|
||||
$this->parameter['Item.' . $this->itemCounter . $itemIdentifier] = $id;
|
||||
$this->parameter['Item.' . $this->itemCounter . '.Quantity'] = $quantity;
|
||||
|
||||
$this->itemCounter++;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A item lookup operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/ItemLookup.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class Lookup extends AbstractOperation
|
||||
{
|
||||
const TYPE_ASIN = 'ASIN';
|
||||
const TYPE_SKU = 'SKU';
|
||||
const TYPE_UPC = 'UPC';
|
||||
const TYPE_EAN = 'EAN';
|
||||
const TYPE_ISBN = 'ISBN';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'ItemLookup';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the itemid which should be looked up
|
||||
*
|
||||
* @param string $itemId
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Lookup
|
||||
*/
|
||||
public function setItemId($itemId)
|
||||
{
|
||||
$this->parameter['ItemId'] = $itemId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the idtype either ASIN (Default), SKU, UPC, EAN, and ISBN
|
||||
*
|
||||
* @param string $idType
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Lookup
|
||||
*/
|
||||
public function setIdType($idType)
|
||||
{
|
||||
$idTypes = array(
|
||||
self::TYPE_ASIN,
|
||||
self::TYPE_SKU,
|
||||
self::TYPE_UPC,
|
||||
self::TYPE_EAN,
|
||||
self::TYPE_ISBN
|
||||
);
|
||||
|
||||
if (!in_array($idType, $idTypes)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
"Invalid type '%s' passed. Valid types are: '%s'",
|
||||
$idType,
|
||||
implode(', ', $idTypes)
|
||||
));
|
||||
}
|
||||
|
||||
$this->parameter['IdType'] = $idType;
|
||||
|
||||
if (empty($this->parameter['SearchIndex']) && $idType != self::TYPE_ASIN) {
|
||||
$this->parameter['SearchIndex'] = 'All';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the searchindex which should be used when set IdType other than ASIN
|
||||
*
|
||||
* @param string $searchIndex
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Lookup
|
||||
*/
|
||||
public function setSearchIndex($searchIndex)
|
||||
{
|
||||
$this->parameter['SearchIndex'] = $searchIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the condition of the items to return: New | Used | Collectible | Refurbished | All
|
||||
*
|
||||
* Defaults to New.
|
||||
*
|
||||
* @param string $condition
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Lookup
|
||||
*/
|
||||
public function setCondition($condition)
|
||||
{
|
||||
$this->parameter['Condition'] = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
interface OperationInterface
|
||||
{
|
||||
/**
|
||||
* Gets the name of the operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/CHAP_OperationListAlphabetical.html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Sets the responsegroups for the current operation
|
||||
* Which responsegroups are available depends on the Operation you perform
|
||||
*
|
||||
* @param array $responseGroup The responsegroup as an array
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/CHAP_ResponseGroupsList.html
|
||||
*/
|
||||
public function setResponseGroup(array $responseGroup);
|
||||
|
||||
/**
|
||||
* Returns all paramerters belonging to the current operation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOperationParameter();
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A item search operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/ItemSearch.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class Search extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'ItemSearch';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amazon category
|
||||
*
|
||||
* @param string $category
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setCategory($category)
|
||||
{
|
||||
$this->parameter['SearchIndex'] = $category;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keywords
|
||||
*
|
||||
* @param string $keywords
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setKeywords($keywords)
|
||||
{
|
||||
$this->parameter['Keywords'] = $keywords;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amazon browseNode
|
||||
*
|
||||
* @param string $browseNode
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setBrowseNode($browseNode)
|
||||
{
|
||||
if (false === is_numeric($browseNode) || (int)$browseNode < 0) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'%s is an invalid browseNode value. It has to be numeric and positive',
|
||||
$browseNode
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->parameter['BrowseNode'] = $browseNode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resultpage to a specified value
|
||||
* Allows to browse resultsets which have more than one page
|
||||
*
|
||||
* @param integer $page
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setPage($page)
|
||||
{
|
||||
if (false === is_numeric($page) || $page < 1 || $page > 10) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'%s is an invalid page value. It has to be numeric, positive and between 1 and 10',
|
||||
$page
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->parameter['ItemPage'] = $page;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum price to a specified value for the search
|
||||
* Currency will be given by the site you are querying: EUR for IT, USD for COM
|
||||
* Price should be given as integer. 8.99$ USD becomes 899
|
||||
*
|
||||
* @param integer $price
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setMinimumPrice($price)
|
||||
{
|
||||
$this->validatePrice($price);
|
||||
$this->parameter['MinimumPrice'] = $price;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum price to a specified value for the search
|
||||
* Currency will be given by the site you are querying: EUR for IT, USD for COM
|
||||
* Price should be given as integer. 8.99$ USD becomes 899
|
||||
*
|
||||
* @param integer $price
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setMaximumPrice($price)
|
||||
{
|
||||
$this->validatePrice($price);
|
||||
$this->parameter['MaximumPrice'] = $price;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the condition of the items to return: New | Used | Collectible | Refurbished | All
|
||||
*
|
||||
* Defaults to New.
|
||||
*
|
||||
* @param string $condition
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\Search
|
||||
*/
|
||||
public function setCondition($condition)
|
||||
{
|
||||
$this->parameter['Condition'] = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given price.
|
||||
*
|
||||
* @param integer $price
|
||||
*/
|
||||
protected function validatePrice($price)
|
||||
{
|
||||
if (false === is_numeric($price) || $price < 1) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'%s is an invalid price value. It has to be numeric and >= than 1',
|
||||
$price
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Operations;
|
||||
|
||||
/**
|
||||
* A similarity lookup operation
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/SimilarityLookup.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class SimilarityLookup extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'SimilarityLookup';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the itemid which has to be looked up
|
||||
* Basicly it is an amazon asin
|
||||
*
|
||||
* @param string $itemId
|
||||
*
|
||||
* @return \libs\ApaiIO\Operations\SimilarityLookup
|
||||
*/
|
||||
public function setItemId($itemId)
|
||||
{
|
||||
$this->parameter['ItemId'] = $itemId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Request;
|
||||
|
||||
use libs\ApaiIO\Configuration\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* A requestfactory which creates a new requestobjects depending on the class name you provide
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class RequestFactory
|
||||
{
|
||||
/**
|
||||
* Storage for the requestobjects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $requestObjects = array();
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
* Private clone
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Requestobject
|
||||
*
|
||||
* @param ConfigurationInterface $configuration The configurationobject
|
||||
*
|
||||
* @return \libs\ApaiIO\Request\RequestInterface
|
||||
*/
|
||||
public static function createRequest(ConfigurationInterface $configuration)
|
||||
{
|
||||
$class = $configuration->getRequest();
|
||||
$factoryCallback = $configuration->getRequestFactory();
|
||||
|
||||
if (true === is_object($class) && $class instanceof RequestInterface) {
|
||||
$class->setConfiguration($configuration);
|
||||
|
||||
return self::applyCallback($factoryCallback, $class);
|
||||
}
|
||||
|
||||
if (true === is_string($class) && true === array_key_exists($class, self::$requestObjects)) {
|
||||
$request = self::$requestObjects[$class];
|
||||
$request->setConfiguration($configuration);
|
||||
|
||||
return self::applyCallback($factoryCallback, $request);
|
||||
}
|
||||
|
||||
try {
|
||||
$reflectionClass = new \ReflectionClass($class);
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new \InvalidArgumentException(sprintf("Requestclass not found: %s", $class));
|
||||
}
|
||||
|
||||
if ($reflectionClass->implementsInterface('\\libs\\ApaiIO\\Request\\RequestInterface')) {
|
||||
$request = new $class();
|
||||
$request->setConfiguration($configuration);
|
||||
|
||||
return self::$requestObjects[$class] = self::applyCallback($factoryCallback, $request);
|
||||
}
|
||||
|
||||
throw new \LogicException(sprintf("Requestclass does not implements the RequestInterface: %s", $class));
|
||||
}
|
||||
|
||||
protected static function applyCallback($callback, $request)
|
||||
{
|
||||
if (false === is_null($callback) && is_callable($callback)) {
|
||||
$request = call_user_func($callback, $request);
|
||||
if ($request instanceof RequestInterface) {
|
||||
return $request;
|
||||
}
|
||||
|
||||
throw new \LogicException(
|
||||
sprintf(
|
||||
"Requestclass does not implements the RequestInterface: %s",
|
||||
get_class($request)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Request;
|
||||
|
||||
use libs\ApaiIO\Configuration\ConfigurationInterface;
|
||||
use libs\ApaiIO\Operations\OperationInterface;
|
||||
|
||||
interface RequestInterface
|
||||
{
|
||||
/**
|
||||
* Sets the configurationobject
|
||||
*
|
||||
* @param ConfigurationInterface $configuration
|
||||
*/
|
||||
public function setConfiguration(ConfigurationInterface $configuration);
|
||||
|
||||
/**
|
||||
* Performs the request
|
||||
*
|
||||
* @param OperationInterface $operation
|
||||
*
|
||||
* @return mixed The response of the request
|
||||
*/
|
||||
public function perform(OperationInterface $operation);
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Request\Rest;
|
||||
|
||||
use libs\ApaiIO\ApaiIO;
|
||||
use libs\ApaiIO\Configuration\ConfigurationInterface;
|
||||
use libs\ApaiIO\Operations\OperationInterface;
|
||||
use libs\ApaiIO\Request\RequestInterface;
|
||||
use libs\ApaiIO\Request\Util;
|
||||
|
||||
/**
|
||||
* Basic implementation of the rest request
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/AnatomyOfaRESTRequest.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class Request implements RequestInterface
|
||||
{
|
||||
/**
|
||||
* Connection time out in seconds
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const CONNECTION_TIMEOUT = CURLOPT_CONNECTTIMEOUT;
|
||||
|
||||
/**
|
||||
* Time out in seconds
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const TIMEOUT = CURLOPT_TIMEOUT;
|
||||
|
||||
/**
|
||||
* Enable/Disable location following
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const FOLLOW_LOCATION = CURLOPT_FOLLOWLOCATION;
|
||||
|
||||
/**
|
||||
* Useragent
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const USERAGENT = CURLOPT_USERAGENT;
|
||||
|
||||
/**
|
||||
* curl options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $options = array();
|
||||
|
||||
/**
|
||||
* The requestscheme
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $requestScheme = "http://webservices.amazon.%s/onca/xml?%s";
|
||||
|
||||
/**
|
||||
* @var ConfigurationInterface
|
||||
*/
|
||||
protected $configuration;
|
||||
|
||||
/**
|
||||
* Initialize instance
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
$this->options = array(
|
||||
self::USERAGENT => "ApaiIO [" . ApaiIO::VERSION . "]",
|
||||
self::CONNECTION_TIMEOUT => 10,
|
||||
self::TIMEOUT => 10,
|
||||
self::FOLLOW_LOCATION => 1
|
||||
);
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the curl options
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function setOptions(array $options = array())
|
||||
{
|
||||
foreach ($options as $currentOption => $currentOptionValue) {
|
||||
$this->options[$currentOption] = $currentOptionValue;
|
||||
}
|
||||
$this->options[CURLOPT_RETURNTRANSFER] = 1; // force the return transfer
|
||||
}
|
||||
|
||||
/**
|
||||
* return the current curl options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function perform(OperationInterface $operation)
|
||||
{
|
||||
$ch = curl_init();
|
||||
|
||||
if (false === $ch) {
|
||||
throw new \RuntimeException("Cannot initialize curl resource");
|
||||
}
|
||||
|
||||
$preparedRequestParams = $this->prepareRequestParams($operation);
|
||||
$queryString = $this->buildQueryString($preparedRequestParams);
|
||||
|
||||
$options = $this->options;
|
||||
$options[CURLOPT_URL] = sprintf($this->requestScheme, $this->configuration->getCountry(), $queryString);
|
||||
|
||||
foreach ($options as $currentOption => $currentOptionValue) {
|
||||
if (false === curl_setopt($ch, $currentOption, $currentOptionValue)) {
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
"An error occurred while setting %s with value %s",
|
||||
$currentOption,
|
||||
$currentOptionValue
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$curlError = false;
|
||||
$errorNumber = null;
|
||||
$errorMessage = null;
|
||||
|
||||
$result = curl_exec($ch);
|
||||
|
||||
if (false === $result) {
|
||||
$curlError = true;
|
||||
$errorNumber = curl_errno($ch);
|
||||
$errorMessage = curl_error($ch);
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($curlError) {
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
"An error occurred while sending request. Error number: %d; Error message: %s",
|
||||
$errorNumber,
|
||||
$errorMessage
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the parameters for the request
|
||||
*
|
||||
* @param OperationInterface $operation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareRequestParams(OperationInterface $operation)
|
||||
{
|
||||
$baseRequestParams = array(
|
||||
'Service' => 'AWSECommerceService',
|
||||
'AWSAccessKeyId' => $this->configuration->getAccessKey(),
|
||||
'AssociateTag' => $this->configuration->getAssociateTag(),
|
||||
'Operation' => $operation->getName(),
|
||||
'Version' => '2011-08-01',
|
||||
'Timestamp' => Util::getTimeStamp()
|
||||
);
|
||||
|
||||
$operationParams = $operation->getOperationParameter();
|
||||
|
||||
foreach ($operationParams as $key => $value) {
|
||||
if (true === is_array($value)) {
|
||||
$operationParams[$key] = implode(',', $value);
|
||||
}
|
||||
}
|
||||
|
||||
$fullParameterList = array_merge($baseRequestParams, $operationParams);
|
||||
ksort($fullParameterList);
|
||||
|
||||
return $fullParameterList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the final querystring including the signature
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildQueryString(array $params)
|
||||
{
|
||||
$parameterList = array();
|
||||
foreach ($params as $key => $value) {
|
||||
$parameterList[] = sprintf('%s=%s', $key, rawurlencode($value));
|
||||
}
|
||||
|
||||
$parameterList[] = 'Signature=' . rawurlencode($this->buildSignature($parameterList));
|
||||
|
||||
return implode("&", $parameterList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the signature for the request
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildSignature(array $params)
|
||||
{
|
||||
$template = "GET\nwebservices.amazon.%s\n/onca/xml\n%s";
|
||||
|
||||
return Util::buildSignature(
|
||||
sprintf(
|
||||
$template,
|
||||
$this->configuration->getCountry(),
|
||||
implode('&', $params)
|
||||
),
|
||||
$this->configuration->getSecretKey()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Request\Soap;
|
||||
|
||||
use libs\ApaiIO\Configuration\ConfigurationInterface;
|
||||
use libs\ApaiIO\Operations\OperationInterface;
|
||||
use libs\ApaiIO\Request\RequestInterface;
|
||||
use libs\ApaiIO\Request\Util;
|
||||
|
||||
/**
|
||||
* Basic implementation of the soap request
|
||||
*
|
||||
* @see http://docs.aws.amazon.com/AWSECommerceService/2011-08-01/DG/MakingSOAPRequests.html
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class Request implements RequestInterface
|
||||
{
|
||||
/**
|
||||
* The WSDL File
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $webserviceWsdl = 'http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl';
|
||||
|
||||
/**
|
||||
* The SOAP Endpoint
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $webserviceEndpoint = 'https://webservices.amazon.%%COUNTRY%%/onca/soap?Service=AWSECommerceService';
|
||||
|
||||
/**
|
||||
* @var ConfigurationInterface
|
||||
*/
|
||||
protected $configuration;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function perform(OperationInterface $operation)
|
||||
{
|
||||
$requestParams = $this->buildRequestParams($operation);
|
||||
|
||||
$result = $this->performSoapRequest($operation, $requestParams);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides some necessary soap headers
|
||||
*
|
||||
* @param OperationInterface $operation
|
||||
*
|
||||
* @return array Each element is a concrete SoapHeader object
|
||||
*/
|
||||
protected function buildSoapHeader(OperationInterface $operation)
|
||||
{
|
||||
$timeStamp = Util::getTimeStamp();
|
||||
$signature = $this->buildSignature($operation->getName() . $timeStamp);
|
||||
|
||||
return array(
|
||||
new \SoapHeader(
|
||||
'http://security.amazonaws.com/doc/2007-01-01/',
|
||||
'AWSAccessKeyId',
|
||||
$this->configuration->getAccessKey()
|
||||
),
|
||||
new \SoapHeader(
|
||||
'http://security.amazonaws.com/doc/2007-01-01/',
|
||||
'Timestamp',
|
||||
$timeStamp
|
||||
),
|
||||
new \SoapHeader(
|
||||
'http://security.amazonaws.com/doc/2007-01-01/',
|
||||
'Signature',
|
||||
$signature
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the request parameters depending on the operation
|
||||
*
|
||||
* @param OperationInterface $operation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function buildRequestParams(OperationInterface $operation)
|
||||
{
|
||||
$associateTag = array('AssociateTag' => $this->configuration->getAssociateTag());
|
||||
|
||||
return array_merge(
|
||||
$associateTag,
|
||||
array(
|
||||
'AWSAccessKeyId' => $this->configuration->getAccessKey(),
|
||||
'Request' => array_merge(
|
||||
array(
|
||||
'Operation' => $operation->getName()
|
||||
),
|
||||
$operation->getOperationParameter()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the soaprequest
|
||||
*
|
||||
* @param OperationInterface $operation The operation
|
||||
* @param array $params Requestparameters 'ParameterName' => 'ParameterValue'
|
||||
*
|
||||
* @return array The response as an array with stdClass objects
|
||||
*/
|
||||
protected function performSoapRequest(OperationInterface $operation, $params)
|
||||
{
|
||||
$soapClient = new \SoapClient(
|
||||
$this->webserviceWsdl,
|
||||
array('exceptions' => 1)
|
||||
);
|
||||
|
||||
$soapClient->__setLocation(
|
||||
str_replace(
|
||||
'%%COUNTRY%%',
|
||||
$this->configuration->getCountry(),
|
||||
$this->webserviceEndpoint
|
||||
)
|
||||
);
|
||||
$soapClient->__setSoapHeaders($this->buildSoapHeader($operation));
|
||||
|
||||
return $soapClient->__soapCall($operation->getName(), array($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the signature for the request
|
||||
*
|
||||
* @param string $request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildSignature($request)
|
||||
{
|
||||
return Util::buildSignature($request, $this->configuration->getSecretKey());
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\Request;
|
||||
|
||||
/**
|
||||
* A collection of misc functions helping to build the request
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* Provides the current timestamp according to the requirements of amazon
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTimeStamp()
|
||||
{
|
||||
return gmdate("Y-m-d\TH:i:s\Z");
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the signature
|
||||
*
|
||||
* @param string $stringToSign The string to be signed
|
||||
* @param string $secretKey The paapi secret key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function buildSignature($stringToSign, $secretKey)
|
||||
{
|
||||
return base64_encode(hash_hmac("sha256", $stringToSign, $secretKey, true));
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\ResponseTransformer;
|
||||
|
||||
/**
|
||||
* A responsetransformer transforming an object to an array
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class ObjectToArray implements ResponseTransformerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($response)
|
||||
{
|
||||
return $this->buildArray($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the responseobject to an array
|
||||
*
|
||||
* @param object $object
|
||||
*
|
||||
* @return array An arrayrepresentation of the given object
|
||||
*/
|
||||
protected function buildArray($object)
|
||||
{
|
||||
$out = array();
|
||||
foreach ($object as $key => $value) {
|
||||
switch (true) {
|
||||
case is_object($value):
|
||||
case is_array($value):
|
||||
$out[$key] = $this->buildArray($value);
|
||||
break;
|
||||
default:
|
||||
$out[$key] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\ResponseTransformer;
|
||||
|
||||
use libs\ApaiIO\Configuration\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* A responsetransformerfactory which creates a new responsetransformerobjects depending on the class name you provide
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class ResponseTransformerFactory
|
||||
{
|
||||
/**
|
||||
* Storage for the responsetransformerobjects
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $responseTransformerObjects = array();
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Private clone
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __clone()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ResponseTransformer-object
|
||||
*
|
||||
* @param ConfigurationInterface $configuration
|
||||
*
|
||||
* @return \libs\ApaiIO\ResponseTransformer\ResponseTransformerInterface
|
||||
*/
|
||||
public static function createResponseTransformer(ConfigurationInterface $configuration)
|
||||
{
|
||||
$class = $configuration->getResponseTransformer();
|
||||
$factoryCallback = $configuration->getResponseTransformerFactory();
|
||||
|
||||
if (true === is_object($class) && $class instanceof \libs\ApaiIO\ResponseTransformer\ResponseTransformerInterface) {
|
||||
return self::applyCallback($factoryCallback, $class);
|
||||
}
|
||||
|
||||
if (true === is_string($class) && true === array_key_exists($class, self::$responseTransformerObjects)) {
|
||||
return self::applyCallback($factoryCallback, self::$responseTransformerObjects[$class]);
|
||||
}
|
||||
|
||||
try {
|
||||
$reflectionClass = new \ReflectionClass($class);
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new \InvalidArgumentException(sprintf("Responsetransformerclass not found: %s", $class));
|
||||
}
|
||||
|
||||
if ($reflectionClass->implementsInterface('\\libs\\ApaiIO\\ResponseTransformer\\ResponseTransformerInterface')) {
|
||||
$responseTransformer = new $class();
|
||||
|
||||
return self::$responseTransformerObjects[$class] = self::applyCallback(
|
||||
$factoryCallback,
|
||||
$responseTransformer
|
||||
);
|
||||
}
|
||||
|
||||
throw new \LogicException(
|
||||
sprintf(
|
||||
"Responsetransformerclass does not implements the ResponseTransformerInterface: %s",
|
||||
$class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected static function applyCallback($callback, $responseTransformer)
|
||||
{
|
||||
if (false === is_null($callback) && is_callable($callback)) {
|
||||
$responseTransformer = call_user_func($callback, $responseTransformer);
|
||||
if ($responseTransformer instanceof ResponseTransformerInterface) {
|
||||
return $responseTransformer;
|
||||
}
|
||||
|
||||
throw new \LogicException(
|
||||
sprintf(
|
||||
"Responsetransformerclass does not implements the ResponseTransformerInterface: %s",
|
||||
get_class($responseTransformer)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $responseTransformer;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\ResponseTransformer;
|
||||
|
||||
interface ResponseTransformerInterface
|
||||
{
|
||||
/**
|
||||
* Transforms the response of the request
|
||||
*
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function transform($response);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\ResponseTransformer;
|
||||
|
||||
/**
|
||||
* A responsetransformer transforming a xml to a domdocument
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class XmlToDomDocument implements ResponseTransformerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($response)
|
||||
{
|
||||
$document = new \DOMDocument('1.0', 'UTF-8');
|
||||
$document->loadXML($response);
|
||||
|
||||
return $document;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\ResponseTransformer;
|
||||
|
||||
/**
|
||||
* A responsetransformer transforming a xml to a simpleXML Object.
|
||||
*
|
||||
* @author Nikolai Panasenko <nikolai@panasenko.de>
|
||||
*/
|
||||
class XmlToSimpleXmlObject implements ResponseTransformerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($response)
|
||||
{
|
||||
$simpleXML = simplexml_load_string($response);
|
||||
|
||||
return $simpleXML;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2013 Jan Eichhorn <exeu65@googlemail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace libs\ApaiIO\ResponseTransformer;
|
||||
|
||||
/**
|
||||
* A responsetransformer transforming an xml via xslt
|
||||
*
|
||||
* @author Jan Eichhorn <exeu65@googlemail.com>
|
||||
*/
|
||||
class Xslt implements ResponseTransformerInterface
|
||||
{
|
||||
/**
|
||||
* XSLTProcessor object
|
||||
*
|
||||
* @var \XSLTProcessor
|
||||
*/
|
||||
protected $xsl;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $xslt
|
||||
*/
|
||||
public function __construct($xslt)
|
||||
{
|
||||
$xsl = new \XSLTProcessor();
|
||||
$xsldoc = new \DOMDocument();
|
||||
|
||||
$xsldoc->loadXML($xslt);
|
||||
$xsl->importStyleSheet($xsldoc);
|
||||
|
||||
$this->xsl = $xsl;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($response)
|
||||
{
|
||||
$document = new \DOMDocument('1.0', 'UTF-8');
|
||||
$document->loadXML($response);
|
||||
|
||||
return $this->xsl->transformToXml($document);
|
||||
}
|
||||
}
|
||||
@@ -1,436 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* GiantBomb PHP wrapper is a simple class written in PHP to
|
||||
* make interactions with GiantBomb api easier.
|
||||
*
|
||||
* @package GiantBomb api PHP wrapper
|
||||
* @version 0.4
|
||||
* @author Amal Francis
|
||||
* @author Koroban
|
||||
* @license MIT License
|
||||
*/
|
||||
class GiantBomb
|
||||
{
|
||||
|
||||
/**
|
||||
* The api key
|
||||
*
|
||||
* @access private
|
||||
* @type string
|
||||
*/
|
||||
private $api_key = "";
|
||||
|
||||
/**
|
||||
* The api response type : json/xml
|
||||
*
|
||||
* @access private
|
||||
* @type string
|
||||
*/
|
||||
private $resp_type = "json";
|
||||
|
||||
/**
|
||||
* A variable to hold the formatted result of
|
||||
* last api request
|
||||
*
|
||||
* @access public
|
||||
* @type array
|
||||
*/
|
||||
public $result = array();
|
||||
|
||||
/**
|
||||
* api endpoint
|
||||
* prefix for all API cals
|
||||
*
|
||||
* @access protected
|
||||
* @type string
|
||||
*/
|
||||
protected $endpoint = 'http://www.giantbomb.com/api/';
|
||||
|
||||
/**
|
||||
* curl instance
|
||||
*
|
||||
* @access protected
|
||||
* @type handle
|
||||
*/
|
||||
protected $ch = null;
|
||||
|
||||
/**
|
||||
* Constructor of class
|
||||
*
|
||||
* @param string $key string API key to use
|
||||
* @param string $resp type Type of respone to request
|
||||
*
|
||||
* @void
|
||||
*/
|
||||
public function __construct($key, $resp = "json")
|
||||
{
|
||||
// Set the api key
|
||||
$this->api_key = $key;
|
||||
|
||||
// Now set the api response type, Default to json
|
||||
$this->resp_type = $resp;
|
||||
|
||||
// Init new instance of curl
|
||||
$this->ch = curl_init();
|
||||
|
||||
// set default options for curl
|
||||
curl_setopt_array(
|
||||
$this->ch,
|
||||
array(
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_NOPROGRESS => true,
|
||||
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
* deletes curl instance
|
||||
*
|
||||
* @void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// Close request to clear up some resources
|
||||
if (!is_null($this->ch)) {
|
||||
curl_close($this->ch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send call to API
|
||||
*
|
||||
* @param string $module string name of url suffix
|
||||
* @param array $params array get parameters to send to API
|
||||
*
|
||||
* @return mixed|array response of API
|
||||
* @throws GiantBombException
|
||||
*/
|
||||
private function call($module, $params = array())
|
||||
{
|
||||
// set api data
|
||||
$params['api_key'] = $this->api_key;
|
||||
$params['format'] = $this->resp_type;
|
||||
|
||||
// build URL
|
||||
$url = $this->endpoint . $module . '?' . http_build_query($params);
|
||||
|
||||
// Set URL
|
||||
curl_setopt($this->ch, CURLOPT_URL, $url);
|
||||
|
||||
// Send the request & save response to $resp
|
||||
$resp = array();
|
||||
$resp["data"] = curl_exec($this->ch);
|
||||
if (curl_errno($this->ch)) {
|
||||
throw new GiantBombException('API call failed: ' . curl_error($this->ch));
|
||||
}
|
||||
|
||||
// save http response code
|
||||
$resp["httpCode"] = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if (!$resp || !$resp["data"]) {
|
||||
throw new GiantBombException("Couldn't get information from API");
|
||||
}
|
||||
|
||||
return $resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format filter array to string
|
||||
*
|
||||
* @param $filters array list of filters
|
||||
*
|
||||
* @return string combined filter string
|
||||
*/
|
||||
private function format_filter($filters = array())
|
||||
{
|
||||
$filters_merged = array();
|
||||
foreach ($filters as $ky => $vl) {
|
||||
$filters_merged[] = $ky . ':' . $vl;
|
||||
}
|
||||
|
||||
return implode(',', $filters_merged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about given object type
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $id string id to request
|
||||
* @param array $field_list array list of fields to response
|
||||
*
|
||||
* @return array response
|
||||
* @throws GiantBombException
|
||||
*/
|
||||
public function get_object($type, $id, $field_list = array())
|
||||
{
|
||||
$resp = $this->call($type . '/' . $id . '/',
|
||||
array('field_list' => implode(',', $field_list)));
|
||||
|
||||
// No game with given game id found
|
||||
if ($resp["httpCode"] == 404) {
|
||||
throw new GiantBombException('Couldn\'t find ' . $type . ' with game id "' . $id . '"');
|
||||
}
|
||||
|
||||
return $this->parse_result($resp["data"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of objects by given filters
|
||||
*
|
||||
* @param $type
|
||||
* @param $filter array filter by given values - no "," accepted
|
||||
* @param $limit integer limit result count by given limit
|
||||
* @param $offset integer offset of results
|
||||
* @param $platform integer id of platform to limit
|
||||
* @param $sort array list of keys to sort, format key => asc/desc,
|
||||
* @param $field_list array list of field to result
|
||||
*
|
||||
* @return mixed|array response
|
||||
*/
|
||||
public function get_objects($type, $filter = array(), $limit = 100, $offset = 0,
|
||||
$platform = null, $sort = array(), $field_list = array())
|
||||
{
|
||||
$resp = $this->call($type . '/',
|
||||
array(
|
||||
'field_list' => implode(',', $field_list),
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
'platforms' => $platform,
|
||||
'sort' => $this->format_filter($sort),
|
||||
'filter' => $this->format_filter($filter)
|
||||
));
|
||||
|
||||
return $this->parse_result($resp["data"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about a game
|
||||
*
|
||||
* @param $id string id to request
|
||||
* @param $field_list array list of fields to response
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
public function game($id, $field_list = array())
|
||||
{
|
||||
return $this->get_object('game', $id, $field_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* List games by filters
|
||||
*
|
||||
* @param $filter array filter by given values - no "," accepted
|
||||
* @param $limit integer limit result count by given limit
|
||||
* @param $offset integer offset of results
|
||||
* @param $platform integer id of platform to limit
|
||||
* @param $sort array list of keys to sort, format key => asc/desc,
|
||||
* @param $field_list array list of field to result
|
||||
*
|
||||
* @return array list of games
|
||||
*/
|
||||
public function games($filter = array(), $limit = 100, $offset = 0, $platform = null,
|
||||
$sort = array(), $field_list = array())
|
||||
{
|
||||
return $this->get_objects('games', $filter, $limit, $offset, $platform, $sort, $field_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get review by id
|
||||
*
|
||||
* @param $review_id string id to request
|
||||
* @param $field_list array list of fields to response
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
public function review($review_id, $field_list = array())
|
||||
{
|
||||
return $this->get_object('review', $review_id, $field_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get game_rating by id
|
||||
*
|
||||
* @param $rating_id string id to request
|
||||
* @param $field_list array list of fields to response
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
public function game_rating($rating_id, $field_list = array())
|
||||
{
|
||||
return $this->get_object('game_rating', $rating_id, $field_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get company by id
|
||||
*
|
||||
* @param $company_id string id to request
|
||||
* @param $field_list array list of fields to response
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
public function company($company_id, $field_list = array())
|
||||
{
|
||||
return $this->get_object('company', $company_id, $field_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get character by id
|
||||
*
|
||||
* @param $character_id string id to request
|
||||
* @param $field_list array list of fields to response
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
public function character($character_id, $field_list = array())
|
||||
{
|
||||
return $this->get_object('character', $character_id, $field_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a search with given keyword
|
||||
*
|
||||
* @param $query string keyword to search
|
||||
* @param $field_list array list of fields to response
|
||||
* @param $limit integer limit result count by given limit
|
||||
* @param $page
|
||||
* @param $resources
|
||||
*
|
||||
* @return array response
|
||||
*/
|
||||
public function search($query, $field_list = array(), $limit = 100, $page = 0, $resources = array())
|
||||
{
|
||||
if (!is_array($field_list)) {
|
||||
$field_list = (array)$field_list;
|
||||
}
|
||||
if (!is_array($resources)) {
|
||||
$resources = (array)$resources;
|
||||
}
|
||||
|
||||
$resp = $this->call(
|
||||
'search/',
|
||||
array(
|
||||
'field_list' => implode(',', $field_list),
|
||||
'limit' => $limit,
|
||||
'page' => $page,
|
||||
'query' => $query,
|
||||
'resources' => implode(',', $resources)
|
||||
)
|
||||
);
|
||||
|
||||
return $this->parse_result($resp['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* List genres
|
||||
*
|
||||
* @param $field_list array list of field to result
|
||||
* @param $limit integer limit result count by given limit
|
||||
* @param $offset integer offset of results
|
||||
*
|
||||
* @return array list of games
|
||||
*/
|
||||
public function genres($field_list = array(), $limit = 100, $offset = 0)
|
||||
{
|
||||
$resp = $this->call(
|
||||
'genres/',
|
||||
array(
|
||||
'field_list' => implode(',', $field_list),
|
||||
'limit' => $limit,
|
||||
'offset' => $offset
|
||||
)
|
||||
);
|
||||
|
||||
return $this->parse_result($resp['data']);
|
||||
}
|
||||
|
||||
/**
|
||||
* List platforms by filter
|
||||
*
|
||||
* @param $field_list array list of field to result
|
||||
* @param $limit integer limit result count by given limit
|
||||
* @param $offset integer offset of results
|
||||
* @param $filter array filter by given values - no "," accepted
|
||||
* @param $sort array list of keys to sort, format key => asc/desc,
|
||||
*
|
||||
* @return array list of games
|
||||
*/
|
||||
public function platforms($field_list = array(), $limit = 100, $offset = 0, $filter = array(),
|
||||
$sort = array())
|
||||
{
|
||||
$resp = $this->call(
|
||||
'platforms/',
|
||||
array(
|
||||
'field_list' => implode(',', $field_list),
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
'sort' => $this->format_filter($sort),
|
||||
'filter' => $this->format_filter($filter)
|
||||
)
|
||||
);
|
||||
|
||||
return $this->parse_result($resp["data"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return parsed result of api response
|
||||
*
|
||||
* @param $data string result of API
|
||||
*
|
||||
* @return mixed|SimpleXMLElement parsed version of input string(object)
|
||||
* @throws GiantBombException
|
||||
*/
|
||||
private function parse_result($data)
|
||||
{
|
||||
try {
|
||||
if ($this->resp_type == "json") {
|
||||
$result = @json_decode($data);
|
||||
} else {
|
||||
$result = @simplexml_load_string($data);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new GiantBombException("Parse error occoured", null, $e);
|
||||
}
|
||||
|
||||
if (empty($result) || !empty($result->error) && strtoupper($result->error) != "OK") {
|
||||
throw new GiantBombException("Following error encountered: " . $result->error);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a custom exception class for api wrapper
|
||||
*/
|
||||
class GiantBombException extends Exception
|
||||
{
|
||||
|
||||
/**
|
||||
* Redefine the exception so message isn't optional
|
||||
*
|
||||
* @param $message string message to set in exception
|
||||
* @param $code integer error code
|
||||
* @param $previous Exception previous Exception to save
|
||||
*
|
||||
* @void
|
||||
*/
|
||||
public function __construct($message, $code = 0, Exception $previous = null)
|
||||
{
|
||||
// make sure everything is assigned properly
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert exception to string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
|
||||
}
|
||||
}
|
||||
@@ -1,684 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Git.php
|
||||
*
|
||||
* A PHP git library
|
||||
*
|
||||
* @package Git.php
|
||||
* @version 0.1.4
|
||||
* @author James Brumond
|
||||
* @copyright Copyright 2013 James Brumond
|
||||
* @repo http://github.com/kbjr/Git.php
|
||||
*/
|
||||
|
||||
if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) die('Bad load order');
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Git Interface Class
|
||||
*
|
||||
* This class enables the creating, reading, and manipulation
|
||||
* of git repositories.
|
||||
*
|
||||
* @class Git
|
||||
*/
|
||||
class Git {
|
||||
|
||||
/**
|
||||
* Git executable location
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $bin = null;
|
||||
|
||||
public function __construct($binPath = null)
|
||||
{
|
||||
self::check_bin($binPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets git executable path
|
||||
*
|
||||
* @param string $path executable location
|
||||
*/
|
||||
public static function set_bin($path) {
|
||||
self::$bin = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets git executable path
|
||||
*/
|
||||
public static function get_bin() {
|
||||
return empty(self::$bin) ? self::check_bin() : self::$bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up library for use in a default Windows environment
|
||||
*/
|
||||
public static function windows_mode() {
|
||||
self::set_bin('git');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new git repository
|
||||
*
|
||||
* Accepts a creation path, and, optionally, a source path
|
||||
*
|
||||
* @access public
|
||||
* @param string repository path
|
||||
* @param string directory to source
|
||||
* @return GitRepo
|
||||
*/
|
||||
public static function &create($repo_path, $source = null) {
|
||||
return GitRepo::create_new($repo_path, $source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an existing git repository
|
||||
*
|
||||
* Accepts a repository path
|
||||
*
|
||||
* @access public
|
||||
* @param string repository path
|
||||
* @return GitRepo
|
||||
*/
|
||||
public static function open($repo_path) {
|
||||
return new GitRepo($repo_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones a remote repo into a directory and then returns a GitRepo object
|
||||
* for the newly created local repo
|
||||
*
|
||||
* Accepts a creation path and a remote to clone from
|
||||
*
|
||||
* @access public
|
||||
* @param string repository path
|
||||
* @param string remote source
|
||||
* @return GitRepo
|
||||
**/
|
||||
public static function &clone_remote($repo_path, $remote) {
|
||||
return GitRepo::create_new($repo_path, $remote, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a variable is an instance of GitRepo
|
||||
*
|
||||
* Accepts a variable
|
||||
*
|
||||
* @access public
|
||||
* @param mixed variable
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_repo($var) {
|
||||
return (get_class($var) == 'GitRepo');
|
||||
}
|
||||
|
||||
private static function check_bin($binPath = '')
|
||||
{
|
||||
$binPath = $binPath ?: '/usr/bin/git';
|
||||
|
||||
$resource = proc_open('which git', [1 => ['pipe', 'w']], $pipes);
|
||||
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
|
||||
foreach ($pipes as $pipe) {
|
||||
fclose($pipe);
|
||||
}
|
||||
|
||||
$status = trim(proc_close($resource));
|
||||
|
||||
if (!$status) {
|
||||
$binPath = trim($stdout);
|
||||
}
|
||||
|
||||
if (strpos($binPath, ' ') !== false) {
|
||||
$binPath = newznab\utility\Utility::isWin() ? '"' . $binPath . '"'
|
||||
: str_replace(' ', '\ ', $binPath);
|
||||
}
|
||||
|
||||
self::set_bin($binPath);
|
||||
return $binPath;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Git Repository Interface Class
|
||||
*
|
||||
* This class enables the creating, reading, and manipulation
|
||||
* of a git repository
|
||||
*
|
||||
* @class GitRepo
|
||||
*/
|
||||
class GitRepo {
|
||||
|
||||
protected $repo_path = null;
|
||||
protected $bare = false;
|
||||
protected $envopts = array();
|
||||
|
||||
/**
|
||||
* Create a new git repository
|
||||
*
|
||||
* Accepts a creation path, and, optionally, a source path
|
||||
*
|
||||
* @access public
|
||||
* @param string repository path
|
||||
* @param string directory to source
|
||||
* @return GitRepo
|
||||
*/
|
||||
public static function &create_new($repo_path, $source = null, $remote_source = false) {
|
||||
if (is_dir($repo_path) && file_exists($repo_path."/.git") && is_dir($repo_path."/.git")) {
|
||||
throw new Exception('"'.$repo_path.'" is already a git repository');
|
||||
} else {
|
||||
$repo = new self($repo_path, true, false);
|
||||
if (is_string($source)) {
|
||||
if ($remote_source) {
|
||||
$repo->clone_remote($source);
|
||||
} else {
|
||||
$repo->clone_from($source);
|
||||
}
|
||||
} else {
|
||||
$repo->run('init');
|
||||
}
|
||||
return $repo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Accepts a repository path
|
||||
*
|
||||
* @access public
|
||||
* @param string repository path
|
||||
* @param bool create if not exists?
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($path = null, $create_new = false, $_init = true) {
|
||||
if (is_string($path)) {
|
||||
$this->set_repo_path($path, $create_new, $_init);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the repository's path
|
||||
*
|
||||
* Accepts the repository path
|
||||
*
|
||||
* @access public
|
||||
* @param string repository path
|
||||
* @param bool create if not exists?
|
||||
* @param bool initialize new Git repo if not exists?
|
||||
* @return void
|
||||
*/
|
||||
public function set_repo_path($repo_path, $create_new = false, $_init = true) {
|
||||
if (is_string($repo_path)) {
|
||||
if ($new_path = realpath($repo_path)) {
|
||||
$repo_path = $new_path;
|
||||
if (is_dir($repo_path)) {
|
||||
// Is this a work tree?
|
||||
if (file_exists($repo_path."/.git") && is_dir($repo_path."/.git")) {
|
||||
$this->repo_path = $repo_path;
|
||||
$this->bare = false;
|
||||
// Is this a bare repo?
|
||||
} else if (is_file($repo_path."/config")) {
|
||||
$parse_ini = parse_ini_file($repo_path."/config");
|
||||
if ($parse_ini['bare']) {
|
||||
$this->repo_path = $repo_path;
|
||||
$this->bare = true;
|
||||
}
|
||||
} else {
|
||||
if ($create_new) {
|
||||
$this->repo_path = $repo_path;
|
||||
if ($_init) {
|
||||
$this->run('init');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('"'.$repo_path.'" is not a git repository');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Exception('"'.$repo_path.'" is not a directory');
|
||||
}
|
||||
} else {
|
||||
if ($create_new) {
|
||||
if ($parent = realpath(dirname($repo_path))) {
|
||||
mkdir($repo_path);
|
||||
$this->repo_path = $repo_path;
|
||||
if ($_init) $this->run('init');
|
||||
} else {
|
||||
throw new Exception('cannot create repository in non-existent directory');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('"'.$repo_path.'" does not exist');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if git is installed
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function test_git() {
|
||||
$descriptorspec = array(
|
||||
1 => array('pipe', 'w'),
|
||||
2 => array('pipe', 'w'),
|
||||
);
|
||||
$pipes = array();
|
||||
$resource = proc_open(Git::get_bin(), $descriptorspec, $pipes);
|
||||
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
foreach ($pipes as $pipe) {
|
||||
fclose($pipe);
|
||||
}
|
||||
|
||||
$status = trim(proc_close($resource));
|
||||
return ($status != 127);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a command in the git repository
|
||||
*
|
||||
* Accepts a shell command to run
|
||||
*
|
||||
* @access protected
|
||||
* @param string command to run
|
||||
* @return string
|
||||
*/
|
||||
protected function run_command($command) {
|
||||
$descriptorspec = array(
|
||||
1 => array('pipe', 'w'),
|
||||
2 => array('pipe', 'w'),
|
||||
);
|
||||
$pipes = array();
|
||||
/* Depending on the value of variables_order, $_ENV may be empty.
|
||||
* In that case, we have to explicitly set the new variables with
|
||||
* putenv, and call proc_open with env=null to inherit the reset
|
||||
* of the system.
|
||||
*
|
||||
* This is kind of crappy because we cannot easily restore just those
|
||||
* variables afterwards.
|
||||
*
|
||||
* If $_ENV is not empty, then we can just copy it and be done with it.
|
||||
*/
|
||||
if(count($_ENV) === 0) {
|
||||
$env = NULL;
|
||||
foreach($this->envopts as $k => $v) {
|
||||
putenv(sprintf("%s=%s",$k,$v));
|
||||
}
|
||||
} else {
|
||||
$env = array_merge($_ENV, $this->envopts);
|
||||
}
|
||||
$cwd = $this->repo_path;
|
||||
$resource = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
|
||||
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
foreach ($pipes as $pipe) {
|
||||
fclose($pipe);
|
||||
}
|
||||
|
||||
$status = trim(proc_close($resource));
|
||||
if ($status) throw new Exception($stderr . PHP_EOL . $command);
|
||||
|
||||
return $stdout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a git command in the git repository
|
||||
*
|
||||
* Accepts a git command to run
|
||||
*
|
||||
* @access public
|
||||
* @param string command to run
|
||||
* @return string
|
||||
*/
|
||||
public function run($command) {
|
||||
// If git.exe is in C:/Program Files, the space between Program and Files causes an error.
|
||||
return $this->run_command(Git::get_bin() . " " . $command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a 'git status' call
|
||||
*
|
||||
* Accept a convert to HTML bool
|
||||
*
|
||||
* @access public
|
||||
* @param bool return string with <br />
|
||||
* @return string
|
||||
*/
|
||||
public function status($html = false) {
|
||||
$msg = $this->run("status");
|
||||
if ($html == true) {
|
||||
$msg = str_replace("\n", "<br />", $msg);
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git add` call
|
||||
*
|
||||
* Accepts a list of files to add
|
||||
*
|
||||
* @access public
|
||||
* @param mixed files to add
|
||||
* @return string
|
||||
*/
|
||||
public function add($files = "*") {
|
||||
if (is_array($files)) {
|
||||
$files = '"'.implode('" "', $files).'"';
|
||||
}
|
||||
return $this->run("add $files -v");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git rm` call
|
||||
*
|
||||
* Accepts a list of files to remove
|
||||
*
|
||||
* @access public
|
||||
* @param mixed files to remove
|
||||
* @param Boolean use the --cached flag?
|
||||
* @return string
|
||||
*/
|
||||
public function rm($files = "*", $cached = false) {
|
||||
if (is_array($files)) {
|
||||
$files = '"'.implode('" "', $files).'"';
|
||||
}
|
||||
return $this->run("rm ".($cached ? '--cached ' : '').$files);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs a `git commit` call
|
||||
*
|
||||
* Accepts a commit message string
|
||||
*
|
||||
* @access public
|
||||
* @param string commit message
|
||||
* @return string
|
||||
*/
|
||||
public function commit($message = "") {
|
||||
return $this->run("commit -av -m ".escapeshellarg($message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git clone` call to clone the current repository
|
||||
* into a different directory
|
||||
*
|
||||
* Accepts a target directory
|
||||
*
|
||||
* @access public
|
||||
* @param string target directory
|
||||
* @return string
|
||||
*/
|
||||
public function clone_to($target) {
|
||||
return $this->run("clone --local ".$this->repo_path." $target");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git clone` call to clone a different repository
|
||||
* into the current repository
|
||||
*
|
||||
* Accepts a source directory
|
||||
*
|
||||
* @access public
|
||||
* @param string source directory
|
||||
* @return string
|
||||
*/
|
||||
public function clone_from($source) {
|
||||
return $this->run("clone --local $source ".$this->repo_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git clone` call to clone a remote repository
|
||||
* into the current repository
|
||||
*
|
||||
* Accepts a source url
|
||||
*
|
||||
* @access public
|
||||
* @param string source url
|
||||
* @return string
|
||||
*/
|
||||
public function clone_remote($source) {
|
||||
return $this->run("clone $source ".$this->repo_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git clean` call
|
||||
*
|
||||
* Accepts a remove directories flag
|
||||
*
|
||||
* @access public
|
||||
* @param bool delete directories?
|
||||
* @param bool force clean?
|
||||
* @return string
|
||||
*/
|
||||
public function clean($dirs = false, $force = false) {
|
||||
return $this->run("clean".(($force) ? " -f" : "").(($dirs) ? " -d" : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git branch` call
|
||||
*
|
||||
* Accepts a name for the branch
|
||||
*
|
||||
* @access public
|
||||
* @param string branch name
|
||||
* @return string
|
||||
*/
|
||||
public function create_branch($branch) {
|
||||
return $this->run("branch $branch");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git branch -[d|D]` call
|
||||
*
|
||||
* Accepts a name for the branch
|
||||
*
|
||||
* @access public
|
||||
* @param string branch name
|
||||
* @return string
|
||||
*/
|
||||
public function delete_branch($branch, $force = false) {
|
||||
return $this->run("branch ".(($force) ? '-D' : '-d')." $branch");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git branch` call
|
||||
*
|
||||
* @access public
|
||||
* @param bool keep asterisk mark on active branch
|
||||
* @return array
|
||||
*/
|
||||
public function list_branches($keep_asterisk = false) {
|
||||
$branchArray = explode("\n", $this->run("branch"));
|
||||
foreach($branchArray as $i => &$branch) {
|
||||
$branch = trim($branch);
|
||||
if (! $keep_asterisk) {
|
||||
$branch = str_replace("* ", "", $branch);
|
||||
}
|
||||
if ($branch == "") {
|
||||
unset($branchArray[$i]);
|
||||
}
|
||||
}
|
||||
return $branchArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists remote branches (using `git branch -r`).
|
||||
*
|
||||
* Also strips out the HEAD reference (e.g. "origin/HEAD -> origin/master").
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function list_remote_branches() {
|
||||
$branchArray = explode("\n", $this->run("branch -r"));
|
||||
foreach($branchArray as $i => &$branch) {
|
||||
$branch = trim($branch);
|
||||
if ($branch == "" || strpos($branch, 'HEAD -> ') !== false) {
|
||||
unset($branchArray[$i]);
|
||||
}
|
||||
}
|
||||
return $branchArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of active branch
|
||||
*
|
||||
* @access public
|
||||
* @param bool keep asterisk mark on branch name
|
||||
* @return string
|
||||
*/
|
||||
public function active_branch($keep_asterisk = false) {
|
||||
$branchArray = $this->list_branches(true);
|
||||
$active_branch = preg_grep("/^\*/", $branchArray);
|
||||
reset($active_branch);
|
||||
if ($keep_asterisk) {
|
||||
return current($active_branch);
|
||||
} else {
|
||||
return str_replace("* ", "", current($active_branch));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a `git checkout` call
|
||||
*
|
||||
* Accepts a name for the branch
|
||||
*
|
||||
* @access public
|
||||
* @param string branch name
|
||||
* @return string
|
||||
*/
|
||||
public function checkout($branch) {
|
||||
return $this->run("checkout $branch");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs a `git merge` call
|
||||
*
|
||||
* Accepts a name for the branch to be merged
|
||||
*
|
||||
* @access public
|
||||
* @param string $branch
|
||||
* @return string
|
||||
*/
|
||||
public function merge($branch) {
|
||||
return $this->run("merge $branch --no-ff");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs a git fetch on the current branch
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function fetch() {
|
||||
return $this->run("fetch");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new tag on the current position
|
||||
*
|
||||
* Accepts the name for the tag and the message
|
||||
*
|
||||
* @param string $tag
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
public function add_tag($tag, $message = null) {
|
||||
if ($message === null) {
|
||||
$message = $tag;
|
||||
}
|
||||
return $this->run("tag -a $tag -m $message");
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the available repository tags.
|
||||
*
|
||||
* Optionally, accept a shell wildcard pattern and return only tags matching it.
|
||||
*
|
||||
* @access public
|
||||
* @param string $pattern Shell wildcard pattern to match tags against.
|
||||
* @return array Available repository tags.
|
||||
*/
|
||||
public function list_tags($pattern = null) {
|
||||
$tagArray = explode("\n", $this->run("tag -l $pattern"));
|
||||
foreach ($tagArray as $i => &$tag) {
|
||||
$tag = trim($tag);
|
||||
if ($tag == '') {
|
||||
unset($tagArray[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return $tagArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push specific branch to a remote
|
||||
*
|
||||
* Accepts the name of the remote and local branch
|
||||
*
|
||||
* @param string $remote
|
||||
* @param string $branch
|
||||
* @return string
|
||||
*/
|
||||
public function push($remote, $branch) {
|
||||
return $this->run("push --tags $remote $branch");
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull specific branch from remote
|
||||
*
|
||||
* Accepts the name of the remote and local branch
|
||||
*
|
||||
* @param string $remote
|
||||
* @param string $branch
|
||||
* @return string
|
||||
*/
|
||||
public function pull($remote, $branch) {
|
||||
return $this->run("pull $remote $branch");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the project description.
|
||||
*
|
||||
* @param string $new
|
||||
*/
|
||||
public function set_description($new) {
|
||||
file_put_contents($this->repo_path."/.git/description", $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the project description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return file_get_contents($this->repo_path."/.git/description");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom environment options for calling Git
|
||||
*
|
||||
* @param string key
|
||||
* @param string value
|
||||
*/
|
||||
public function setenv($key, $value) {
|
||||
$this->envopts[$key] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* End of file */
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "kbjr/Git.php",
|
||||
"autoload": {
|
||||
"classmap": ["Git.php"]
|
||||
}
|
||||
}
|
||||
@@ -1,708 +0,0 @@
|
||||
Copyright (c) 2010 James Brumond
|
||||
|
||||
This software is dual licensed under the MIT and GNU General Public Licenses.
|
||||
This means that you may use this software under either of these licenses (at
|
||||
your option).
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
MIT LICENSE
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -1,21 +0,0 @@
|
||||
# Git.php
|
||||
|
||||
## Description
|
||||
|
||||
A PHP git repository control library. Allows the running of any git command from a PHP class. Runs git commands using `proc_open`, not `exec` or the type, therefore it can run in PHP safe mode.
|
||||
|
||||
## Requirements
|
||||
|
||||
A system with [git](http://git-scm.com/) installed
|
||||
|
||||
## Basic Use
|
||||
|
||||
```php
|
||||
require_once('Git.php');
|
||||
|
||||
$repo = Git::open('/path/to/repo'); // -or- Git::create('/path/to/repo')
|
||||
|
||||
$repo->add('.');
|
||||
$repo->commit('Some commit message');
|
||||
$repo->push('origin', 'master');
|
||||
```
|
||||
@@ -1,170 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* test-suite.php
|
||||
*
|
||||
* The Git.php test suite
|
||||
*
|
||||
* @package Git.php
|
||||
* @version 0.1.1-a
|
||||
* @author James Brumond
|
||||
* @copyright Copyright 2010 James Brumond
|
||||
* @license http://github.com/kbjr/Git.php
|
||||
* @link http://code.kbjrweb.com/project/gitphp
|
||||
*/
|
||||
|
||||
define("DIR", dirname(__FILE__));
|
||||
|
||||
// include the git library
|
||||
require DIR."/../Git.php";
|
||||
|
||||
$Git_Tests = array(
|
||||
|
||||
'Git' => function() {
|
||||
$return = null;
|
||||
$repo = new GitRepo();
|
||||
$found = $repo->test_git();
|
||||
if ($found) {
|
||||
$return = array(0, "Git was located and tested successfully");
|
||||
} else {
|
||||
$return = array(1, "Git could not be found at the default location");
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
|
||||
'Git::create()' => function() {
|
||||
$return = null;
|
||||
$repo = Git::create(DIR."/create");
|
||||
if (! Git::is_repo($repo)) {
|
||||
$return = array(2, "Git::create() failed to produce expected output.");
|
||||
} else {
|
||||
$return = array(0, "Git::create() executed successfully");
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
|
||||
'Git::create([ $source ])' => function() {
|
||||
$return = null;
|
||||
$repo = Git::create(DIR."/createfrom", DIR."/test.git");
|
||||
if (! Git::is_repo($repo)) {
|
||||
$return = array(2, "Git::create([ \$source ]) failed to produce expected output.");
|
||||
} else {
|
||||
$return = array(0, "Git::create([ \$source ]) executed successfully");
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
|
||||
'Git::open()' => function() {
|
||||
$return = null;
|
||||
$repo = Git::open(DIR."/test.git");
|
||||
if (! Git::is_repo($repo)) {
|
||||
$return = array(2, "Git::open() failed to produce expected output.");
|
||||
} else {
|
||||
$return = array(0, "Git::open() executed successfully");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
class Git_TestSuiteControl {
|
||||
|
||||
protected $warnings = 0;
|
||||
protected $errors = 0;
|
||||
|
||||
public static function rm($dir) {
|
||||
if (! file_exists($dir)) return true;
|
||||
if (! is_dir($dir)) return unlink($dir);
|
||||
$items = scandir($dir);
|
||||
closedir(opendir($dir));
|
||||
foreach ($items as $item) {
|
||||
if ($item == '.' || $item == '..') continue;
|
||||
if (! self::rm("$dir/$item")) return false;
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
$this->output("Starting Git.php Test Suite.");
|
||||
}
|
||||
|
||||
public function output($msg) {
|
||||
echo "$msg\n";
|
||||
}
|
||||
|
||||
public function warning($msg) {
|
||||
$this->warnings++;
|
||||
$this->output("Warning: $msg");
|
||||
}
|
||||
|
||||
public function error($msg) {
|
||||
$this->errors++;
|
||||
$this->output("Error: $msg");
|
||||
}
|
||||
|
||||
public function finish() {
|
||||
$this->cleanup();
|
||||
$this->output("\n\n".str_repeat('-', 30));
|
||||
$this->output("Tests Complete. Results:");
|
||||
$this->output("Errors: ".$this->errors." Warnings: ".$this->warnings);
|
||||
}
|
||||
|
||||
public function cleanup() {
|
||||
self::rm(DIR."/create");
|
||||
self::rm(DIR."/createfrom");
|
||||
}
|
||||
|
||||
public function run_test($name, $callback) {
|
||||
$this->output("\nTesting $name.");
|
||||
$this->cleanup();
|
||||
try {
|
||||
$oldReport = error_reporting(0);
|
||||
set_error_handler(function($n, $str) {
|
||||
throw new Exception($str);
|
||||
});
|
||||
$result = $callback();
|
||||
error_reporting($oldReport);
|
||||
restore_error_handler();
|
||||
} catch (Exception $e) {
|
||||
$this->error("Test case threw an exception:\n ".implode("\n ", explode("\n", $e->getMessage())));
|
||||
return;
|
||||
}
|
||||
switch ($result[0]) {
|
||||
case 0:
|
||||
$this->output($result[1]);
|
||||
break;
|
||||
case 1:
|
||||
$this->warning($result[1]);
|
||||
break;
|
||||
case 2:
|
||||
$this->error($result[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// define the test class
|
||||
class Git_TestSuite {
|
||||
|
||||
public static function run() {
|
||||
|
||||
$test = new Git_TestSuiteControl();
|
||||
|
||||
foreach ($GLOBALS['Git_Tests'] as $name => $callback) {
|
||||
$test->run_test($name, $callback);
|
||||
}
|
||||
|
||||
$test->finish();
|
||||
unset($test);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) {
|
||||
header("Content-Type: text/plain");
|
||||
Git_TestSuite::run();
|
||||
}
|
||||
|
||||
/* End Of File */
|
||||
@@ -1,46 +0,0 @@
|
||||
# TVMaze-PHP-API-Wrapper
|
||||
An easier way to interact with TVMaze's endpoints. Developed in PHP.
|
||||
|
||||
Goal
|
||||
====
|
||||
- The goal of this API Wrapper is to turn TVMaze's endpoints into something more object orientated and readable
|
||||
|
||||
Documentation
|
||||
=============
|
||||
At the current version this wrapper supports all of TVMaze's endpoints except for schedule.
|
||||
|
||||
Pre-reqs
|
||||
--------
|
||||
- Before attempting to use this wrapper make sure you require 'TVMazeIncludes.php'; at the top of your php file.
|
||||
|
||||
Supported Methods
|
||||
-----------------
|
||||
search -> Return all tv shows relating to the given input
|
||||
|
||||
singleSearch -> Return the most relevant tv show relating to the given input
|
||||
|
||||
getShowBySiteID -> Allows show lookup by using TVRage or TheTVDB ID
|
||||
|
||||
getPersonByName -> Return all possible actors relating to the given input
|
||||
|
||||
getSchedule (In progess) -> Return all the shows in the given country and/or date
|
||||
|
||||
getShowByShowID -> Return all information about a show given the show ID
|
||||
|
||||
getEpisodesByShowID -> Return all episodes for a show given the show ID
|
||||
|
||||
getCastByShowID -> Return the cast for a show given the show ID
|
||||
|
||||
getAllShowsByPage -> Return a master list of TVMaze's shows given the page number
|
||||
|
||||
getPersonByID -> Return an actor given their ID
|
||||
|
||||
getCastCreditsByID -> Return an array of all the shows a particular actor has been in given their ID
|
||||
|
||||
getCrewCreditsByID -> Return an array of all the positions a particular actor has been in given their ID
|
||||
|
||||
Open Source Projects using this
|
||||
-------------------------------
|
||||
nZEDb
|
||||
Website Link: http://www.nzedb.com
|
||||
Github Link: https://github.com/nZEDb/nZEDb
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
Class AKA
|
||||
{
|
||||
/**
|
||||
* @param $aka_data
|
||||
*/
|
||||
function __construct($aka_data)
|
||||
{
|
||||
if(!empty($aka_data['name'])) {
|
||||
$this->akas = $aka_data['name'];
|
||||
} else {
|
||||
$this->akas = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Creator: jpinkney
|
||||
* Date: 9/15/15
|
||||
* Time: 2:15 PM
|
||||
*/
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
/*
|
||||
*
|
||||
* Currently unused because there is no actor specific methods with TVMaze
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Actor
|
||||
*
|
||||
* @package JPinkney\TVMaze
|
||||
*/
|
||||
class Actor extends TVProduction {
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* User: jpinkney
|
||||
* Date: 9/15/15
|
||||
* Time: 2:15 PM
|
||||
*/
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
/*
|
||||
*
|
||||
* Currently unused because there is no character specific methods with TVMaze
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Class Character
|
||||
*
|
||||
* @package JPinkney\TVMaze
|
||||
*/
|
||||
class Character extends TVProduction {
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -1,392 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
/**
|
||||
* Class Client
|
||||
*
|
||||
* @package libs\JPinkney\TVMaze
|
||||
*/
|
||||
class Client {
|
||||
|
||||
CONST APIURL = 'http://api.tvmaze.com';
|
||||
|
||||
/**
|
||||
* @var array Embed Options for API Queries
|
||||
*/
|
||||
public $embed;
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a show name
|
||||
* Outputs array of all the related shows for that given name
|
||||
*
|
||||
* @param $show_name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function search($show_name)
|
||||
{
|
||||
$relevant_shows = false;
|
||||
$url = self::APIURL . "/search/shows?q=" . rawurlencode($show_name);
|
||||
|
||||
$shows = $this->getFile($url);
|
||||
|
||||
if (is_array($shows)) {
|
||||
$relevant_shows = array();
|
||||
foreach ($shows as $series) {
|
||||
$TVShow = new TVShow($series['show']);
|
||||
array_push($relevant_shows, $TVShow);
|
||||
}
|
||||
}
|
||||
return $relevant_shows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a show name with optional modifiers (akas)
|
||||
* Outputs array of the MOST related show for that given name
|
||||
*
|
||||
* @param $show_name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function singleSearch($show_name)
|
||||
{
|
||||
$TVShow = false;
|
||||
$url = self::APIURL . "/singlesearch/shows?q=" . rawurlencode($show_name) . '&embed=akas';
|
||||
$shows = $this->getFile($url);
|
||||
|
||||
if (is_array($shows)) {
|
||||
$TVShow = new TVShow($shows);
|
||||
}
|
||||
return array($TVShow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows show lookup by using TVRage or TheTVDB ID
|
||||
* site is the string of the website (either 'tvrage' or 'thetvdb') and the id is the id of the show on that respective site
|
||||
*
|
||||
* @param $site
|
||||
* @param $ID
|
||||
*
|
||||
* @return TVShow
|
||||
*/
|
||||
function getShowBySiteID($site, $ID)
|
||||
{
|
||||
$site = strtolower($site);
|
||||
$url = self::APIURL . '/lookup/shows?' . $site . '=' . $ID;
|
||||
$show = $this->getFile($url);
|
||||
|
||||
return new TVShow($show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in an actors name and outputs their actor object
|
||||
*
|
||||
* @param $name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getPersonByName($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
$url = self::APIURL . '/search/people?q=' . $name;
|
||||
$person = $this->getFile($url);
|
||||
|
||||
$people = array();
|
||||
foreach($person as $peeps) {
|
||||
array_push($people, new Actor($peeps['person']));
|
||||
}
|
||||
|
||||
return $people;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: this still needs to be done
|
||||
*
|
||||
* @param null $country
|
||||
* @param null $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getSchedule($country=null, $date=null) {
|
||||
if($country != null && $date != null) {
|
||||
$url = self::APIURL . '/schedule?country=' . $country .'&date='. $date;
|
||||
} else if ($country == null && $date != null) {
|
||||
$url = self::APIURL . '/schedule?date=' . $date;
|
||||
} else if ($country != null && $date == null) {
|
||||
$url = self::APIURL . '/schedule?country=' . $country;
|
||||
} else {
|
||||
$url = self::APIURL . '/schedule';
|
||||
}
|
||||
|
||||
$schedule = $this->getFile($url);
|
||||
|
||||
$show_list = array();
|
||||
foreach($schedule as $episode) {
|
||||
$ep = new Episode($episode);
|
||||
$show = new TVShow($episode['show']);
|
||||
array_push($show_list, $show, $ep);
|
||||
}
|
||||
|
||||
return $show_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a show ID and outputs the TVShow Object
|
||||
*
|
||||
* @param $ID
|
||||
* @param null $embed_cast
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
function getShowByShowID($ID, $embed_cast = false)
|
||||
{
|
||||
if($embed_cast) {
|
||||
$url = self::APIURL . '/shows/'. $ID . '?embed=cast';
|
||||
} else {
|
||||
$url = self::APIURL . '/shows/' . $ID;
|
||||
}
|
||||
|
||||
$show = $this->getFile($url);
|
||||
|
||||
$cast = array();
|
||||
if ($embed_cast) {
|
||||
foreach($show['_embedded']['cast'] as $person) {
|
||||
$actor = new Actor($person['person']);
|
||||
$character = new Character($person['character']);
|
||||
array_push($cast, array($actor, $character));
|
||||
}
|
||||
}
|
||||
|
||||
$TVShow = new TVShow($show);
|
||||
|
||||
return ($embed_cast === true ? array($TVShow, $cast) : $TVShow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a show ID and outputs the AKA Object
|
||||
*
|
||||
* @param $ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getShowAKAs($ID)
|
||||
{
|
||||
$url = self::APIURL . '/shows/' . $ID . '/akas';
|
||||
|
||||
$akas = $this->getFile($url);
|
||||
|
||||
$AKA = new AKA($akas);
|
||||
|
||||
if (!empty($akas['name'])) {
|
||||
|
||||
return $AKA;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a show ID and outputs all the episode objects for that show in an array
|
||||
*
|
||||
* @param $ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getEpisodesByShowID($ID)
|
||||
{
|
||||
|
||||
$url = self::APIURL . '/shows/' . $ID . '/episodes';
|
||||
|
||||
$episodes = $this->getFile($url);
|
||||
|
||||
$allEpisodes = array();
|
||||
if (is_array($episodes)) {
|
||||
foreach ($episodes as $episode) {
|
||||
$ep = new Episode($episode);
|
||||
array_push($allEpisodes, $ep);
|
||||
}
|
||||
}
|
||||
return $allEpisodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single episodes information by its show ID, season and episode numbers
|
||||
*
|
||||
* @param $ID
|
||||
* @param $season
|
||||
* @param $episode
|
||||
*
|
||||
* @return Episode|mixed
|
||||
*/
|
||||
function getEpisodeByNumber($ID, $season, $episode)
|
||||
{
|
||||
$ep = false;
|
||||
$url = self::APIURL . '/shows/' . $ID . '/episodebynumber?season='. $season . '&number=' . $episode;
|
||||
$response = $this->getFile($url);
|
||||
if (is_array($response)) {
|
||||
$ep = new Episode($response);
|
||||
}
|
||||
return $ep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns episodes for a given show ID and ISO 8601 airdate
|
||||
*
|
||||
* @param $ID
|
||||
* @param $airdate
|
||||
*
|
||||
* @return Episode|mixed
|
||||
*/
|
||||
function getEpisodesByAirdate($ID, $airdate)
|
||||
{
|
||||
$url = self::APIURL . '/shows/' . $ID . '/episodesbydate?date=' . date('Y-m-d', strtotime($airdate));
|
||||
$episodes = $this->getFile($url);
|
||||
|
||||
$allEpisodes = array();
|
||||
if (is_array($episodes)) {
|
||||
foreach ($episodes as $episode) {
|
||||
$ep = new Episode($episode);
|
||||
array_push($allEpisodes, $ep);
|
||||
}
|
||||
}
|
||||
return $allEpisodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a show ID and outputs all of the cast members in the form (actor, character)
|
||||
*
|
||||
* @param $ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getCastByShowID($ID)
|
||||
{
|
||||
$url = self::APIURL . '/shows/' . $ID . '/cast';
|
||||
$people = $this->getFile($url);
|
||||
|
||||
$cast = array();
|
||||
foreach($people as $person) {
|
||||
$actor = new Actor($person['person']);
|
||||
$character = new Character($person['character']);
|
||||
array_push($cast, array($actor, $character));
|
||||
}
|
||||
|
||||
return $cast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all shows in the database. Page number is optional (caps display at 250 results)
|
||||
*
|
||||
* @param null $page
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getAllShowsByPage($page=null)
|
||||
{
|
||||
if($page == null){
|
||||
$url = self::APIURL . '/shows';
|
||||
}else{
|
||||
$url = self::APIURL . '/shows?page' . $page;
|
||||
}
|
||||
|
||||
$shows = $this->getFile($url);
|
||||
|
||||
$relevant_shows = array();
|
||||
foreach($shows as $series){
|
||||
$TVShow = new TVShow($series);
|
||||
array_push($relevant_shows, $TVShow);
|
||||
}
|
||||
return $relevant_shows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an actor by their ID
|
||||
*
|
||||
* @param $ID
|
||||
*
|
||||
* @return Actor
|
||||
*/
|
||||
function getPersonByID($ID)
|
||||
{
|
||||
$url = self::APIURL . '/people/' . $ID;
|
||||
$show = $this->getFile($url);
|
||||
return new Actor($show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of all the shows a particular actor has been in
|
||||
*
|
||||
* @param $ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getCastCreditsByID($ID)
|
||||
{
|
||||
$url = self::APIURL . '/people/' . $ID . '/castcredits?embed=show';
|
||||
$castCredit = $this->getFile($url);
|
||||
|
||||
$shows_appeared = array();
|
||||
foreach($castCredit as $series) {
|
||||
$TVShow = new TVShow($series['_embedded']['show']);
|
||||
array_push($shows_appeared, $TVShow);
|
||||
}
|
||||
return $shows_appeared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position worked at the tv show in a tuple with the tvshow
|
||||
*
|
||||
* @param $ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getCrewCreditsByID($ID)
|
||||
{
|
||||
$url = self::APIURL . '/people/' . $ID . '/crewcredits?embed=show';
|
||||
$crewCredit = $this->getFile($url);
|
||||
|
||||
$shows_appeared = array();
|
||||
foreach($crewCredit as $series) {
|
||||
$position = $series['type'];
|
||||
$TVShow = new TVShow($series['_embedded']['show']);
|
||||
array_push($shows_appeared, array($position, $TVShow));
|
||||
}
|
||||
return $shows_appeared;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to get the data from the URL and return the results in an array
|
||||
*
|
||||
* @param $url
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function getFile($url)
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
|
||||
$result = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$response = json_decode($result, TRUE);
|
||||
if (is_array($response) && count($response) > 0 && (!isset($response['status']) || $response['status'] != '404')) {
|
||||
return $response;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Creator: jpinkney
|
||||
* Date: 9/15/15
|
||||
* Time: 2:12 PM
|
||||
*/
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
/**
|
||||
* Class Crew
|
||||
*
|
||||
* @package JPinkney\TVMaze
|
||||
*/
|
||||
class Crew {
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* @param $crew_data
|
||||
*/
|
||||
function __construct($crew_data){
|
||||
$this->type = $crew_data['type'];
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: joshpinkney
|
||||
* Date: 9/15/15
|
||||
* Time: 2:13 PM
|
||||
*/
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
/**
|
||||
* Class Episode
|
||||
*
|
||||
* @package JPinkney\TVMaze
|
||||
*/
|
||||
class Episode extends TVProduction {
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $season;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $number;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $airdate;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $airtime;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $airstamp;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $runtime;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $summary;
|
||||
|
||||
/**
|
||||
* @param $episode_data
|
||||
*/
|
||||
function __construct($episode_data){
|
||||
parent::__construct($episode_data);
|
||||
$this->season = $episode_data['season'];
|
||||
$this->number = $episode_data['number'];
|
||||
$this->airdate = $episode_data['airdate'];
|
||||
$this->airtime = $episode_data['airtime'];
|
||||
$this->airstamp = $episode_data['airstamp'];
|
||||
$this->runtime = $episode_data['runtime'];
|
||||
$this->summary = strip_tags($episode_data['summary']);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Creator: joshpinkney
|
||||
* Date: 9/15/15
|
||||
* Time: 2:16 PM
|
||||
*/
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
/**
|
||||
* Class TVProduction
|
||||
*
|
||||
* @package JPinkney\TVMaze
|
||||
*/
|
||||
class TVProduction {
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $url;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $images;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $mediumImage;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $originalImage;
|
||||
|
||||
/**
|
||||
* @param $production_data
|
||||
*/
|
||||
function __construct($production_data){
|
||||
$this->id = $production_data['id'];
|
||||
$this->url = $production_data['url'];
|
||||
$this->name = $production_data['name'];
|
||||
$this->images = $production_data['image'];
|
||||
$this->mediumImage = $production_data['image']['medium'];
|
||||
$this->originalImage = $production_data['image']['original'];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -1,130 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: joshpinkney
|
||||
* Date: 9/15/15
|
||||
* Time: 2:16 PM
|
||||
*/
|
||||
|
||||
namespace libs\JPinkney\TVMaze;
|
||||
|
||||
//Check back here if we can move the episode data to the episode class later
|
||||
|
||||
/**
|
||||
* Class TVShow
|
||||
*
|
||||
* @package libs\JPinkney\TVMaze
|
||||
*/
|
||||
class TVShow extends TVProduction{
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $type;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $language;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $genres;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $status;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $runtime;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $premiered;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $rating;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $weight;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $network_array;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $network;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $webChannel;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $externalIDs;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $summary;
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $nextAirDate;
|
||||
/**
|
||||
* @var bool|string
|
||||
*/
|
||||
public $airTime;
|
||||
/**
|
||||
* @var bool|string
|
||||
*/
|
||||
public $airDay;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $country;
|
||||
|
||||
/**
|
||||
* @param $show_data
|
||||
*/
|
||||
function __construct($show_data){
|
||||
parent::__construct($show_data);
|
||||
$this->type = $show_data['type'];
|
||||
$this->language = $show_data['language'];
|
||||
$this->genres = $show_data['genres'];
|
||||
$this->status = $show_data['status'];
|
||||
$this->runtime = $show_data['runtime'];
|
||||
$this->premiered = $show_data['premiered'];
|
||||
$this->rating = $show_data['rating'];
|
||||
$this->weight = $show_data['weight'];
|
||||
$this->network_array = $show_data['network'];
|
||||
$this->network = $show_data['network']['name'];
|
||||
$this->country = $show_data['network']['country']['code'];
|
||||
if (count($show_data['webChannel']) > 0) {
|
||||
$this->country = $show_data['webChannel']['country']['code'];
|
||||
}
|
||||
$this->webChannel = $show_data['webChannel'];
|
||||
$this->externalIDs = $show_data['externals'];
|
||||
$this->summary = strip_tags($show_data['summary']);
|
||||
$this->akas = (isset($show_data['_embedded']['akas']) ? $show_data['_embedded']['akas'] : null);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* This function is used to check whether or not the object contains any data
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function isEmpty()
|
||||
{
|
||||
return($this->id == null || $this->id == 0 && $this->url == null && $this->name == null);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
/**
|
||||
* Actor object
|
||||
*
|
||||
* @package TvDb
|
||||
* @author Lucas Personnaz <lucas.personnaz@gmail.com>
|
||||
**/
|
||||
|
||||
class Actor
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $image;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $role;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $sortOrder;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \SimpleXMLElement $data A simplexml element created from thetvdb.com's xml data for the actor
|
||||
* @return \libs\Moinax\TvDb\Actor
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->id = (int)$data->id;
|
||||
$this->image = (string)$data->Image;
|
||||
$this->name = (string)$data->Name;
|
||||
$this->role = (string)$data->Role;
|
||||
$this->sortOrder = (int)$data->SortOrder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
/**
|
||||
* Simple banner object
|
||||
*
|
||||
* @package TvDb
|
||||
* @author Jérôme Poskin <moinax@gmail.com>
|
||||
*/
|
||||
class Banner
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $path = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $type = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $type2 = '';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $colors = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $language = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $rating = '';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $ratingCount = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $seriesName = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $thumbnailPath = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $vignettePath = '';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $season;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \SimpleXMLElement $data A simplexml element created from thetvdb.com's xml data for the tv serie banner
|
||||
* @return \libs\Moinax\TvDb\Banner
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->id = (int)$data->id;
|
||||
$this->path = (string)$data->BannerPath;
|
||||
$this->type = (string)$data->BannerType;
|
||||
$this->type2 = (string)$data->BannerType2;
|
||||
$this->colors = (array)$data->Colors;
|
||||
$this->language = (string)$data->Language;
|
||||
$this->rating = (string)$data->Rating;
|
||||
$this->ratingCount = (int)$data->RatingCount;
|
||||
$this->seriesName = (string)$data->SeriesName;
|
||||
$this->thumbnailPath = (string)$data->ThumbnailPath;
|
||||
$this->vignettePath = (string)$data->VignettePath;
|
||||
$this->season = (int)$data->Season;
|
||||
}
|
||||
}
|
||||
@@ -1,530 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
use libs\Moinax\TVDB\CurlException;
|
||||
use libs\Moinax\TVDB\Http\CurlClient;
|
||||
use libs\Moinax\TVDB\Http\HttpClient;
|
||||
|
||||
/**
|
||||
* Base TVDB library class, provides universal functions and variables
|
||||
*
|
||||
* @package TvDb
|
||||
* @author Jérôme Poskin <moinax@gmail.com>
|
||||
**/
|
||||
class Client
|
||||
{
|
||||
const POST = 'post';
|
||||
const GET = 'get';
|
||||
|
||||
const MIRROR_TYPE_XML = 1;
|
||||
const MIRROR_TYPE_BANNER = 2;
|
||||
const MIRROR_TYPE_ZIP = 4;
|
||||
|
||||
const DEFAULT_LANGUAGE = 'en';
|
||||
|
||||
const FORMAT_XML = 'xml';
|
||||
const FORMAT_ZIP = 'zip';
|
||||
|
||||
/**
|
||||
* Base url for TheTVDB
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $baseUrl = '';
|
||||
|
||||
/**
|
||||
* API key for thetvdb.com
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $apiKey = '';
|
||||
|
||||
/**
|
||||
* Array of available mirrors
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mirrors = array();
|
||||
|
||||
/**
|
||||
* Array of available languages
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $languages = array();
|
||||
|
||||
/**
|
||||
* Default language.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $defaultLanguage = 'en';
|
||||
|
||||
/**
|
||||
* HttpClient used to query the API.
|
||||
*
|
||||
* @var HttpClient
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
/**
|
||||
* @param string $baseUrl Domain name of the api without trailing slash
|
||||
* @param string $apiKey Api key provided by http://thetvdb.com
|
||||
*/
|
||||
public function __construct($baseUrl, $apiKey)
|
||||
{
|
||||
$this->baseUrl = $baseUrl;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->httpClient = new CurlClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HttpClient used to query the API.
|
||||
*
|
||||
* @param HttpClient $client
|
||||
*/
|
||||
public function setHttpClient(HttpClient $client)
|
||||
{
|
||||
$this->httpClient = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a language information
|
||||
*
|
||||
* @param string $abbreviation
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getLanguage($abbreviation)
|
||||
{
|
||||
if (empty($this->languages)) {
|
||||
$this->getLanguages();
|
||||
}
|
||||
if (!isset($this->languages[$abbreviation])) {
|
||||
throw new \Exception('This language is not available');
|
||||
}
|
||||
|
||||
return $this->languages[$abbreviation];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default query language. It must be a valid language code.
|
||||
*
|
||||
* @param string $language
|
||||
*/
|
||||
public function setDefaultLanguage($language) {
|
||||
$this->defaultLanguage = $language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default query language.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultLanguage() {
|
||||
return $this->defaultLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server time for further updates
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getServerTime()
|
||||
{
|
||||
return (string)$this->fetchXml('Updates.php?type=none')->Time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for tv serie based on series name
|
||||
*
|
||||
* @param string $seriesName
|
||||
* @param string $language
|
||||
* @return array
|
||||
*/
|
||||
public function getSeries($seriesName, $language = null)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
$data = $this->fetchXml('GetSeries.php?seriesname=' . urlencode($seriesName) . '&language=' . $language);
|
||||
$series = array();
|
||||
foreach ($data->Series as $serie) {
|
||||
$series[] = new Serie($serie);
|
||||
}
|
||||
return $series;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a tv serie by the id from thetvdb.com
|
||||
*
|
||||
* @var int $serieId
|
||||
* @var string $language
|
||||
*
|
||||
* @return Serie A serie object or false if not found
|
||||
**/
|
||||
public function getSerie($serieId, $language = null)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
$data = $this->fetchXml('series/' . $serieId . '/' . $language . '.xml');
|
||||
|
||||
return new Serie($data->Series);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a tv serie by a remote id
|
||||
*
|
||||
* @param array $remoteId
|
||||
* @param string $language
|
||||
*
|
||||
* @example <pre><code>$obj->getSerieByRemoteId(array('imdbid' => '<imdbid>'));</code></pre>
|
||||
* @example <pre><code>$obj->getSerieByRemoteId(array('zap2it' => '<zap2it>'));</code></pre>
|
||||
*
|
||||
* @return Serie
|
||||
*/
|
||||
public function getSerieByRemoteId(array $remoteId, $language = null)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
$data = $this->fetchXml('GetSeriesByRemoteID.php?' . http_build_query($remoteId) . '&language=' . $language);
|
||||
|
||||
return new Serie($data->Series);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all banners related to a serie
|
||||
*
|
||||
* @param int $serieId
|
||||
* @return string
|
||||
*/
|
||||
public function getBanners($serieId)
|
||||
{
|
||||
$data = $this->fetchXml('series/' . $serieId . '/banners.xml');
|
||||
$banners = array();
|
||||
foreach ($data->Banner as $banner) {
|
||||
$banners[] = new Banner($banner);
|
||||
}
|
||||
|
||||
return $banners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all actors related to a serie
|
||||
*
|
||||
* @param int $serieId
|
||||
* @return array
|
||||
*/
|
||||
public function getActors($serieId)
|
||||
{
|
||||
$data = $this->fetchXml('series/'. $serieId . '/actors.xml');
|
||||
$actors = array();
|
||||
foreach ($data->Actor as $actor) {
|
||||
$actors [] = new Actor($actor);
|
||||
}
|
||||
|
||||
return $actors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all episodes for a serie
|
||||
*
|
||||
* @param int $serieId
|
||||
* @param string $language
|
||||
* @param string $format
|
||||
* @return array
|
||||
* @throws \ErrorException
|
||||
*/
|
||||
public function getSerieEpisodes($serieId, $language = null, $format = self::FORMAT_XML)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
switch ($format) {
|
||||
case self::FORMAT_XML:
|
||||
$data = $this->fetchXml('series/' . $serieId . '/all/' . $language . '.' . $format);
|
||||
break;
|
||||
case self::FORMAT_ZIP:
|
||||
if (!in_array('zip', stream_get_wrappers())) {
|
||||
throw new \ErrorException('Your PHP does not support ZIP stream wrappers');
|
||||
}
|
||||
$data = $this->fetchZIP('series/' . $serieId . '/all/' . $language . '.' . $format, array(), self::GET, $language.".xml");
|
||||
break;
|
||||
default:
|
||||
throw new \ErrorException('Unsupported format');
|
||||
break;
|
||||
}
|
||||
$serie = new Serie($data->Series);
|
||||
$episodes = array();
|
||||
foreach ($data->Episode as $episode) {
|
||||
$episodes[(int)$episode->id] = new Episode($episode);
|
||||
}
|
||||
return array('serie' => $serie, 'episodes' => $episodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific episode by season and episode number
|
||||
*
|
||||
* @var int $serieId required the id of the serie
|
||||
* @var int $season required the season number
|
||||
* @var int $episode required the episode number
|
||||
* @var string $language language abbreviation
|
||||
*
|
||||
* @return Episode
|
||||
**/
|
||||
public function getEpisode($serieId, $season, $episode, $language = null)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
$data = $this->fetchXml('series/' . $serieId . '/default/' . $season . '/' . $episode . '/' . $language . '.xml');
|
||||
|
||||
return new Episode($data->Episode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific episode by his id
|
||||
*
|
||||
* @var int $episodeId required the id of the episode
|
||||
* @var string $language
|
||||
* @return Episode
|
||||
**/
|
||||
public function getEpisodeById($episodeId, $language = null)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
$data = $this->fetchXml('episodes/' . $episodeId . '/' . $language . '.xml');
|
||||
|
||||
return new Episode($data->Episode);
|
||||
}
|
||||
|
||||
/** nZEDb added
|
||||
* @param $serieId
|
||||
* @param $airdate
|
||||
* @param null $language
|
||||
*
|
||||
* @return Episode
|
||||
*/
|
||||
public function getEpisodeByAirDate($serieId, $airdate, $language = null)
|
||||
{
|
||||
$language = $language ? : $this->defaultLanguage;
|
||||
|
||||
$data = $this->fetchXml('GetEpisodeByAirDate.php?apikey=' . $this->apiKey . '&seriesid=' . $serieId . '&airdate=' . $airdate . '&language=' . $language );
|
||||
|
||||
return new Episode($data->Episode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get updates list based on previous time you got data
|
||||
*
|
||||
* @param int $previousTime
|
||||
* @return array
|
||||
*/
|
||||
public function getUpdates($previousTime)
|
||||
{
|
||||
$data = $this->fetchXml('Updates.php?type=all&time=' . $previousTime);
|
||||
|
||||
$series = array();
|
||||
foreach ($data->Series as $serieId) {
|
||||
$series[] = (int)$serieId;
|
||||
}
|
||||
$episodes = array();
|
||||
foreach ($data->Episode as $episodeId) {
|
||||
$episodes[] = (int)$episodeId;
|
||||
}
|
||||
return array('series' => $series, 'episodes' => $episodes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch banner raw jpeg data from banner mirror.
|
||||
*
|
||||
* @param string $banner the banner to fetch like graphical/79349-g7.jpg
|
||||
* @return string raw jpeg data
|
||||
*/
|
||||
public function fetchBanner($banner)
|
||||
{
|
||||
$url = $this->getMirror(self::MIRROR_TYPE_BANNER) . '/banners/' . $banner;
|
||||
return $this->httpClient->fetch($url, array(), self::GET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data via curl and returns result
|
||||
*
|
||||
* @access protected
|
||||
* @param string $function The function used to fetch data in xml
|
||||
* @param array $params
|
||||
* @param string $method
|
||||
* @return string The data
|
||||
*/
|
||||
protected function fetchXml($function, $params = array(), $method = self::GET)
|
||||
{
|
||||
if (strpos($function, '.php') > 0) { // no need of api key for php calls
|
||||
$url = $this->getMirror(self::MIRROR_TYPE_XML) . '/api/' . $function;
|
||||
} else {
|
||||
$url = $this->getMirror(self::MIRROR_TYPE_XML) . '/api/' . $this->apiKey . '/' . $function;
|
||||
}
|
||||
|
||||
$data = $this->httpClient->fetch($url, $params, $method);
|
||||
|
||||
$simpleXml = $this->getXml($data);
|
||||
|
||||
return $simpleXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches data via curl and returns result
|
||||
*
|
||||
* @access protected
|
||||
* @param string $function The function used to fetch data in zip
|
||||
* @param array $params
|
||||
* @param string $method
|
||||
* @param string $file The file to extract from the ZIP
|
||||
* @return string The data
|
||||
*/
|
||||
protected function fetchZIP($function, $params = array(), $method = self::GET, $file=null)
|
||||
{
|
||||
if (strpos($function, '.php') > 0) { // no need of api key for php calls
|
||||
$url = $this->getMirror(self::MIRROR_TYPE_ZIP) . '/api/' . $function;
|
||||
} else {
|
||||
$url = $this->getMirror(self::MIRROR_TYPE_ZIP) . '/api/' . $this->apiKey . '/' . $function;
|
||||
}
|
||||
|
||||
$zipName = tempnam(sys_get_temp_dir(), "tvdb-");
|
||||
$zip = fopen($zipName, "w");
|
||||
fwrite($zip, $this->httpClient->fetch($url, $params, $method));
|
||||
fclose($zip);
|
||||
if (is_null($file)) {
|
||||
$file = $this->getDefaultLanguage().".xml";
|
||||
}
|
||||
$dataPath = "zip://".$zipName."#".$file;
|
||||
$data = file_get_contents($dataPath);
|
||||
|
||||
$simpleXml = $this->getXml($data);
|
||||
|
||||
return $simpleXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data with curl
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $params
|
||||
* @param string $method
|
||||
* @throws CurlException
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function fetch($url, array $params = array(), $method = self::GET)
|
||||
{
|
||||
return $this->httpClient->fetch($url, $params, $method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert xml string to SimpleXMLElement
|
||||
*
|
||||
* @param string $data
|
||||
* @return \SimpleXMLElement
|
||||
* @throws \ErrorException|\Exception
|
||||
*/
|
||||
protected function getXml($data)
|
||||
{
|
||||
if (extension_loaded('libxml')) {
|
||||
libxml_use_internal_errors(true);
|
||||
}
|
||||
|
||||
$simpleXml = simplexml_load_string($data);
|
||||
if (!$simpleXml) {
|
||||
if (extension_loaded('libxml')) {
|
||||
$xmlErrors = libxml_get_errors();
|
||||
$errors = array();
|
||||
foreach ($xmlErrors as $error) {
|
||||
$errors[] = sprintf('Error in file %s on line %d with message : %s', $error->file, $error->line, $error->message);
|
||||
}
|
||||
if (count($errors) > 0) {
|
||||
|
||||
throw new XmlException(implode("\n", $errors));
|
||||
}
|
||||
}
|
||||
throw new XmlException('Xml file could not be loaded');
|
||||
}
|
||||
|
||||
return $simpleXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of mirrors available to fetchXml the data from the api
|
||||
* @return void
|
||||
*/
|
||||
protected function getMirrors()
|
||||
{
|
||||
$data = $this->httpClient->fetch($this->baseUrl . '/api/' . $this->apiKey . '/mirrors.xml');
|
||||
$mirrors = $this->getXml($data);
|
||||
|
||||
foreach ($mirrors->Mirror as $mirror) {
|
||||
$typeMask = (int)$mirror->typemask;
|
||||
$mirrorPath = (string)$mirror->mirrorpath;
|
||||
|
||||
if ($typeMask & self::MIRROR_TYPE_XML) {
|
||||
$this->mirrors[self::MIRROR_TYPE_XML][] = $mirrorPath;
|
||||
}
|
||||
if ($typeMask & self::MIRROR_TYPE_BANNER) {
|
||||
$this->mirrors[self::MIRROR_TYPE_BANNER][] = $mirrorPath;
|
||||
}
|
||||
if ($typeMask & self::MIRROR_TYPE_ZIP) {
|
||||
$this->mirrors[self::MIRROR_TYPE_ZIP][] = $mirrorPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random mirror from the list of available mirrors
|
||||
*
|
||||
* @param int $typeMask
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
public function getMirror($typeMask = self::MIRROR_TYPE_XML)
|
||||
{
|
||||
if (empty($this->mirrors)) {
|
||||
$this->getMirrors();
|
||||
}
|
||||
return $this->mirrors[$typeMask][array_rand($this->mirrors[$typeMask], 1)];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of languages available for the content of the api
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
protected function getLanguages()
|
||||
{
|
||||
$languages = $this->fetchXml('languages.xml');
|
||||
|
||||
foreach ($languages->Language as $language) {
|
||||
$this->languages[(string)$language->abbreviation] = array(
|
||||
'name' => (string)$language->name,
|
||||
'abbreviation' => (string)$language->abbreviation,
|
||||
'id' => (int)$language->id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes indexes from an array if they are zero length after trimming
|
||||
*
|
||||
* @param array $array The array to remove empty indexes from
|
||||
* @return array An array with all empty indexes removed
|
||||
**/
|
||||
public static function removeEmptyIndexes($array)
|
||||
{
|
||||
|
||||
$length = count($array);
|
||||
|
||||
for ($i = $length - 1; $i >= 0; $i--) {
|
||||
if (trim($array[$i]) == '') {
|
||||
unset($array[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
sort($array);
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
|
||||
class CurlException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
/**
|
||||
* Episode class. Class for single tv episode for a TV serie.
|
||||
*
|
||||
* @package TvDb
|
||||
* @author Jérôme Poskin <moinax@gmail.com>
|
||||
**/
|
||||
class Episode
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $number = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $season = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $directors = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $guestStars = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $writers = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $firstAired;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $imdbId = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $language = Client::DEFAULT_LANGUAGE;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $overview = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $rating = '';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $ratingCount = 0;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $lastUpdated;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $seasonId = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $serieId = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $thumbnail = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @return \libs\Moinax\TvDb\Episode
|
||||
* @param \SimpleXMLElement $data simplexml element created from thetvdb.com's xml data for the tv episode
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->id = (int)$data->id;
|
||||
$this->number = (int)$data->EpisodeNumber;
|
||||
$this->season = (int)$data->SeasonNumber;
|
||||
$this->directors = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Director));
|
||||
$this->name = (string)$data->EpisodeName;
|
||||
$this->firstAired = (string)$data->FirstAired !== '' ? (string)$data->FirstAired : null;
|
||||
$this->guestStars = Client::removeEmptyIndexes(explode('|', (string)$data->GuestStars));
|
||||
$this->imdbId = (string)$data->IMDB_ID;
|
||||
$this->language = (string) $data->Language;
|
||||
$this->overview = (string)$data->Overview;
|
||||
$this->rating = (string)$data->Rating;
|
||||
$this->ratingCount = (int)$data->RatingCount;
|
||||
$this->lastUpdated = \DateTime::createFromFormat('U', (int)$data->lastupdated);
|
||||
$this->writers = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Writer));
|
||||
$this->thumbnail = (string)$data->filename;
|
||||
$this->seasonId = (int)$data->seasonid;
|
||||
$this->serieId = (int)$data->seriesid;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
|
||||
class Exception extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB\Http\Cache;
|
||||
|
||||
interface Cache
|
||||
{
|
||||
|
||||
public function getDate($resource);
|
||||
|
||||
public function setDate($resource, $date);
|
||||
|
||||
public function cache($resource, $date, $content);
|
||||
|
||||
public function getContent($resource);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
namespace libs\Moinax\TVDB\Http\Cache;
|
||||
|
||||
class FilesystemCache implements Cache
|
||||
{
|
||||
|
||||
private $directory;
|
||||
|
||||
public function __construct($directory)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see \Moinax\TvDb\Http\Cache\Cache::getDate()
|
||||
*/
|
||||
public function getDate($resource)
|
||||
{
|
||||
$path = $this->getPath($resource);
|
||||
if(!file_exists($path)) {
|
||||
return -1;
|
||||
}
|
||||
return filemtime($path);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see \Moinax\TvDb\Http\Cache\Cache::setDate()
|
||||
*/
|
||||
public function setDate($resource, $date)
|
||||
{
|
||||
$path = $this->getPath($resource);
|
||||
|
||||
if(! file_exists($path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
touch($path, $date);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see \Moinax\TvDb\Http\Cache\Cache::cache()
|
||||
*/
|
||||
public function cache($resource, $date, $content)
|
||||
{
|
||||
$path = $this->getPath($resource);
|
||||
|
||||
$dirname = dirname($path);
|
||||
if(!is_dir($dirname)) {
|
||||
mkdir($dirname, 0777, true);
|
||||
}
|
||||
|
||||
file_put_contents($path, $content);
|
||||
$this->setDate($resource, $date);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see \Moinax\TvDb\Http\Cache\Cache::getContent()
|
||||
*/
|
||||
public function getContent($resource)
|
||||
{
|
||||
$path = $this->getPath($resource);
|
||||
|
||||
if(! file_exists($path)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return file_get_contents($path);
|
||||
}
|
||||
|
||||
private function getPath($resource) {
|
||||
return $this->directory . $resource;
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
<?php
|
||||
namespace libs\Moinax\TVDB\Http;
|
||||
|
||||
use libs\Moinax\TVDB\CurlException;
|
||||
use libs\Moinax\TVDB\Http\Cache\Cache;
|
||||
|
||||
class CacheClient implements HttpClient
|
||||
{
|
||||
|
||||
/**
|
||||
* Cache to store resources.
|
||||
*
|
||||
* @var Cache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* Minimum resource age before doing any request.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $ttl;
|
||||
|
||||
/**
|
||||
* Create a new HttpClient with caching features.
|
||||
*
|
||||
* @param Cache $cache
|
||||
* @param integer $ttl
|
||||
*/
|
||||
public function __construct(Cache $cache, $ttl)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
|
||||
$this->ttl = $ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see \Moinax\TvDb\Http\HttpClient::fetch()
|
||||
*/
|
||||
public function fetch($url, array $params = array(), $method = HttpClient::GET)
|
||||
{
|
||||
$ch = $this->curlInit($url, $params, $method);
|
||||
if($method == HttpClient::POST) {
|
||||
return $this->doPost($ch, $url);
|
||||
}
|
||||
return $this->doGet($ch, $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache time to live.
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
public function getTtl()
|
||||
{
|
||||
return $this->ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache time to live.
|
||||
*
|
||||
* @param integer $ttl
|
||||
*/
|
||||
public function setTtl($ttl)
|
||||
{
|
||||
$this->ttl = $ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a GET request.
|
||||
*
|
||||
* @param resource $ch
|
||||
* @param string $url
|
||||
* @throws CurlException
|
||||
* @return string
|
||||
*/
|
||||
private function doGet($ch, $url)
|
||||
{
|
||||
$now = time();
|
||||
$resource = $this->getResourceName($url);
|
||||
$date = $this->cache->getDate($resource);
|
||||
$limit = $now - $this->ttl;
|
||||
|
||||
//Return content if ttl has not yet expired.
|
||||
if($date > 0 && $date > $limit) {
|
||||
return $this->cache->getContent($resource);
|
||||
}
|
||||
|
||||
//Add the If-Modified-Since header
|
||||
if($date > 0) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
sprintf("If-Modified-Since: %s GMT", gmdate("D, d M Y H:i:s", $date)),
|
||||
));
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_FILETIME, true);
|
||||
|
||||
$data = $this->curlExec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$date = curl_getinfo($ch, CURLINFO_FILETIME);
|
||||
curl_close($ch);
|
||||
|
||||
//Return content from cache.
|
||||
if($httpCode == 304) {
|
||||
$this->cache->setDate($resource, $date);
|
||||
return $this->cache->getContent($resource);
|
||||
}
|
||||
|
||||
//Cache content
|
||||
if ($httpCode == 200) {
|
||||
$date = ($date >= 0) ? $date : $now;
|
||||
$this->cache->cache($resource, $date, $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
throw new CurlException(sprintf('Cannot fetch %s', $url), $httpCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a POST request.
|
||||
*
|
||||
* @param resource $ch
|
||||
* @param string $url
|
||||
* @throws CurlException
|
||||
* @return string
|
||||
*/
|
||||
private function doPost($ch, $url)
|
||||
{
|
||||
$data = $this->curlExec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode != 200) {
|
||||
throw new CurlException(sprintf('Cannot fetch %s', $url), $httpCode);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec the given cURL connection and return the content body.
|
||||
* @param resource $ch
|
||||
* @return string
|
||||
*/
|
||||
private function curlExec($ch)
|
||||
{
|
||||
$response = curl_exec($ch);
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
return substr($response, $headerSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a new cURL client.
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $params
|
||||
* @param string $method
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
private function curlInit($url, array $params, $method)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
|
||||
if ($method == HttpClient::POST) {
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
|
||||
}
|
||||
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource name from url removing the host part and the API key if provided.
|
||||
*
|
||||
* @param string $url
|
||||
* @return string
|
||||
*/
|
||||
private function getResourceName($url)
|
||||
{
|
||||
$url = parse_url($url);
|
||||
$extension = pathinfo($url['path'], PATHINFO_EXTENSION);
|
||||
|
||||
$resource = $url['path'];
|
||||
if(in_array($extension, array('xml', 'zip'))) {
|
||||
//Remove the api key from the resource name.
|
||||
$path = explode('/', $url['path']);
|
||||
unset($path[2]);
|
||||
$resource = implode('/', $path);
|
||||
}
|
||||
|
||||
if (!empty($url['query'])) {
|
||||
$resource .= '?' . $url['query'];
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
namespace libs\Moinax\TVDB\Http;
|
||||
|
||||
use libs\Moinax\TVDB\CurlException;
|
||||
|
||||
class CurlClient implements HttpClient
|
||||
{
|
||||
|
||||
/**
|
||||
* Fetch the given url contents using cURL library
|
||||
*
|
||||
* @see \Moinax\TvDb\Http\HttpClient::fetch()
|
||||
*/
|
||||
public function fetch($url, array $params = array(), $method = HttpClient::GET)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
|
||||
if ($method == HttpClient::POST) {
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
|
||||
}
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$data = substr($response, $headerSize);
|
||||
curl_close($ch);
|
||||
|
||||
if ($httpCode != 200) {
|
||||
throw new CurlException(sprintf('Cannot fetch %s', $url), $httpCode);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
namespace libs\Moinax\TVDB\Http;
|
||||
|
||||
interface HttpClient
|
||||
{
|
||||
|
||||
const POST = 'post';
|
||||
|
||||
const GET = 'get';
|
||||
|
||||
public function fetch($url, array $params = array(), $method = self::GET);
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
TvDb
|
||||
====
|
||||
|
||||
Based on the well known php library phptvdb (available on http://code.google.com/p/phptvdb/), this version
|
||||
has been completely refactored to offer more features from the tvdb api (available on http://www.thetvdb.com/wiki/index.php/Programmers_API)
|
||||
by using PHP 5.3 namespaces, very useful to import in a bigger project like Symfony 2 for example.
|
||||
|
||||
What does it do:
|
||||
----------------
|
||||
|
||||
The Client implements almost all api functions from thetvdb excepted the download in ZIP format
|
||||
|
||||
Usage:
|
||||
------
|
||||
|
||||
```php
|
||||
use Moinax\TvDb\Client;
|
||||
$apiKey = 'YOURAPIKEY';
|
||||
|
||||
$tvdb = new Client("http://thetvdb.com", $apiKey);
|
||||
$tvdb->getSerie(75710);
|
||||
```
|
||||
|
||||
Cache usage:
|
||||
------------
|
||||
|
||||
To save bandwidth, reduce latency, or both of two, you can use a Http Client with caching features.
|
||||
The HTTP client use the If-Modified-Since header to fetch full content only if resource was modified. This saves bandwidth.
|
||||
The HTTP client also use a time to live parameter to completly avoid making request if resource was fresh enough. This reduce latency.
|
||||
|
||||
```php
|
||||
<?php
|
||||
use Moinax\TvDb\Http\Cache\FilesystemCache;
|
||||
use Moinax\TvDb\Http\CacheClient;
|
||||
use Moinax\TvDb\Client;
|
||||
|
||||
$ttl = 600; # how long things should get cached, in seconds.
|
||||
$apiKey = 'YOURAPIKEY';
|
||||
|
||||
$cache = new FilesystemCache(__DIR__ . '/cache');
|
||||
$httpClient = new CacheClient($cache, $ttl);
|
||||
|
||||
$tvdb = new Client("http://thetvdb.com", $apiKey);
|
||||
$tvdb->setHttpClient($httpClient);
|
||||
|
||||
$tvdb->getSerie(75710); //This request will fetch the resource online.
|
||||
$tvdb->getSerie(75710); //Cache content is fresh enough. We don't make any request.
|
||||
sleep(600);
|
||||
$tvdb->getSerie(75710); //The content is not fresh enough. We make a request with
|
||||
//the If-Modified-Since header. The server respond 304 Not
|
||||
//modified, so we load content from the cache.
|
||||
```
|
||||
|
||||
|
||||
Examples:
|
||||
---------
|
||||
|
||||
Use the index.php to test the Api
|
||||
Rename the settings.php.dist in settings.php if you wan to test and enter your own API key provided by http://thetvdb.com
|
||||
|
||||
Status:
|
||||
-------
|
||||
This version is quite stable and used in production on http://nextepisode.tv
|
||||
@@ -1,172 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
/**
|
||||
* Serie object
|
||||
*
|
||||
* @package TvDb
|
||||
* @author Jérôme Poskin <moinax@gmail.com>
|
||||
*/
|
||||
class Serie
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $language;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $banner;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $overview;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $firstAired;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $imdbId;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $actors = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $airsDayOfWeek = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $airsTime = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $contentRating = '';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $genres = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $network = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $rating = '';
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $ratingCount = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $runtime = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $status = '';
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $added;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $addedBy;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $fanArt = '';
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $lastUpdated;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $poster = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $zap2ItId = '';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $aliasNames = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \SimpleXMLElement $data A simplexml element created from thetvdb.com's xml data for the tv show
|
||||
* @return \libs\Moinax\TvDb\Serie
|
||||
*/
|
||||
public function __construct($data)
|
||||
{
|
||||
$this->id = (int)$data->id;
|
||||
$this->language = (string)$data->Language;
|
||||
if(isset($data->language)) {
|
||||
$this->language = (string)$data->language;
|
||||
}
|
||||
$this->name = (string)$data->SeriesName;
|
||||
$this->banner = (string)$data->banner;
|
||||
$this->overview = (string)$data->Overview;
|
||||
$this->firstAired = (string)$data->FirstAired;
|
||||
$this->imdbId = (string)$data->IMDB_ID;
|
||||
$this->actors = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Actors));
|
||||
$this->airsDayOfWeek = (string)$data->Airs_DayOfWeek;
|
||||
$this->airsTime = (string)$data->Airs_Time;
|
||||
$this->contentRating = (string)$data->ContentRating;
|
||||
$this->genres = (array)Client::removeEmptyIndexes(explode('|', (string)$data->Genre));
|
||||
$this->network = (string)$data->Network;
|
||||
$this->rating = (string)$data->Rating;
|
||||
$this->ratingCount = (string)$data->RatingCount;
|
||||
$this->runtime = (int)$data->Runtime;
|
||||
$this->status = (string)$data->Status;
|
||||
$this->added = new \DateTime((string)$data->added);
|
||||
$this->addedBy = (int)$data->addedBy;
|
||||
$this->fanArt = (string)$data->fanart;
|
||||
$this->lastUpdated = \DateTime::createFromFormat('U', (int)$data->lastupdated);
|
||||
$this->poster = (string)$data->poster;
|
||||
$this->zap2ItId = (string)$data->zap2it_id;
|
||||
if(isset($data->AliasNames)) {
|
||||
$this->aliasNames = (array)Client::removeEmptyIndexes(explode('|', (string)$data->AliasNames));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace libs\Moinax\TVDB;
|
||||
|
||||
|
||||
class XmlException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* PHPMailer SPL autoloader.
|
||||
* PHP Version 5
|
||||
* @package PHPMailer
|
||||
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
* @author Brent R. Matzelle (original founder)
|
||||
* @copyright 2012 - 2014 Marcus Bointon
|
||||
* @copyright 2010 - 2012 Jim Jagielski
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* PHPMailer SPL autoloader.
|
||||
* @param string $classname The name of the class to load
|
||||
*/
|
||||
function PHPMailerAutoload($classname)
|
||||
{
|
||||
//Can't use __DIR__ as it's only in PHP 5.3+
|
||||
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
|
||||
if (is_readable($filename)) {
|
||||
require $filename;
|
||||
}
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
|
||||
//SPL autoloading was introduced in PHP 5.1.2
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
||||
spl_autoload_register('PHPMailerAutoload', true, true);
|
||||
} else {
|
||||
spl_autoload_register('PHPMailerAutoload');
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Fall back to traditional autoload for old PHP versions
|
||||
* @param string $classname The name of the class to load
|
||||
*/
|
||||
function __autoload($classname)
|
||||
{
|
||||
PHPMailerAutoload($classname);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
5.2.9
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,397 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* PHPMailer POP-Before-SMTP Authentication Class.
|
||||
* PHP Version 5
|
||||
* @package PHPMailer
|
||||
* @link https://github.com/PHPMailer/PHPMailer/
|
||||
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
* @author Brent R. Matzelle (original founder)
|
||||
* @copyright 2012 - 2014 Marcus Bointon
|
||||
* @copyright 2010 - 2012 Jim Jagielski
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* PHPMailer POP-Before-SMTP Authentication Class.
|
||||
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
|
||||
* Does not support APOP.
|
||||
* @package PHPMailer
|
||||
* @author Richard Davey (original author) <rich@corephp.co.uk>
|
||||
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
*/
|
||||
class POP3
|
||||
{
|
||||
/**
|
||||
* The POP3 PHPMailer Version number.
|
||||
* @type string
|
||||
* @access public
|
||||
*/
|
||||
public $Version = '5.2.9';
|
||||
|
||||
/**
|
||||
* Default POP3 port number.
|
||||
* @type integer
|
||||
* @access public
|
||||
*/
|
||||
public $POP3_PORT = 110;
|
||||
|
||||
/**
|
||||
* Default timeout in seconds.
|
||||
* @type integer
|
||||
* @access public
|
||||
*/
|
||||
public $POP3_TIMEOUT = 30;
|
||||
|
||||
/**
|
||||
* POP3 Carriage Return + Line Feed.
|
||||
* @type string
|
||||
* @access public
|
||||
* @deprecated Use the constant instead
|
||||
*/
|
||||
public $CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Debug display level.
|
||||
* Options: 0 = no, 1+ = yes
|
||||
* @type integer
|
||||
* @access public
|
||||
*/
|
||||
public $do_debug = 0;
|
||||
|
||||
/**
|
||||
* POP3 mail server hostname.
|
||||
* @type string
|
||||
* @access public
|
||||
*/
|
||||
public $host;
|
||||
|
||||
/**
|
||||
* POP3 port number.
|
||||
* @type integer
|
||||
* @access public
|
||||
*/
|
||||
public $port;
|
||||
|
||||
/**
|
||||
* POP3 Timeout Value in seconds.
|
||||
* @type integer
|
||||
* @access public
|
||||
*/
|
||||
public $tval;
|
||||
|
||||
/**
|
||||
* POP3 username
|
||||
* @type string
|
||||
* @access public
|
||||
*/
|
||||
public $username;
|
||||
|
||||
/**
|
||||
* POP3 password.
|
||||
* @type string
|
||||
* @access public
|
||||
*/
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* Resource handle for the POP3 connection socket.
|
||||
* @type resource
|
||||
* @access private
|
||||
*/
|
||||
private $pop_conn;
|
||||
|
||||
/**
|
||||
* Are we connected?
|
||||
* @type boolean
|
||||
* @access private
|
||||
*/
|
||||
private $connected = false;
|
||||
|
||||
/**
|
||||
* Error container.
|
||||
* @type array
|
||||
* @access private
|
||||
*/
|
||||
private $errors = array();
|
||||
|
||||
/**
|
||||
* Line break constant
|
||||
*/
|
||||
const CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Simple static wrapper for all-in-one POP before SMTP
|
||||
* @param $host
|
||||
* @param boolean $port
|
||||
* @param boolean $tval
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param integer $debug_level
|
||||
* @return boolean
|
||||
*/
|
||||
public static function popBeforeSmtp(
|
||||
$host,
|
||||
$port = false,
|
||||
$tval = false,
|
||||
$username = '',
|
||||
$password = '',
|
||||
$debug_level = 0
|
||||
) {
|
||||
$pop = new POP3;
|
||||
return $pop->authorise($host, $port, $tval, $username, $password, $debug_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate with a POP3 server.
|
||||
* A connect, login, disconnect sequence
|
||||
* appropriate for POP-before SMTP authorisation.
|
||||
* @access public
|
||||
* @param string $host The hostname to connect to
|
||||
* @param integer|boolean $port The port number to connect to
|
||||
* @param integer|boolean $timeout The timeout value
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param integer $debug_level
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
|
||||
{
|
||||
$this->host = $host;
|
||||
// If no port value provided, use default
|
||||
if (false === $port) {
|
||||
$this->port = $this->POP3_PORT;
|
||||
} else {
|
||||
$this->port = (integer)$port;
|
||||
}
|
||||
// If no timeout value provided, use default
|
||||
if (false === $timeout) {
|
||||
$this->tval = $this->POP3_TIMEOUT;
|
||||
} else {
|
||||
$this->tval = (integer)$timeout;
|
||||
}
|
||||
$this->do_debug = $debug_level;
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
// Reset the error log
|
||||
$this->errors = array();
|
||||
// connect
|
||||
$result = $this->connect($this->host, $this->port, $this->tval);
|
||||
if ($result) {
|
||||
$login_result = $this->login($this->username, $this->password);
|
||||
if ($login_result) {
|
||||
$this->disconnect();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// We need to disconnect regardless of whether the login succeeded
|
||||
$this->disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a POP3 server.
|
||||
* @access public
|
||||
* @param string $host
|
||||
* @param integer|boolean $port
|
||||
* @param integer $tval
|
||||
* @return boolean
|
||||
*/
|
||||
public function connect($host, $port = false, $tval = 30)
|
||||
{
|
||||
// Are we already connected?
|
||||
if ($this->connected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
|
||||
//Rather than suppress it with @fsockopen, capture it cleanly instead
|
||||
set_error_handler(array($this, 'catchWarning'));
|
||||
|
||||
if (false === $port) {
|
||||
$port = $this->POP3_PORT;
|
||||
}
|
||||
|
||||
// connect to the POP3 server
|
||||
$this->pop_conn = fsockopen(
|
||||
$host, // POP3 Host
|
||||
$port, // Port #
|
||||
$errno, // Error Number
|
||||
$errstr, // Error Message
|
||||
$tval
|
||||
); // Timeout (seconds)
|
||||
// Restore the error handler
|
||||
restore_error_handler();
|
||||
|
||||
// Did we connect?
|
||||
if (false === $this->pop_conn) {
|
||||
// It would appear not...
|
||||
$this->setError(array(
|
||||
'error' => "Failed to connect to server $host on port $port",
|
||||
'errno' => $errno,
|
||||
'errstr' => $errstr
|
||||
));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Increase the stream time-out
|
||||
stream_set_timeout($this->pop_conn, $tval, 0);
|
||||
|
||||
// Get the POP3 server response
|
||||
$pop3_response = $this->getResponse();
|
||||
// Check for the +OK
|
||||
if ($this->checkResponse($pop3_response)) {
|
||||
// The connection is established and the POP3 server is talking
|
||||
$this->connected = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log in to the POP3 server.
|
||||
* Does not support APOP (RFC 2828, 4949).
|
||||
* @access public
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return boolean
|
||||
*/
|
||||
public function login($username = '', $password = '')
|
||||
{
|
||||
if (!$this->connected) {
|
||||
$this->setError('Not connected to POP3 server');
|
||||
}
|
||||
if (empty($username)) {
|
||||
$username = $this->username;
|
||||
}
|
||||
if (empty($password)) {
|
||||
$password = $this->password;
|
||||
}
|
||||
|
||||
// Send the Username
|
||||
$this->sendString("USER $username" . self::CRLF);
|
||||
$pop3_response = $this->getResponse();
|
||||
if ($this->checkResponse($pop3_response)) {
|
||||
// Send the Password
|
||||
$this->sendString("PASS $password" . self::CRLF);
|
||||
$pop3_response = $this->getResponse();
|
||||
if ($this->checkResponse($pop3_response)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the POP3 server.
|
||||
* @access public
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->sendString('QUIT');
|
||||
//The QUIT command may cause the daemon to exit, which will kill our connection
|
||||
//So ignore errors here
|
||||
try {
|
||||
@fclose($this->pop_conn);
|
||||
} catch (Exception $e) {
|
||||
//Do nothing
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a response from the POP3 server.
|
||||
* $size is the maximum number of bytes to retrieve
|
||||
* @param integer $size
|
||||
* @return string
|
||||
* @access private
|
||||
*/
|
||||
private function getResponse($size = 128)
|
||||
{
|
||||
$response = fgets($this->pop_conn, $size);
|
||||
if ($this->do_debug >= 1) {
|
||||
echo "Server -> Client: $response";
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send raw data to the POP3 server.
|
||||
* @param string $string
|
||||
* @return integer
|
||||
* @access private
|
||||
*/
|
||||
private function sendString($string)
|
||||
{
|
||||
if ($this->pop_conn) {
|
||||
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
|
||||
echo "Client -> Server: $string";
|
||||
}
|
||||
return fwrite($this->pop_conn, $string, strlen($string));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the POP3 server response.
|
||||
* Looks for for +OK or -ERR.
|
||||
* @param string $string
|
||||
* @return boolean
|
||||
* @access private
|
||||
*/
|
||||
private function checkResponse($string)
|
||||
{
|
||||
if (substr($string, 0, 3) !== '+OK') {
|
||||
$this->setError(array(
|
||||
'error' => "Server reported an error: $string",
|
||||
'errno' => 0,
|
||||
'errstr' => ''
|
||||
));
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an error to the internal error store.
|
||||
* Also display debug output if it's enabled.
|
||||
* @param $error
|
||||
*/
|
||||
private function setError($error)
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
if ($this->do_debug >= 1) {
|
||||
echo '<pre>';
|
||||
foreach ($this->errors as $error) {
|
||||
print_r($error);
|
||||
}
|
||||
echo '</pre>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POP3 connection error handler.
|
||||
* @param integer $errno
|
||||
* @param string $errstr
|
||||
* @param string $errfile
|
||||
* @param integer $errline
|
||||
* @access private
|
||||
*/
|
||||
private function catchWarning($errno, $errstr, $errfile, $errline)
|
||||
{
|
||||
$this->setError(array(
|
||||
'error' => "Connecting to the POP3 server raised a PHP warning: ",
|
||||
'errno' => $errno,
|
||||
'errstr' => $errstr,
|
||||
'errfile' => $errfile,
|
||||
'errline' => $errline
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,974 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* PHPMailer RFC821 SMTP email transport class.
|
||||
* PHP Version 5
|
||||
* @package PHPMailer
|
||||
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
|
||||
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
|
||||
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
|
||||
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
|
||||
* @author Brent R. Matzelle (original founder)
|
||||
* @copyright 2014 Marcus Bointon
|
||||
* @copyright 2010 - 2012 Jim Jagielski
|
||||
* @copyright 2004 - 2009 Andy Prevost
|
||||
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
|
||||
* @note This program is distributed in the hope that it will be useful - WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* PHPMailer RFC821 SMTP email transport class.
|
||||
* Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server.
|
||||
* @package PHPMailer
|
||||
* @author Chris Ryan <unknown@example.com>
|
||||
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
|
||||
*/
|
||||
class SMTP
|
||||
{
|
||||
/**
|
||||
* The PHPMailer SMTP version number.
|
||||
* @type string
|
||||
*/
|
||||
const VERSION = '5.2.9';
|
||||
|
||||
/**
|
||||
* SMTP line break constant.
|
||||
* @type string
|
||||
*/
|
||||
const CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* The SMTP port to use if one is not specified.
|
||||
* @type integer
|
||||
*/
|
||||
const DEFAULT_SMTP_PORT = 25;
|
||||
|
||||
/**
|
||||
* The maximum line length allowed by RFC 2822 section 2.1.1
|
||||
* @type integer
|
||||
*/
|
||||
const MAX_LINE_LENGTH = 998;
|
||||
|
||||
/**
|
||||
* Debug level for no output
|
||||
*/
|
||||
const DEBUG_OFF = 0;
|
||||
|
||||
/**
|
||||
* Debug level to show client -> server messages
|
||||
*/
|
||||
const DEBUG_CLIENT = 1;
|
||||
|
||||
/**
|
||||
* Debug level to show client -> server and server -> client messages
|
||||
*/
|
||||
const DEBUG_SERVER = 2;
|
||||
|
||||
/**
|
||||
* Debug level to show connection status, client -> server and server -> client messages
|
||||
*/
|
||||
const DEBUG_CONNECTION = 3;
|
||||
|
||||
/**
|
||||
* Debug level to show all messages
|
||||
*/
|
||||
const DEBUG_LOWLEVEL = 4;
|
||||
|
||||
/**
|
||||
* The PHPMailer SMTP Version number.
|
||||
* @type string
|
||||
* @deprecated Use the `VERSION` constant instead
|
||||
* @see SMTP::VERSION
|
||||
*/
|
||||
public $Version = '5.2.9';
|
||||
|
||||
/**
|
||||
* SMTP server port number.
|
||||
* @type integer
|
||||
* @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead
|
||||
* @see SMTP::DEFAULT_SMTP_PORT
|
||||
*/
|
||||
public $SMTP_PORT = 25;
|
||||
|
||||
/**
|
||||
* SMTP reply line ending.
|
||||
* @type string
|
||||
* @deprecated Use the `CRLF` constant instead
|
||||
* @see SMTP::CRLF
|
||||
*/
|
||||
public $CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* Debug output level.
|
||||
* Options:
|
||||
* * self::DEBUG_OFF (`0`) No debug output, default
|
||||
* * self::DEBUG_CLIENT (`1`) Client commands
|
||||
* * self::DEBUG_SERVER (`2`) Client commands and server responses
|
||||
* * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status
|
||||
* * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages
|
||||
* @type integer
|
||||
*/
|
||||
public $do_debug = self::DEBUG_OFF;
|
||||
|
||||
/**
|
||||
* How to handle debug output.
|
||||
* Options:
|
||||
* * `echo` Output plain-text as-is, appropriate for CLI
|
||||
* * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
|
||||
* * `error_log` Output to error log as configured in php.ini
|
||||
*
|
||||
* Alternatively, you can provide a callable expecting two params: a message string and the debug level:
|
||||
* <code>
|
||||
* $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
|
||||
* </code>
|
||||
* @type string|callable
|
||||
*/
|
||||
public $Debugoutput = 'echo';
|
||||
|
||||
/**
|
||||
* Whether to use VERP.
|
||||
* @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
|
||||
* @link http://www.postfix.org/VERP_README.html Info on VERP
|
||||
* @type boolean
|
||||
*/
|
||||
public $do_verp = false;
|
||||
|
||||
/**
|
||||
* The timeout value for connection, in seconds.
|
||||
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
|
||||
* This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
|
||||
* @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
|
||||
* @type integer
|
||||
*/
|
||||
public $Timeout = 300;
|
||||
|
||||
/**
|
||||
* How long to wait for commands to complete, in seconds.
|
||||
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
|
||||
* @type integer
|
||||
*/
|
||||
public $Timelimit = 300;
|
||||
|
||||
/**
|
||||
* The socket for the server connection.
|
||||
* @type resource
|
||||
*/
|
||||
protected $smtp_conn;
|
||||
|
||||
/**
|
||||
* Error message, if any, for the last call.
|
||||
* @type array
|
||||
*/
|
||||
protected $error = array();
|
||||
|
||||
/**
|
||||
* The reply the server sent to us for HELO.
|
||||
* If null, no HELO string has yet been received.
|
||||
* @type string|null
|
||||
*/
|
||||
protected $helo_rply = null;
|
||||
|
||||
/**
|
||||
* The most recent reply received from the server.
|
||||
* @type string
|
||||
*/
|
||||
protected $last_reply = '';
|
||||
|
||||
/**
|
||||
* Output debugging info via a user-selected method.
|
||||
* @see SMTP::$Debugoutput
|
||||
* @see SMTP::$do_debug
|
||||
* @param string $str Debug string to output
|
||||
* @param integer $level The debug level of this message; see DEBUG_* constants
|
||||
* @return void
|
||||
*/
|
||||
protected function edebug($str, $level = 0)
|
||||
{
|
||||
if ($level > $this->do_debug) {
|
||||
return;
|
||||
}
|
||||
//Avoid clash with built-in function names
|
||||
if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
|
||||
call_user_func($this->Debugoutput, $str, $this->do_debug);
|
||||
return;
|
||||
}
|
||||
switch ($this->Debugoutput) {
|
||||
case 'error_log':
|
||||
//Don't output, just log
|
||||
error_log($str);
|
||||
break;
|
||||
case 'html':
|
||||
//Cleans up output a bit for a better looking, HTML-safe output
|
||||
echo htmlentities(
|
||||
preg_replace('/[\r\n]+/', '', $str),
|
||||
ENT_QUOTES,
|
||||
'UTF-8'
|
||||
)
|
||||
. "<br>\n";
|
||||
break;
|
||||
case 'echo':
|
||||
default:
|
||||
//Normalize line breaks
|
||||
$str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
|
||||
echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
|
||||
"\n",
|
||||
"\n \t ",
|
||||
trim($str)
|
||||
)."\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to an SMTP server.
|
||||
* @param string $host SMTP server IP or host name
|
||||
* @param integer $port The port number to connect to
|
||||
* @param integer $timeout How long to wait for the connection to open
|
||||
* @param array $options An array of options for stream_context_create()
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function connect($host, $port = null, $timeout = 30, $options = array())
|
||||
{
|
||||
static $streamok;
|
||||
//This is enabled by default since 5.0.0 but some providers disable it
|
||||
//Check this once and cache the result
|
||||
if (is_null($streamok)) {
|
||||
$streamok = function_exists('stream_socket_client');
|
||||
}
|
||||
// Clear errors to avoid confusion
|
||||
$this->error = array();
|
||||
// Make sure we are __not__ connected
|
||||
if ($this->connected()) {
|
||||
// Already connected, generate error
|
||||
$this->error = array('error' => 'Already connected to a server');
|
||||
return false;
|
||||
}
|
||||
if (empty($port)) {
|
||||
$port = self::DEFAULT_SMTP_PORT;
|
||||
}
|
||||
// Connect to the SMTP server
|
||||
$this->edebug(
|
||||
"Connection: opening to $host:$port, t=$timeout, opt=".var_export($options, true),
|
||||
self::DEBUG_CONNECTION
|
||||
);
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
if ($streamok) {
|
||||
$socket_context = stream_context_create($options);
|
||||
//Suppress errors; connection failures are handled at a higher level
|
||||
$this->smtp_conn = @stream_socket_client(
|
||||
$host . ":" . $port,
|
||||
$errno,
|
||||
$errstr,
|
||||
$timeout,
|
||||
STREAM_CLIENT_CONNECT,
|
||||
$socket_context
|
||||
);
|
||||
} else {
|
||||
//Fall back to fsockopen which should work in more places, but is missing some features
|
||||
$this->edebug(
|
||||
"Connection: stream_socket_client not available, falling back to fsockopen",
|
||||
self::DEBUG_CONNECTION
|
||||
);
|
||||
$this->smtp_conn = fsockopen(
|
||||
$host,
|
||||
$port,
|
||||
$errno,
|
||||
$errstr,
|
||||
$timeout
|
||||
);
|
||||
}
|
||||
// Verify we connected properly
|
||||
if (!is_resource($this->smtp_conn)) {
|
||||
$this->error = array(
|
||||
'error' => 'Failed to connect to server',
|
||||
'errno' => $errno,
|
||||
'errstr' => $errstr
|
||||
);
|
||||
$this->edebug(
|
||||
'SMTP ERROR: ' . $this->error['error']
|
||||
. ": $errstr ($errno)",
|
||||
self::DEBUG_CLIENT
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
|
||||
// SMTP server can take longer to respond, give longer timeout for first read
|
||||
// Windows does not have support for this timeout function
|
||||
if (substr(PHP_OS, 0, 3) != 'WIN') {
|
||||
$max = ini_get('max_execution_time');
|
||||
if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
|
||||
@set_time_limit($timeout);
|
||||
}
|
||||
stream_set_timeout($this->smtp_conn, $timeout, 0);
|
||||
}
|
||||
// Get any announcement
|
||||
$announce = $this->get_lines();
|
||||
$this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a TLS (encrypted) session.
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function startTLS()
|
||||
{
|
||||
if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
|
||||
return false;
|
||||
}
|
||||
// Begin encrypted connection
|
||||
if (!stream_socket_enable_crypto(
|
||||
$this->smtp_conn,
|
||||
true,
|
||||
STREAM_CRYPTO_METHOD_TLS_CLIENT
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform SMTP authentication.
|
||||
* Must be run after hello().
|
||||
* @see hello()
|
||||
* @param string $username The user name
|
||||
* @param string $password The password
|
||||
* @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)
|
||||
* @param string $realm The auth realm for NTLM
|
||||
* @param string $workstation The auth workstation for NTLM
|
||||
* @access public
|
||||
* @return boolean True if successfully authenticated.
|
||||
*/
|
||||
public function authenticate(
|
||||
$username,
|
||||
$password,
|
||||
$authtype = 'LOGIN',
|
||||
$realm = '',
|
||||
$workstation = ''
|
||||
) {
|
||||
if (empty($authtype)) {
|
||||
$authtype = 'LOGIN';
|
||||
}
|
||||
switch ($authtype) {
|
||||
case 'PLAIN':
|
||||
// Start authentication
|
||||
if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
|
||||
return false;
|
||||
}
|
||||
// Send encoded username and password
|
||||
if (!$this->sendCommand(
|
||||
'User & Password',
|
||||
base64_encode("\0" . $username . "\0" . $password),
|
||||
235
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'LOGIN':
|
||||
// Start authentication
|
||||
if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->sendCommand("Username", base64_encode($username), 334)) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->sendCommand("Password", base64_encode($password), 235)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'NTLM':
|
||||
/*
|
||||
* ntlm_sasl_client.php
|
||||
* Bundled with Permission
|
||||
*
|
||||
* How to telnet in windows:
|
||||
* http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
|
||||
* PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
|
||||
*/
|
||||
require_once 'extras/ntlm_sasl_client.php';
|
||||
$temp = new stdClass();
|
||||
$ntlm_client = new ntlm_sasl_client_class;
|
||||
//Check that functions are available
|
||||
if (!$ntlm_client->Initialize($temp)) {
|
||||
$this->error = array('error' => $temp->error);
|
||||
$this->edebug(
|
||||
'You need to enable some modules in your php.ini file: '
|
||||
. $this->error['error'],
|
||||
self::DEBUG_CLIENT
|
||||
);
|
||||
return false;
|
||||
}
|
||||
//msg1
|
||||
$msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
|
||||
|
||||
if (!$this->sendCommand(
|
||||
'AUTH NTLM',
|
||||
'AUTH NTLM ' . base64_encode($msg1),
|
||||
334
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
//Though 0 based, there is a white space after the 3 digit number
|
||||
//msg2
|
||||
$challenge = substr($this->last_reply, 3);
|
||||
$challenge = base64_decode($challenge);
|
||||
$ntlm_res = $ntlm_client->NTLMResponse(
|
||||
substr($challenge, 24, 8),
|
||||
$password
|
||||
);
|
||||
//msg3
|
||||
$msg3 = $ntlm_client->TypeMsg3(
|
||||
$ntlm_res,
|
||||
$username,
|
||||
$realm,
|
||||
$workstation
|
||||
);
|
||||
// send encoded username
|
||||
return $this->sendCommand('Username', base64_encode($msg3), 235);
|
||||
case 'CRAM-MD5':
|
||||
// Start authentication
|
||||
if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
|
||||
return false;
|
||||
}
|
||||
// Get the challenge
|
||||
$challenge = base64_decode(substr($this->last_reply, 4));
|
||||
|
||||
// Build the response
|
||||
$response = $username . ' ' . $this->hmac($challenge, $password);
|
||||
|
||||
// send encoded credentials
|
||||
return $this->sendCommand('Username', base64_encode($response), 235);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate an MD5 HMAC hash.
|
||||
* Works like hash_hmac('md5', $data, $key)
|
||||
* in case that function is not available
|
||||
* @param string $data The data to hash
|
||||
* @param string $key The key to hash with
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function hmac($data, $key)
|
||||
{
|
||||
if (function_exists('hash_hmac')) {
|
||||
return hash_hmac('md5', $data, $key);
|
||||
}
|
||||
|
||||
// The following borrowed from
|
||||
// http://php.net/manual/en/function.mhash.php#27225
|
||||
|
||||
// RFC 2104 HMAC implementation for php.
|
||||
// Creates an md5 HMAC.
|
||||
// Eliminates the need to install mhash to compute a HMAC
|
||||
// by Lance Rushing
|
||||
|
||||
$bytelen = 64; // byte length for md5
|
||||
if (strlen($key) > $bytelen) {
|
||||
$key = pack('H*', md5($key));
|
||||
}
|
||||
$key = str_pad($key, $bytelen, chr(0x00));
|
||||
$ipad = str_pad('', $bytelen, chr(0x36));
|
||||
$opad = str_pad('', $bytelen, chr(0x5c));
|
||||
$k_ipad = $key ^ $ipad;
|
||||
$k_opad = $key ^ $opad;
|
||||
|
||||
return md5($k_opad . pack('H*', md5($k_ipad . $data)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check connection state.
|
||||
* @access public
|
||||
* @return boolean True if connected.
|
||||
*/
|
||||
public function connected()
|
||||
{
|
||||
if (is_resource($this->smtp_conn)) {
|
||||
$sock_status = stream_get_meta_data($this->smtp_conn);
|
||||
if ($sock_status['eof']) {
|
||||
// The socket is valid but we are not connected
|
||||
$this->edebug(
|
||||
'SMTP NOTICE: EOF caught while checking if connected',
|
||||
self::DEBUG_CLIENT
|
||||
);
|
||||
$this->close();
|
||||
return false;
|
||||
}
|
||||
return true; // everything looks good
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the socket and clean up the state of the class.
|
||||
* Don't use this function without first trying to use QUIT.
|
||||
* @see quit()
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->error = array();
|
||||
$this->helo_rply = null;
|
||||
if (is_resource($this->smtp_conn)) {
|
||||
// close the connection and cleanup
|
||||
fclose($this->smtp_conn);
|
||||
$this->smtp_conn = null; //Makes for cleaner serialization
|
||||
$this->edebug('Connection: closed', self::DEBUG_CONNECTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP DATA command.
|
||||
* Issues a data command and sends the msg_data to the server,
|
||||
* finializing the mail transaction. $msg_data is the message
|
||||
* that is to be send with the headers. Each header needs to be
|
||||
* on a single line followed by a <CRLF> with the message headers
|
||||
* and the message body being separated by and additional <CRLF>.
|
||||
* Implements rfc 821: DATA <CRLF>
|
||||
* @param string $msg_data Message data to send
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function data($msg_data)
|
||||
{
|
||||
//This will use the standard timelimit
|
||||
if (!$this->sendCommand('DATA', 'DATA', 354)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The server is ready to accept data!
|
||||
* According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF)
|
||||
* so we will break the data up into lines by \r and/or \n then if needed we will break each of those into
|
||||
* smaller lines to fit within the limit.
|
||||
* We will also look for lines that start with a '.' and prepend an additional '.'.
|
||||
* NOTE: this does not count towards line-length limit.
|
||||
*/
|
||||
|
||||
// Normalize line breaks before exploding
|
||||
$lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data));
|
||||
|
||||
/* To distinguish between a complete RFC822 message and a plain message body, we check if the first field
|
||||
* of the first line (':' separated) does not contain a space then it _should_ be a header and we will
|
||||
* process all lines before a blank line as headers.
|
||||
*/
|
||||
|
||||
$field = substr($lines[0], 0, strpos($lines[0], ':'));
|
||||
$in_headers = false;
|
||||
if (!empty($field) && strpos($field, ' ') === false) {
|
||||
$in_headers = true;
|
||||
}
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$lines_out = array();
|
||||
if ($in_headers and $line == '') {
|
||||
$in_headers = false;
|
||||
}
|
||||
//We need to break this line up into several smaller lines
|
||||
//This is a small micro-optimisation: isset($str[$len]) is equivalent to (strlen($str) > $len)
|
||||
while (isset($line[self::MAX_LINE_LENGTH])) {
|
||||
//Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on
|
||||
//so as to avoid breaking in the middle of a word
|
||||
$pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
|
||||
if (!$pos) { //Deliberately matches both false and 0
|
||||
//No nice break found, add a hard break
|
||||
$pos = self::MAX_LINE_LENGTH - 1;
|
||||
$lines_out[] = substr($line, 0, $pos);
|
||||
$line = substr($line, $pos);
|
||||
} else {
|
||||
//Break at the found point
|
||||
$lines_out[] = substr($line, 0, $pos);
|
||||
//Move along by the amount we dealt with
|
||||
$line = substr($line, $pos + 1);
|
||||
}
|
||||
//If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1
|
||||
if ($in_headers) {
|
||||
$line = "\t" . $line;
|
||||
}
|
||||
}
|
||||
$lines_out[] = $line;
|
||||
|
||||
//Send the lines to the server
|
||||
foreach ($lines_out as $line_out) {
|
||||
//RFC2821 section 4.5.2
|
||||
if (!empty($line_out) and $line_out[0] == '.') {
|
||||
$line_out = '.' . $line_out;
|
||||
}
|
||||
$this->client_send($line_out . self::CRLF);
|
||||
}
|
||||
}
|
||||
|
||||
//Message data has been sent, complete the command
|
||||
//Increase timelimit for end of DATA command
|
||||
$savetimelimit = $this->Timelimit;
|
||||
$this->Timelimit = $this->Timelimit * 2;
|
||||
$result = $this->sendCommand('DATA END', '.', 250);
|
||||
//Restore timelimit
|
||||
$this->Timelimit = $savetimelimit;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP HELO or EHLO command.
|
||||
* Used to identify the sending server to the receiving server.
|
||||
* This makes sure that client and server are in a known state.
|
||||
* Implements RFC 821: HELO <SP> <domain> <CRLF>
|
||||
* and RFC 2821 EHLO.
|
||||
* @param string $host The host name or IP to connect to
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function hello($host = '')
|
||||
{
|
||||
//Try extended hello first (RFC 2821)
|
||||
return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP HELO or EHLO command.
|
||||
* Low-level implementation used by hello()
|
||||
* @see hello()
|
||||
* @param string $hello The HELO string
|
||||
* @param string $host The hostname to say we are
|
||||
* @access protected
|
||||
* @return boolean
|
||||
*/
|
||||
protected function sendHello($hello, $host)
|
||||
{
|
||||
$noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
|
||||
$this->helo_rply = $this->last_reply;
|
||||
return $noerror;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP MAIL command.
|
||||
* Starts a mail transaction from the email address specified in
|
||||
* $from. Returns true if successful or false otherwise. If True
|
||||
* the mail transaction is started and then one or more recipient
|
||||
* commands may be called followed by a data command.
|
||||
* Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
|
||||
* @param string $from Source address of this message
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function mail($from)
|
||||
{
|
||||
$useVerp = ($this->do_verp ? ' XVERP' : '');
|
||||
return $this->sendCommand(
|
||||
'MAIL FROM',
|
||||
'MAIL FROM:<' . $from . '>' . $useVerp,
|
||||
250
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP QUIT command.
|
||||
* Closes the socket if there is no error or the $close_on_error argument is true.
|
||||
* Implements from rfc 821: QUIT <CRLF>
|
||||
* @param boolean $close_on_error Should the connection close if an error occurs?
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function quit($close_on_error = true)
|
||||
{
|
||||
$noerror = $this->sendCommand('QUIT', 'QUIT', 221);
|
||||
$err = $this->error; //Save any error
|
||||
if ($noerror or $close_on_error) {
|
||||
$this->close();
|
||||
$this->error = $err; //Restore any error from the quit command
|
||||
}
|
||||
return $noerror;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP RCPT command.
|
||||
* Sets the TO argument to $toaddr.
|
||||
* Returns true if the recipient was accepted false if it was rejected.
|
||||
* Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
|
||||
* @param string $toaddr The address the message is being sent to
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function recipient($toaddr)
|
||||
{
|
||||
return $this->sendCommand(
|
||||
'RCPT TO',
|
||||
'RCPT TO:<' . $toaddr . '>',
|
||||
array(250, 251)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP RSET command.
|
||||
* Abort any transaction that is currently in progress.
|
||||
* Implements rfc 821: RSET <CRLF>
|
||||
* @access public
|
||||
* @return boolean True on success.
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
return $this->sendCommand('RSET', 'RSET', 250);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to an SMTP server and check its return code.
|
||||
* @param string $command The command name - not sent to the server
|
||||
* @param string $commandstring The actual command to send
|
||||
* @param integer|array $expect One or more expected integer success codes
|
||||
* @access protected
|
||||
* @return boolean True on success.
|
||||
*/
|
||||
protected function sendCommand($command, $commandstring, $expect)
|
||||
{
|
||||
if (!$this->connected()) {
|
||||
$this->error = array(
|
||||
'error' => "Called $command without being connected"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$this->client_send($commandstring . self::CRLF);
|
||||
|
||||
$this->last_reply = $this->get_lines();
|
||||
$code = substr($this->last_reply, 0, 3);
|
||||
|
||||
$this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
|
||||
|
||||
if (!in_array($code, (array)$expect)) {
|
||||
$this->error = array(
|
||||
'error' => "$command command failed",
|
||||
'smtp_code' => $code,
|
||||
'detail' => substr($this->last_reply, 4)
|
||||
);
|
||||
$this->edebug(
|
||||
'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply,
|
||||
self::DEBUG_CLIENT
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->error = array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP SAML command.
|
||||
* Starts a mail transaction from the email address specified in $from.
|
||||
* Returns true if successful or false otherwise. If True
|
||||
* the mail transaction is started and then one or more recipient
|
||||
* commands may be called followed by a data command. This command
|
||||
* will send the message to the users terminal if they are logged
|
||||
* in and send them an email.
|
||||
* Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
|
||||
* @param string $from The address the message is from
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendAndMail($from)
|
||||
{
|
||||
return $this->sendCommand('SAML', "SAML FROM:$from", 250);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP VRFY command.
|
||||
* @param string $name The name to verify
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function verify($name)
|
||||
{
|
||||
return $this->sendCommand('VRFY', "VRFY $name", array(250, 251));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP NOOP command.
|
||||
* Used to keep keep-alives alive, doesn't actually do anything
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
return $this->sendCommand('NOOP', 'NOOP', 250);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP TURN command.
|
||||
* This is an optional command for SMTP that this class does not support.
|
||||
* This method is here to make the RFC821 Definition complete for this class
|
||||
* and _may_ be implemented in future
|
||||
* Implements from rfc 821: TURN <CRLF>
|
||||
* @access public
|
||||
* @return boolean
|
||||
*/
|
||||
public function turn()
|
||||
{
|
||||
$this->error = array(
|
||||
'error' => 'The SMTP TURN command is not implemented'
|
||||
);
|
||||
$this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send raw data to the server.
|
||||
* @param string $data The data to send
|
||||
* @access public
|
||||
* @return integer|boolean The number of bytes sent to the server or false on error
|
||||
*/
|
||||
public function client_send($data)
|
||||
{
|
||||
$this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT);
|
||||
return fwrite($this->smtp_conn, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest error.
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last reply from the server.
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getLastReply()
|
||||
{
|
||||
return $this->last_reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the SMTP server's response.
|
||||
* Either before eof or socket timeout occurs on the operation.
|
||||
* With SMTP we can tell if we have more lines to read if the
|
||||
* 4th character is '-' symbol. If it is a space then we don't
|
||||
* need to read anything else.
|
||||
* @access protected
|
||||
* @return string
|
||||
*/
|
||||
protected function get_lines()
|
||||
{
|
||||
// If the connection is bad, give up straight away
|
||||
if (!is_resource($this->smtp_conn)) {
|
||||
return '';
|
||||
}
|
||||
$data = '';
|
||||
$endtime = 0;
|
||||
stream_set_timeout($this->smtp_conn, $this->Timeout);
|
||||
if ($this->Timelimit > 0) {
|
||||
$endtime = time() + $this->Timelimit;
|
||||
}
|
||||
while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
|
||||
$str = @fgets($this->smtp_conn, 515);
|
||||
$this->edebug("SMTP -> get_lines(): \$data was \"$data\"", self::DEBUG_LOWLEVEL);
|
||||
$this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL);
|
||||
$data .= $str;
|
||||
$this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
|
||||
// If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen
|
||||
if ((isset($str[3]) and $str[3] == ' ')) {
|
||||
break;
|
||||
}
|
||||
// Timed-out? Log and break
|
||||
$info = stream_get_meta_data($this->smtp_conn);
|
||||
if ($info['timed_out']) {
|
||||
$this->edebug(
|
||||
'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
|
||||
self::DEBUG_LOWLEVEL
|
||||
);
|
||||
break;
|
||||
}
|
||||
// Now check if reads took too long
|
||||
if ($endtime and time() > $endtime) {
|
||||
$this->edebug(
|
||||
'SMTP -> get_lines(): timelimit reached ('.
|
||||
$this->Timelimit . ' sec)',
|
||||
self::DEBUG_LOWLEVEL
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable VERP address generation.
|
||||
* @param boolean $enabled
|
||||
*/
|
||||
public function setVerp($enabled = false)
|
||||
{
|
||||
$this->do_verp = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get VERP address generation mode.
|
||||
* @return boolean
|
||||
*/
|
||||
public function getVerp()
|
||||
{
|
||||
return $this->do_verp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug output method.
|
||||
* @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it.
|
||||
*/
|
||||
public function setDebugOutput($method = 'echo')
|
||||
{
|
||||
$this->Debugoutput = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get debug output method.
|
||||
* @return string
|
||||
*/
|
||||
public function getDebugOutput()
|
||||
{
|
||||
return $this->Debugoutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug output level.
|
||||
* @param integer $level
|
||||
*/
|
||||
public function setDebugLevel($level = 0)
|
||||
{
|
||||
$this->do_debug = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get debug output level.
|
||||
* @return integer
|
||||
*/
|
||||
public function getDebugLevel()
|
||||
{
|
||||
return $this->do_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SMTP timeout.
|
||||
* @param integer $timeout
|
||||
*/
|
||||
public function setTimeout($timeout = 0)
|
||||
{
|
||||
$this->Timeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SMTP timeout.
|
||||
* @return integer
|
||||
*/
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->Timeout;
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* EasyPeasyICS
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Manuel Reinhard, manu@sprain.ch
|
||||
/* Twitter: @sprain
|
||||
/* Web: www.sprain.ch
|
||||
/*
|
||||
/* Built with inspiration by
|
||||
/" http://stackoverflow.com/questions/1463480/how-can-i-use-php-to-dynamically-publish-an-ical-file-to-be-read-by-google-calend/1464355#1464355
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* History:
|
||||
/* 2010/12/17 - Manuel Reinhard - when it all started
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
class EasyPeasyICS {
|
||||
|
||||
protected $calendarName;
|
||||
protected $events = array();
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param string $calendarName
|
||||
*/
|
||||
public function __construct($calendarName=""){
|
||||
$this->calendarName = $calendarName;
|
||||
}//function
|
||||
|
||||
|
||||
/**
|
||||
* Add event to calendar
|
||||
* @param string $calendarName
|
||||
*/
|
||||
public function addEvent($start, $end, $summary="", $description="", $url=""){
|
||||
$this->events[] = array(
|
||||
"start" => $start,
|
||||
"end" => $end,
|
||||
"summary" => $summary,
|
||||
"description" => $description,
|
||||
"url" => $url
|
||||
);
|
||||
}//function
|
||||
|
||||
|
||||
public function render($output = true){
|
||||
|
||||
//start Variable
|
||||
$ics = "";
|
||||
|
||||
//Add header
|
||||
$ics .= "BEGIN:VCALENDAR
|
||||
METHOD:PUBLISH
|
||||
VERSION:2.0
|
||||
X-WR-CALNAME:".$this->calendarName."
|
||||
PRODID:-//hacksw/handcal//NONSGML v1.0//EN";
|
||||
|
||||
//Add events
|
||||
foreach($this->events as $event){
|
||||
$ics .= "
|
||||
BEGIN:VEVENT
|
||||
UID:". md5(uniqid(mt_rand(), true)) ."@EasyPeasyICS.php
|
||||
DTSTAMP:" . gmdate('Ymd').'T'. gmdate('His') . "Z
|
||||
DTSTART:".gmdate('Ymd', $event["start"])."T".gmdate('His', $event["start"])."Z
|
||||
DTEND:".gmdate('Ymd', $event["end"])."T".gmdate('His', $event["end"])."Z
|
||||
SUMMARY:".str_replace("\n", "\\n", $event['summary'])."
|
||||
DESCRIPTION:".str_replace("\n", "\\n", $event['description'])."
|
||||
URL;VALUE=URI:".$event['url']."
|
||||
END:VEVENT";
|
||||
}//foreach
|
||||
|
||||
|
||||
//Footer
|
||||
$ics .= "
|
||||
END:VCALENDAR";
|
||||
|
||||
|
||||
if ($output) {
|
||||
//Output
|
||||
header('Content-type: text/calendar; charset=utf-8');
|
||||
header('Content-Disposition: inline; filename='.$this->calendarName.'.ics');
|
||||
echo $ics;
|
||||
} else {
|
||||
return $ics;
|
||||
}
|
||||
|
||||
}//function
|
||||
|
||||
}//class
|
||||
@@ -1,21 +0,0 @@
|
||||
#PHPMailer Extras
|
||||
|
||||
These classes provide optional additional functions to PHPMailer.
|
||||
|
||||
These are not loaded by the PHPMailer autoloader, so in some cases you may need to `require` them yourself before using them.
|
||||
|
||||
##HTML2Text
|
||||
|
||||
This class was written by Jon Abernathy and provides a simple conversion of HTML to plain-text, while attempting to preserve some aspects of the formatting. It is used in PHPMailer if you set the `advanced` parameter to `true` in either the `msgHTML()` or `html2text` methods of PHPMailer.
|
||||
|
||||
##EasyPeasyICS
|
||||
|
||||
This class was originally written by Manuel Reinhard and provides a simple means of generating ICS/vCal files that are used in sending calendar events. PHPMailer does not use it directly, but you can use it to generate content appropriate for placing in the `Ical` property of PHPMailer. The PHPMailer project is now its official home as Manuel has given permission for that and is no longer maintaining it himself.
|
||||
|
||||
##htmlfilter
|
||||
|
||||
This class by Konstantin Riabitsev and Jim Jagielski implements HTML filtering to remove potentially malicious tags, such as `<script>` or `onclick=` attributes that can result in XSS attacks. This is a simple filter and is not as comprehensive as [HTMLawed](http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/) or [HTMLPurifier](http://htmlpurifier.org), but it's easier to use and considerably better than nothing! PHPMailer does not use it directly, but you may want to apply it to user-supplied HTML before using it as a message body.
|
||||
|
||||
##NTLM_SASL_client
|
||||
|
||||
This class by Manuel Lemos (bundled with permission) adds the ability to authenticate with Microsoft Windows mail servers that use NTLM-based authentication. It is used by PHPMailer if you send via SMTP and set the `AuthType` property to `NTLM`; you will also need to use the `Realm` and `Workstation` properties. The original source is [here](http://www.phpclasses.org/browse/file/7495.html).
|
||||
@@ -1,677 +0,0 @@
|
||||
<?php
|
||||
/*************************************************************************
|
||||
* *
|
||||
* Converts HTML to formatted plain text *
|
||||
* *
|
||||
* Portions Copyright (c) 2005-2007 Jon Abernathy <jon@chuggnutt.com> *
|
||||
* *
|
||||
* This script is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* The GNU General Public License can be found at *
|
||||
* http://www.gnu.org/copyleft/gpl.html. *
|
||||
* *
|
||||
* This script is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
/**
|
||||
* Converts HTML to formatted plain text
|
||||
*/
|
||||
class Html2Text
|
||||
{
|
||||
/**
|
||||
* Contains the HTML content to convert.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
protected $html;
|
||||
|
||||
/**
|
||||
* Contains the converted, formatted text.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
protected $text;
|
||||
|
||||
/**
|
||||
* Maximum width of the formatted text, in columns.
|
||||
*
|
||||
* Set this value to 0 (or less) to ignore word wrapping
|
||||
* and not constrain text to a fixed-width column.
|
||||
*
|
||||
* @type integer
|
||||
*/
|
||||
protected $width = 70;
|
||||
|
||||
/**
|
||||
* List of preg* regular expression patterns to search for,
|
||||
* used in conjunction with $replace.
|
||||
*
|
||||
* @type array
|
||||
* @see $replace
|
||||
*/
|
||||
protected $search = array(
|
||||
"/\r/", // Non-legal carriage return
|
||||
"/[\n\t]+/", // Newlines and tabs
|
||||
'/<head[^>]*>.*?<\/head>/i', // <head>
|
||||
'/<script[^>]*>.*?<\/script>/i', // <script>s -- which strip_tags supposedly has problems with
|
||||
'/<style[^>]*>.*?<\/style>/i', // <style>s -- which strip_tags supposedly has problems with
|
||||
'/<p[^>]*>/i', // <P>
|
||||
'/<br[^>]*>/i', // <br>
|
||||
'/<i[^>]*>(.*?)<\/i>/i', // <i>
|
||||
'/<em[^>]*>(.*?)<\/em>/i', // <em>
|
||||
'/(<ul[^>]*>|<\/ul>)/i', // <ul> and </ul>
|
||||
'/(<ol[^>]*>|<\/ol>)/i', // <ol> and </ol>
|
||||
'/(<dl[^>]*>|<\/dl>)/i', // <dl> and </dl>
|
||||
'/<li[^>]*>(.*?)<\/li>/i', // <li> and </li>
|
||||
'/<dd[^>]*>(.*?)<\/dd>/i', // <dd> and </dd>
|
||||
'/<dt[^>]*>(.*?)<\/dt>/i', // <dt> and </dt>
|
||||
'/<li[^>]*>/i', // <li>
|
||||
'/<hr[^>]*>/i', // <hr>
|
||||
'/<div[^>]*>/i', // <div>
|
||||
'/(<table[^>]*>|<\/table>)/i', // <table> and </table>
|
||||
'/(<tr[^>]*>|<\/tr>)/i', // <tr> and </tr>
|
||||
'/<td[^>]*>(.*?)<\/td>/i', // <td> and </td>
|
||||
'/<span class="_html2text_ignore">.+?<\/span>/i' // <span class="_html2text_ignore">...</span>
|
||||
);
|
||||
|
||||
/**
|
||||
* List of pattern replacements corresponding to patterns searched.
|
||||
*
|
||||
* @type array
|
||||
* @see $search
|
||||
*/
|
||||
protected $replace = array(
|
||||
'', // Non-legal carriage return
|
||||
' ', // Newlines and tabs
|
||||
'', // <head>
|
||||
'', // <script>s -- which strip_tags supposedly has problems with
|
||||
'', // <style>s -- which strip_tags supposedly has problems with
|
||||
"\n\n", // <P>
|
||||
"\n", // <br>
|
||||
'_\\1_', // <i>
|
||||
'_\\1_', // <em>
|
||||
"\n\n", // <ul> and </ul>
|
||||
"\n\n", // <ol> and </ol>
|
||||
"\n\n", // <dl> and </dl>
|
||||
"\t* \\1\n", // <li> and </li>
|
||||
" \\1\n", // <dd> and </dd>
|
||||
"\t* \\1", // <dt> and </dt>
|
||||
"\n\t* ", // <li>
|
||||
"\n-------------------------\n", // <hr>
|
||||
"<div>\n", // <div>
|
||||
"\n\n", // <table> and </table>
|
||||
"\n", // <tr> and </tr>
|
||||
"\t\t\\1\n", // <td> and </td>
|
||||
"" // <span class="_html2text_ignore">...</span>
|
||||
);
|
||||
|
||||
/**
|
||||
* List of preg* regular expression patterns to search for,
|
||||
* used in conjunction with $ent_replace.
|
||||
*
|
||||
* @type array
|
||||
* @see $ent_replace
|
||||
*/
|
||||
protected $ent_search = array(
|
||||
'/&(nbsp|#160);/i', // Non-breaking space
|
||||
'/&(quot|rdquo|ldquo|#8220|#8221|#147|#148);/i',
|
||||
// Double quotes
|
||||
'/&(apos|rsquo|lsquo|#8216|#8217);/i', // Single quotes
|
||||
'/>/i', // Greater-than
|
||||
'/</i', // Less-than
|
||||
'/&(copy|#169);/i', // Copyright
|
||||
'/&(trade|#8482|#153);/i', // Trademark
|
||||
'/&(reg|#174);/i', // Registered
|
||||
'/&(mdash|#151|#8212);/i', // mdash
|
||||
'/&(ndash|minus|#8211|#8722);/i', // ndash
|
||||
'/&(bull|#149|#8226);/i', // Bullet
|
||||
'/&(pound|#163);/i', // Pound sign
|
||||
'/&(euro|#8364);/i', // Euro sign
|
||||
'/&(amp|#38);/i', // Ampersand: see _converter()
|
||||
'/[ ]{2,}/', // Runs of spaces, post-handling
|
||||
);
|
||||
|
||||
/**
|
||||
* List of pattern replacements corresponding to patterns searched.
|
||||
*
|
||||
* @type array
|
||||
* @see $ent_search
|
||||
*/
|
||||
protected $ent_replace = array(
|
||||
' ', // Non-breaking space
|
||||
'"', // Double quotes
|
||||
"'", // Single quotes
|
||||
'>',
|
||||
'<',
|
||||
'(c)',
|
||||
'(tm)',
|
||||
'(R)',
|
||||
'--',
|
||||
'-',
|
||||
'*',
|
||||
'£',
|
||||
'EUR', // Euro sign. € ?
|
||||
'|+|amp|+|', // Ampersand: see _converter()
|
||||
' ', // Runs of spaces, post-handling
|
||||
);
|
||||
|
||||
/**
|
||||
* List of preg* regular expression patterns to search for
|
||||
* and replace using callback function.
|
||||
*
|
||||
* @type array
|
||||
*/
|
||||
protected $callback_search = array(
|
||||
'/<(a) [^>]*href=("|\')([^"\']+)\2([^>]*)>(.*?)<\/a>/i', // <a href="">
|
||||
'/<(h)[123456]( [^>]*)?>(.*?)<\/h[123456]>/i', // h1 - h6
|
||||
'/<(b)( [^>]*)?>(.*?)<\/b>/i', // <b>
|
||||
'/<(strong)( [^>]*)?>(.*?)<\/strong>/i', // <strong>
|
||||
'/<(th)( [^>]*)?>(.*?)<\/th>/i', // <th> and </th>
|
||||
);
|
||||
|
||||
/**
|
||||
* List of preg* regular expression patterns to search for in PRE body,
|
||||
* used in conjunction with $pre_replace.
|
||||
*
|
||||
* @type array
|
||||
* @see $pre_replace
|
||||
*/
|
||||
protected $pre_search = array(
|
||||
"/\n/",
|
||||
"/\t/",
|
||||
'/ /',
|
||||
'/<pre[^>]*>/',
|
||||
'/<\/pre>/'
|
||||
);
|
||||
|
||||
/**
|
||||
* List of pattern replacements corresponding to patterns searched for PRE body.
|
||||
*
|
||||
* @type array
|
||||
* @see $pre_search
|
||||
*/
|
||||
protected $pre_replace = array(
|
||||
'<br>',
|
||||
' ',
|
||||
' ',
|
||||
'',
|
||||
''
|
||||
);
|
||||
|
||||
/**
|
||||
* Temporary workspace used during PRE processing.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
protected $pre_content = '';
|
||||
|
||||
/**
|
||||
* Contains a list of HTML tags to allow in the resulting text.
|
||||
*
|
||||
* @type string
|
||||
* @see set_allowed_tags()
|
||||
*/
|
||||
protected $allowed_tags = '';
|
||||
|
||||
/**
|
||||
* Contains the base URL that relative links should resolve to.
|
||||
*
|
||||
* @type string
|
||||
*/
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* Indicates whether content in the $html variable has been converted yet.
|
||||
*
|
||||
* @type boolean
|
||||
* @see $html, $text
|
||||
*/
|
||||
protected $_converted = false;
|
||||
|
||||
/**
|
||||
* Contains URL addresses from links to be rendered in plain text.
|
||||
*
|
||||
* @type array
|
||||
* @see _build_link_list()
|
||||
*/
|
||||
protected $_link_list = array();
|
||||
|
||||
/**
|
||||
* Various configuration options (able to be set in the constructor)
|
||||
*
|
||||
* @type array
|
||||
*/
|
||||
protected $_options = array(
|
||||
// 'none'
|
||||
// 'inline' (show links inline)
|
||||
// 'nextline' (show links on the next line)
|
||||
// 'table' (if a table of link URLs should be listed after the text.
|
||||
'do_links' => 'inline',
|
||||
// Maximum width of the formatted text, in columns.
|
||||
// Set this value to 0 (or less) to ignore word wrapping
|
||||
// and not constrain text to a fixed-width column.
|
||||
'width' => 70,
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* If the HTML source string (or file) is supplied, the class
|
||||
* will instantiate with that source propagated, all that has
|
||||
* to be done it to call get_text().
|
||||
*
|
||||
* @param string $source HTML content
|
||||
* @param boolean $from_file Indicates $source is a file to pull content from
|
||||
* @param array $options Set configuration options
|
||||
*/
|
||||
public function __construct($source = '', $from_file = false, $options = array())
|
||||
{
|
||||
$this->_options = array_merge($this->_options, $options);
|
||||
|
||||
if (!empty($source)) {
|
||||
$this->set_html($source, $from_file);
|
||||
}
|
||||
|
||||
$this->set_base_url();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads source HTML into memory, either from $source string or a file.
|
||||
*
|
||||
* @param string $source HTML content
|
||||
* @param boolean $from_file Indicates $source is a file to pull content from
|
||||
*/
|
||||
public function set_html($source, $from_file = false)
|
||||
{
|
||||
if ($from_file && file_exists($source)) {
|
||||
$this->html = file_get_contents($source);
|
||||
} else {
|
||||
$this->html = $source;
|
||||
}
|
||||
|
||||
$this->_converted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text, converted from HTML.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_text()
|
||||
{
|
||||
if (!$this->_converted) {
|
||||
$this->_convert();
|
||||
}
|
||||
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the text, converted from HTML.
|
||||
*/
|
||||
public function print_text()
|
||||
{
|
||||
print $this->get_text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias to print_text(), operates identically.
|
||||
*
|
||||
* @see print_text()
|
||||
*/
|
||||
public function p()
|
||||
{
|
||||
print $this->get_text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the allowed HTML tags to pass through to the resulting text.
|
||||
*
|
||||
* Tags should be in the form "<p>", with no corresponding closing tag.
|
||||
* @param string $allowed_tags
|
||||
*/
|
||||
public function set_allowed_tags($allowed_tags = '')
|
||||
{
|
||||
if (!empty($allowed_tags)) {
|
||||
$this->allowed_tags = $allowed_tags;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a base URL to handle relative links.
|
||||
*
|
||||
* @param string $url
|
||||
*/
|
||||
public function set_base_url($url = '')
|
||||
{
|
||||
if (empty($url)) {
|
||||
if (!empty($_SERVER['HTTP_HOST'])) {
|
||||
$this->url = 'http://' . $_SERVER['HTTP_HOST'];
|
||||
} else {
|
||||
$this->url = '';
|
||||
}
|
||||
} else {
|
||||
// Strip any trailing slashes for consistency (relative
|
||||
// URLs may already start with a slash like "/file.html")
|
||||
if (substr($url, -1) == '/') {
|
||||
$url = substr($url, 0, -1);
|
||||
}
|
||||
$this->url = $url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Workhorse function that does actual conversion (calls _converter() method).
|
||||
*/
|
||||
protected function _convert()
|
||||
{
|
||||
// Variables used for building the link list
|
||||
$this->_link_list = array();
|
||||
|
||||
$text = trim(stripslashes($this->html));
|
||||
|
||||
// Convert HTML to TXT
|
||||
$this->_converter($text);
|
||||
|
||||
// Add link list
|
||||
if (!empty($this->_link_list)) {
|
||||
$text .= "\n\nLinks:\n------\n";
|
||||
foreach ($this->_link_list as $idx => $url) {
|
||||
$text .= '[' . ($idx + 1) . '] ' . $url . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$this->text = $text;
|
||||
|
||||
$this->_converted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workhorse function that does actual conversion.
|
||||
*
|
||||
* First performs custom tag replacement specified by $search and
|
||||
* $replace arrays. Then strips any remaining HTML tags, reduces whitespace
|
||||
* and newlines to a readable format, and word wraps the text to
|
||||
* $this->_options['width'] characters.
|
||||
*
|
||||
* @param string $text Reference to HTML content string
|
||||
*/
|
||||
protected function _converter(&$text)
|
||||
{
|
||||
// Convert <BLOCKQUOTE> (before PRE!)
|
||||
$this->_convert_blockquotes($text);
|
||||
|
||||
// Convert <PRE>
|
||||
$this->_convert_pre($text);
|
||||
|
||||
// Run our defined tags search-and-replace
|
||||
$text = preg_replace($this->search, $this->replace, $text);
|
||||
|
||||
// Run our defined tags search-and-replace with callback
|
||||
$text = preg_replace_callback($this->callback_search, array($this, '_preg_callback'), $text);
|
||||
|
||||
// Strip any other HTML tags
|
||||
$text = strip_tags($text, $this->allowed_tags);
|
||||
|
||||
// Run our defined entities/characters search-and-replace
|
||||
$text = preg_replace($this->ent_search, $this->ent_replace, $text);
|
||||
|
||||
// Replace known html entities
|
||||
$text = html_entity_decode($text, ENT_QUOTES);
|
||||
|
||||
// Remove unknown/unhandled entities (this cannot be done in search-and-replace block)
|
||||
$text = preg_replace('/&([a-zA-Z0-9]{2,6}|#[0-9]{2,4});/', '', $text);
|
||||
|
||||
// Convert "|+|amp|+|" into "&", need to be done after handling of unknown entities
|
||||
// This properly handles situation of "&quot;" in input string
|
||||
$text = str_replace('|+|amp|+|', '&', $text);
|
||||
|
||||
// Bring down number of empty lines to 2 max
|
||||
$text = preg_replace("/\n\s+\n/", "\n\n", $text);
|
||||
$text = preg_replace("/[\n]{3,}/", "\n\n", $text);
|
||||
|
||||
// remove leading empty lines (can be produced by eg. P tag on the beginning)
|
||||
$text = ltrim($text, "\n");
|
||||
|
||||
// Wrap the text to a readable format
|
||||
// for PHP versions >= 4.0.2. Default width is 75
|
||||
// If width is 0 or less, don't wrap the text.
|
||||
if ($this->_options['width'] > 0) {
|
||||
$text = wordwrap($text, $this->_options['width']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function called by preg_replace() on link replacement.
|
||||
*
|
||||
* Maintains an internal list of links to be displayed at the end of the
|
||||
* text, with numeric indices to the original point in the text they
|
||||
* appeared. Also makes an effort at identifying and handling absolute
|
||||
* and relative links.
|
||||
*
|
||||
* @param string $link URL of the link
|
||||
* @param string $display Part of the text to associate number with
|
||||
* @param null $link_override
|
||||
* @return string
|
||||
*/
|
||||
protected function _build_link_list($link, $display, $link_override = null)
|
||||
{
|
||||
$link_method = ($link_override) ? $link_override : $this->_options['do_links'];
|
||||
if ($link_method == 'none') {
|
||||
return $display;
|
||||
}
|
||||
|
||||
|
||||
// Ignored link types
|
||||
if (preg_match('!^(javascript:|mailto:|#)!i', $link)) {
|
||||
return $display;
|
||||
}
|
||||
|
||||
if (preg_match('!^([a-z][a-z0-9.+-]+:)!i', $link)) {
|
||||
$url = $link;
|
||||
} else {
|
||||
$url = $this->url;
|
||||
if (substr($link, 0, 1) != '/') {
|
||||
$url .= '/';
|
||||
}
|
||||
$url .= "$link";
|
||||
}
|
||||
|
||||
if ($link_method == 'table') {
|
||||
if (($index = array_search($url, $this->_link_list)) === false) {
|
||||
$index = count($this->_link_list);
|
||||
$this->_link_list[] = $url;
|
||||
}
|
||||
|
||||
return $display . ' [' . ($index + 1) . ']';
|
||||
} elseif ($link_method == 'nextline') {
|
||||
return $display . "\n[" . $url . ']';
|
||||
} else { // link_method defaults to inline
|
||||
|
||||
return $display . ' [' . $url . ']';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for PRE body conversion.
|
||||
*
|
||||
* @param string $text HTML content
|
||||
*/
|
||||
protected function _convert_pre(&$text)
|
||||
{
|
||||
// get the content of PRE element
|
||||
while (preg_match('/<pre[^>]*>(.*)<\/pre>/ismU', $text, $matches)) {
|
||||
$this->pre_content = $matches[1];
|
||||
|
||||
// Run our defined tags search-and-replace with callback
|
||||
$this->pre_content = preg_replace_callback(
|
||||
$this->callback_search,
|
||||
array($this, '_preg_callback'),
|
||||
$this->pre_content
|
||||
);
|
||||
|
||||
// convert the content
|
||||
$this->pre_content = sprintf(
|
||||
'<div><br>%s<br></div>',
|
||||
preg_replace($this->pre_search, $this->pre_replace, $this->pre_content)
|
||||
);
|
||||
|
||||
// replace the content (use callback because content can contain $0 variable)
|
||||
$text = preg_replace_callback(
|
||||
'/<pre[^>]*>.*<\/pre>/ismU',
|
||||
array($this, '_preg_pre_callback'),
|
||||
$text,
|
||||
1
|
||||
);
|
||||
|
||||
// free memory
|
||||
$this->pre_content = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for BLOCKQUOTE body conversion.
|
||||
*
|
||||
* @param string $text HTML content
|
||||
*/
|
||||
protected function _convert_blockquotes(&$text)
|
||||
{
|
||||
if (preg_match_all('/<\/*blockquote[^>]*>/i', $text, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
$start = 0;
|
||||
$taglen = 0;
|
||||
$level = 0;
|
||||
$diff = 0;
|
||||
foreach ($matches[0] as $m) {
|
||||
if ($m[0][0] == '<' && $m[0][1] == '/') {
|
||||
$level--;
|
||||
if ($level < 0) {
|
||||
$level = 0; // malformed HTML: go to next blockquote
|
||||
} elseif ($level > 0) {
|
||||
// skip inner blockquote
|
||||
} else {
|
||||
$end = $m[1];
|
||||
$len = $end - $taglen - $start;
|
||||
// Get blockquote content
|
||||
$body = substr($text, $start + $taglen - $diff, $len);
|
||||
|
||||
// Set text width
|
||||
$p_width = $this->_options['width'];
|
||||
if ($this->_options['width'] > 0) $this->_options['width'] -= 2;
|
||||
// Convert blockquote content
|
||||
$body = trim($body);
|
||||
$this->_converter($body);
|
||||
// Add citation markers and create PRE block
|
||||
$body = preg_replace('/((^|\n)>*)/', '\\1> ', trim($body));
|
||||
$body = '<pre>' . htmlspecialchars($body) . '</pre>';
|
||||
// Re-set text width
|
||||
$this->_options['width'] = $p_width;
|
||||
// Replace content
|
||||
$text = substr($text, 0, $start - $diff)
|
||||
. $body . substr($text, $end + strlen($m[0]) - $diff);
|
||||
|
||||
$diff = $len + $taglen + strlen($m[0]) - strlen($body);
|
||||
unset($body);
|
||||
}
|
||||
} else {
|
||||
if ($level == 0) {
|
||||
$start = $m[1];
|
||||
$taglen = strlen($m[0]);
|
||||
}
|
||||
$level++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for preg_replace_callback use.
|
||||
*
|
||||
* @param array $matches PREG matches
|
||||
* @return string
|
||||
*/
|
||||
protected function _preg_callback($matches)
|
||||
{
|
||||
switch (strtolower($matches[1])) {
|
||||
case 'b':
|
||||
case 'strong':
|
||||
return $this->_toupper($matches[3]);
|
||||
case 'th':
|
||||
return $this->_toupper("\t\t" . $matches[3] . "\n");
|
||||
case 'h':
|
||||
return $this->_toupper("\n\n" . $matches[3] . "\n\n");
|
||||
case 'a':
|
||||
// override the link method
|
||||
$link_override = null;
|
||||
if (preg_match('/_html2text_link_(\w+)/', $matches[4], $link_override_match)) {
|
||||
$link_override = $link_override_match[1];
|
||||
}
|
||||
// Remove spaces in URL (#1487805)
|
||||
$url = str_replace(' ', '', $matches[3]);
|
||||
|
||||
return $this->_build_link_list($url, $matches[5], $link_override);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for preg_replace_callback use in PRE content handler.
|
||||
*
|
||||
* @param array $matches PREG matches
|
||||
* @return string
|
||||
*/
|
||||
protected function _preg_pre_callback(
|
||||
/** @noinspection PhpUnusedParameterInspection */
|
||||
$matches)
|
||||
{
|
||||
return $this->pre_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strtoupper function with HTML tags and entities handling.
|
||||
*
|
||||
* @param string $str Text to convert
|
||||
* @return string Converted text
|
||||
*/
|
||||
private function _toupper($str)
|
||||
{
|
||||
// string can contain HTML tags
|
||||
$chunks = preg_split('/(<[^>]*>)/', $str, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
// convert toupper only the text between HTML tags
|
||||
foreach ($chunks as $idx => $chunk) {
|
||||
if ($chunk[0] != '<') {
|
||||
$chunks[$idx] = $this->_strtoupper($chunk);
|
||||
}
|
||||
}
|
||||
|
||||
return implode($chunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strtoupper multibyte wrapper function with HTML entities handling.
|
||||
* Forces mb_strtoupper-call to UTF-8.
|
||||
*
|
||||
* @param string $str Text to convert
|
||||
* @return string Converted text
|
||||
*/
|
||||
private function _strtoupper($str)
|
||||
{
|
||||
$str = html_entity_decode($str, ENT_COMPAT);
|
||||
|
||||
if (function_exists('mb_strtoupper'))
|
||||
$str = mb_strtoupper($str, 'UTF-8');
|
||||
else
|
||||
$str = strtoupper($str);
|
||||
|
||||
$str = htmlspecialchars($str, ENT_COMPAT);
|
||||
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
@@ -1,874 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* htmlfilter.inc
|
||||
* ---------------
|
||||
* This set of functions allows you to filter html in order to remove
|
||||
* any malicious tags from it. Useful in cases when you need to filter
|
||||
* user input for any cross-site-scripting attempts.
|
||||
*
|
||||
* Copyright (C) 2002-2004 by Duke University
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
* @Author Konstantin Riabitsev <icon@linux.duke.edu>
|
||||
* @Author Jim Jagielski <jim@jaguNET.com / jimjag@gmail.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* This function returns the final tag out of the tag name, an array
|
||||
* of attributes, and the type of the tag. This function is called by
|
||||
* tln_sanitize internally.
|
||||
*
|
||||
* @param string $tagname the name of the tag.
|
||||
* @param array $attary the array of attributes and their values
|
||||
* @param integer $tagtype The type of the tag (see in comments).
|
||||
* @return string A string with the final tag representation.
|
||||
*/
|
||||
function tln_tagprint($tagname, $attary, $tagtype)
|
||||
{
|
||||
if ($tagtype == 2) {
|
||||
$fulltag = '</' . $tagname . '>';
|
||||
} else {
|
||||
$fulltag = '<' . $tagname;
|
||||
if (is_array($attary) && sizeof($attary)) {
|
||||
$atts = array();
|
||||
while (list($attname, $attvalue) = each($attary)) {
|
||||
array_push($atts, "$attname=$attvalue");
|
||||
}
|
||||
$fulltag .= ' ' . join(' ', $atts);
|
||||
}
|
||||
if ($tagtype == 3) {
|
||||
$fulltag .= ' /';
|
||||
}
|
||||
$fulltag .= '>';
|
||||
}
|
||||
return $fulltag;
|
||||
}
|
||||
|
||||
/**
|
||||
* A small helper function to use with array_walk. Modifies a by-ref
|
||||
* value and makes it lowercase.
|
||||
*
|
||||
* @param string $val a value passed by-ref.
|
||||
* @return void since it modifies a by-ref value.
|
||||
*/
|
||||
function tln_casenormalize(&$val)
|
||||
{
|
||||
$val = strtolower($val);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function skips any whitespace from the current position within
|
||||
* a string and to the next non-whitespace value.
|
||||
*
|
||||
* @param string $body the string
|
||||
* @param integer $offset the offset within the string where we should start
|
||||
* looking for the next non-whitespace character.
|
||||
* @return integer the location within the $body where the next
|
||||
* non-whitespace char is located.
|
||||
*/
|
||||
function tln_skipspace($body, $offset)
|
||||
{
|
||||
preg_match('/^(\s*)/s', substr($body, $offset), $matches);
|
||||
if (sizeof($matches[1])) {
|
||||
$count = strlen($matches[1]);
|
||||
$offset += $count;
|
||||
}
|
||||
return $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function looks for the next character within a string. It's
|
||||
* really just a glorified "strpos", except it catches the failures
|
||||
* nicely.
|
||||
*
|
||||
* @param string $body The string to look for needle in.
|
||||
* @param integer $offset Start looking from this position.
|
||||
* @param string $needle The character/string to look for.
|
||||
* @return integer location of the next occurrence of the needle, or
|
||||
* strlen($body) if needle wasn't found.
|
||||
*/
|
||||
function tln_findnxstr($body, $offset, $needle)
|
||||
{
|
||||
$pos = strpos($body, $needle, $offset);
|
||||
if ($pos === false) {
|
||||
$pos = strlen($body);
|
||||
}
|
||||
return $pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function takes a PCRE-style regexp and tries to match it
|
||||
* within the string.
|
||||
*
|
||||
* @param string $body The string to look for needle in.
|
||||
* @param integer $offset Start looking from here.
|
||||
* @param string $reg A PCRE-style regex to match.
|
||||
* @return array|boolean Returns a false if no matches found, or an array
|
||||
* with the following members:
|
||||
* - integer with the location of the match within $body
|
||||
* - string with whatever content between offset and the match
|
||||
* - string with whatever it is we matched
|
||||
*/
|
||||
function tln_findnxreg($body, $offset, $reg)
|
||||
{
|
||||
$matches = array();
|
||||
$retarr = array();
|
||||
$preg_rule = '%^(.*?)(' . $reg . ')%s';
|
||||
preg_match($preg_rule, substr($body, $offset), $matches);
|
||||
if (!isset($matches[0])) {
|
||||
$retarr = false;
|
||||
} else {
|
||||
$retarr[0] = $offset + strlen($matches[1]);
|
||||
$retarr[1] = $matches[1];
|
||||
$retarr[2] = $matches[2];
|
||||
}
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function looks for the next tag.
|
||||
*
|
||||
* @param string $body String where to look for the next tag.
|
||||
* @param integer $offset Start looking from here.
|
||||
* @return array|boolean false if no more tags exist in the body, or
|
||||
* an array with the following members:
|
||||
* - string with the name of the tag
|
||||
* - array with attributes and their values
|
||||
* - integer with tag type (1, 2, or 3)
|
||||
* - integer where the tag starts (starting "<")
|
||||
* - integer where the tag ends (ending ">")
|
||||
* first three members will be false, if the tag is invalid.
|
||||
*/
|
||||
function tln_getnxtag($body, $offset)
|
||||
{
|
||||
if ($offset > strlen($body)) {
|
||||
return false;
|
||||
}
|
||||
$lt = tln_findnxstr($body, $offset, '<');
|
||||
if ($lt == strlen($body)) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* We are here:
|
||||
* blah blah <tag attribute="value">
|
||||
* \---------^
|
||||
*/
|
||||
$pos = tln_skipspace($body, $lt + 1);
|
||||
if ($pos >= strlen($body)) {
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
/**
|
||||
* There are 3 kinds of tags:
|
||||
* 1. Opening tag, e.g.:
|
||||
* <a href="blah">
|
||||
* 2. Closing tag, e.g.:
|
||||
* </a>
|
||||
* 3. XHTML-style content-less tag, e.g.:
|
||||
* <img src="blah"/>
|
||||
*/
|
||||
switch (substr($body, $pos, 1)) {
|
||||
case '/':
|
||||
$tagtype = 2;
|
||||
$pos++;
|
||||
break;
|
||||
case '!':
|
||||
/**
|
||||
* A comment or an SGML declaration.
|
||||
*/
|
||||
if (substr($body, $pos + 1, 2) == '--') {
|
||||
$gt = strpos($body, '-->', $pos);
|
||||
if ($gt === false) {
|
||||
$gt = strlen($body);
|
||||
} else {
|
||||
$gt += 2;
|
||||
}
|
||||
return array(false, false, false, $lt, $gt);
|
||||
} else {
|
||||
$gt = tln_findnxstr($body, $pos, '>');
|
||||
return array(false, false, false, $lt, $gt);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/**
|
||||
* Assume tagtype 1 for now. If it's type 3, we'll switch values
|
||||
* later.
|
||||
*/
|
||||
$tagtype = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for next [\W-_], which will indicate the end of the tag name.
|
||||
*/
|
||||
$regary = tln_findnxreg($body, $pos, '[^\w\-_]');
|
||||
if ($regary == false) {
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
list($pos, $tagname, $match) = $regary;
|
||||
$tagname = strtolower($tagname);
|
||||
|
||||
/**
|
||||
* $match can be either of these:
|
||||
* '>' indicating the end of the tag entirely.
|
||||
* '\s' indicating the end of the tag name.
|
||||
* '/' indicating that this is type-3 xhtml tag.
|
||||
*
|
||||
* Whatever else we find there indicates an invalid tag.
|
||||
*/
|
||||
switch ($match) {
|
||||
case '/':
|
||||
/**
|
||||
* This is an xhtml-style tag with a closing / at the
|
||||
* end, like so: <img src="blah"/>. Check if it's followed
|
||||
* by the closing bracket. If not, then this tag is invalid
|
||||
*/
|
||||
if (substr($body, $pos, 2) == '/>') {
|
||||
$pos++;
|
||||
$tagtype = 3;
|
||||
} else {
|
||||
$gt = tln_findnxstr($body, $pos, '>');
|
||||
$retary = array(false, false, false, $lt, $gt);
|
||||
return $retary;
|
||||
}
|
||||
//intentional fall-through
|
||||
case '>':
|
||||
return array($tagname, false, $tagtype, $lt, $pos);
|
||||
break;
|
||||
default:
|
||||
/**
|
||||
* Check if it's whitespace
|
||||
*/
|
||||
if (preg_match('/\s/', $match)) {
|
||||
} else {
|
||||
/**
|
||||
* This is an invalid tag! Look for the next closing ">".
|
||||
*/
|
||||
$gt = tln_findnxstr($body, $lt, '>');
|
||||
return array(false, false, false, $lt, $gt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* At this point we're here:
|
||||
* <tagname attribute='blah'>
|
||||
* \-------^
|
||||
*
|
||||
* At this point we loop in order to find all attributes.
|
||||
*/
|
||||
$attary = array();
|
||||
|
||||
while ($pos <= strlen($body)) {
|
||||
$pos = tln_skipspace($body, $pos);
|
||||
if ($pos == strlen($body)) {
|
||||
/**
|
||||
* Non-closed tag.
|
||||
*/
|
||||
return array(false, false, false, $lt, $pos);
|
||||
}
|
||||
/**
|
||||
* See if we arrived at a ">" or "/>", which means that we reached
|
||||
* the end of the tag.
|
||||
*/
|
||||
$matches = array();
|
||||
preg_match('%^(\s*)(>|/>)%s', substr($body, $pos), $matches);
|
||||
if (isset($matches[0]) && $matches[0]) {
|
||||
/**
|
||||
* Yep. So we did.
|
||||
*/
|
||||
$pos += strlen($matches[1]);
|
||||
if ($matches[2] == '/>') {
|
||||
$tagtype = 3;
|
||||
$pos++;
|
||||
}
|
||||
return array($tagname, $attary, $tagtype, $lt, $pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* There are several types of attributes, with optional
|
||||
* [:space:] between members.
|
||||
* Type 1:
|
||||
* attrname[:space:]=[:space:]'CDATA'
|
||||
* Type 2:
|
||||
* attrname[:space:]=[:space:]"CDATA"
|
||||
* Type 3:
|
||||
* attr[:space:]=[:space:]CDATA
|
||||
* Type 4:
|
||||
* attrname
|
||||
*
|
||||
* We leave types 1 and 2 the same, type 3 we check for
|
||||
* '"' and convert to """ if needed, then wrap in
|
||||
* double quotes. Type 4 we convert into:
|
||||
* attrname="yes".
|
||||
*/
|
||||
$regary = tln_findnxreg($body, $pos, '[^\w\-_]');
|
||||
if ($regary == false) {
|
||||
/**
|
||||
* Looks like body ended before the end of tag.
|
||||
*/
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
list($pos, $attname, $match) = $regary;
|
||||
$attname = strtolower($attname);
|
||||
/**
|
||||
* We arrived at the end of attribute name. Several things possible
|
||||
* here:
|
||||
* '>' means the end of the tag and this is attribute type 4
|
||||
* '/' if followed by '>' means the same thing as above
|
||||
* '\s' means a lot of things -- look what it's followed by.
|
||||
* anything else means the attribute is invalid.
|
||||
*/
|
||||
switch ($match) {
|
||||
case '/':
|
||||
/**
|
||||
* This is an xhtml-style tag with a closing / at the
|
||||
* end, like so: <img src="blah"/>. Check if it's followed
|
||||
* by the closing bracket. If not, then this tag is invalid
|
||||
*/
|
||||
if (substr($body, $pos, 2) == '/>') {
|
||||
$pos++;
|
||||
$tagtype = 3;
|
||||
} else {
|
||||
$gt = tln_findnxstr($body, $pos, '>');
|
||||
$retary = array(false, false, false, $lt, $gt);
|
||||
return $retary;
|
||||
}
|
||||
//intentional fall-through
|
||||
case '>':
|
||||
$attary{$attname} = '"yes"';
|
||||
return array($tagname, $attary, $tagtype, $lt, $pos);
|
||||
break;
|
||||
default:
|
||||
/**
|
||||
* Skip whitespace and see what we arrive at.
|
||||
*/
|
||||
$pos = tln_skipspace($body, $pos);
|
||||
$char = substr($body, $pos, 1);
|
||||
/**
|
||||
* Two things are valid here:
|
||||
* '=' means this is attribute type 1 2 or 3.
|
||||
* \w means this was attribute type 4.
|
||||
* anything else we ignore and re-loop. End of tag and
|
||||
* invalid stuff will be caught by our checks at the beginning
|
||||
* of the loop.
|
||||
*/
|
||||
if ($char == '=') {
|
||||
$pos++;
|
||||
$pos = tln_skipspace($body, $pos);
|
||||
/**
|
||||
* Here are 3 possibilities:
|
||||
* "'" attribute type 1
|
||||
* '"' attribute type 2
|
||||
* everything else is the content of tag type 3
|
||||
*/
|
||||
$quot = substr($body, $pos, 1);
|
||||
if ($quot == '\'') {
|
||||
$regary = tln_findnxreg($body, $pos + 1, '\'');
|
||||
if ($regary == false) {
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
list($pos, $attval, $match) = $regary;
|
||||
$pos++;
|
||||
$attary{$attname} = '\'' . $attval . '\'';
|
||||
} else {
|
||||
if ($quot == '"') {
|
||||
$regary = tln_findnxreg($body, $pos + 1, '\"');
|
||||
if ($regary == false) {
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
list($pos, $attval, $match) = $regary;
|
||||
$pos++;
|
||||
$attary{$attname} = '"' . $attval . '"';
|
||||
} else {
|
||||
/**
|
||||
* These are hateful. Look for \s, or >.
|
||||
*/
|
||||
$regary = tln_findnxreg($body, $pos, '[\s>]');
|
||||
if ($regary == false) {
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
list($pos, $attval, $match) = $regary;
|
||||
/**
|
||||
* If it's ">" it will be caught at the top.
|
||||
*/
|
||||
$attval = preg_replace('/\"/s', '"', $attval);
|
||||
$attary{$attname} = '"' . $attval . '"';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (preg_match('|[\w/>]|', $char)) {
|
||||
/**
|
||||
* That was attribute type 4.
|
||||
*/
|
||||
$attary{$attname} = '"yes"';
|
||||
} else {
|
||||
/**
|
||||
* An illegal character. Find next '>' and return.
|
||||
*/
|
||||
$gt = tln_findnxstr($body, $pos, '>');
|
||||
return array(false, false, false, $lt, $gt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The fact that we got here indicates that the tag end was never
|
||||
* found. Return invalid tag indication so it gets stripped.
|
||||
*/
|
||||
return array(false, false, false, $lt, strlen($body));
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates entities into literal values so they can be checked.
|
||||
*
|
||||
* @param string $attvalue the by-ref value to check.
|
||||
* @param string $regex the regular expression to check against.
|
||||
* @param boolean $hex whether the entites are hexadecimal.
|
||||
* @return boolean True or False depending on whether there were matches.
|
||||
*/
|
||||
function tln_deent(&$attvalue, $regex, $hex = false)
|
||||
{
|
||||
preg_match_all($regex, $attvalue, $matches);
|
||||
if (is_array($matches) && sizeof($matches[0]) > 0) {
|
||||
$repl = array();
|
||||
for ($i = 0; $i < sizeof($matches[0]); $i++) {
|
||||
$numval = $matches[1][$i];
|
||||
if ($hex) {
|
||||
$numval = hexdec($numval);
|
||||
}
|
||||
$repl{$matches[0][$i]} = chr($numval);
|
||||
}
|
||||
$attvalue = strtr($attvalue, $repl);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks attribute values for entity-encoded values
|
||||
* and returns them translated into 8-bit strings so we can run
|
||||
* checks on them.
|
||||
*
|
||||
* @param string $attvalue A string to run entity check against.
|
||||
* @return Void, modifies a reference value.
|
||||
*/
|
||||
function tln_defang(&$attvalue)
|
||||
{
|
||||
/**
|
||||
* Skip this if there aren't ampersands or backslashes.
|
||||
*/
|
||||
if (strpos($attvalue, '&') === false
|
||||
&& strpos($attvalue, '\\') === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
$m = false;
|
||||
$m = $m || tln_deent($attvalue, '/\�*(\d+);*/s');
|
||||
$m = $m || tln_deent($attvalue, '/\�*((\d|[a-f])+);*/si', true);
|
||||
$m = $m || tln_deent($attvalue, '/\\\\(\d+)/s', true);
|
||||
} while ($m == true);
|
||||
$attvalue = stripslashes($attvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill any tabs, newlines, or carriage returns. Our friends the
|
||||
* makers of the browser with 95% market value decided that it'd
|
||||
* be funny to make "java[tab]script" be just as good as "javascript".
|
||||
*
|
||||
* @param string $attvalue The attribute value before extraneous spaces removed.
|
||||
* @return Void, modifies a reference value.
|
||||
*/
|
||||
function tln_unspace(&$attvalue)
|
||||
{
|
||||
if (strcspn($attvalue, "\t\r\n\0 ") != strlen($attvalue)) {
|
||||
$attvalue = str_replace(
|
||||
array("\t", "\r", "\n", "\0", " "),
|
||||
array('', '', '', '', ''),
|
||||
$attvalue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function runs various checks against the attributes.
|
||||
*
|
||||
* @param string $tagname String with the name of the tag.
|
||||
* @param array $attary Array with all tag attributes.
|
||||
* @param array $rm_attnames See description for tln_sanitize
|
||||
* @param array $bad_attvals See description for tln_sanitize
|
||||
* @param array $add_attr_to_tag See description for tln_sanitize
|
||||
* @return Array with modified attributes.
|
||||
*/
|
||||
function tln_fixatts(
|
||||
$tagname,
|
||||
$attary,
|
||||
$rm_attnames,
|
||||
$bad_attvals,
|
||||
$add_attr_to_tag
|
||||
) {
|
||||
while (list($attname, $attvalue) = each($attary)) {
|
||||
/**
|
||||
* See if this attribute should be removed.
|
||||
*/
|
||||
foreach ($rm_attnames as $matchtag => $matchattrs) {
|
||||
if (preg_match($matchtag, $tagname)) {
|
||||
foreach ($matchattrs as $matchattr) {
|
||||
if (preg_match($matchattr, $attname)) {
|
||||
unset($attary{$attname});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Remove any backslashes, entities, or extraneous whitespace.
|
||||
*/
|
||||
tln_defang($attvalue);
|
||||
tln_unspace($attvalue);
|
||||
|
||||
/**
|
||||
* Now let's run checks on the attvalues.
|
||||
* I don't expect anyone to comprehend this. If you do,
|
||||
* get in touch with me so I can drive to where you live and
|
||||
* shake your hand personally. :)
|
||||
*/
|
||||
foreach ($bad_attvals as $matchtag => $matchattrs) {
|
||||
if (preg_match($matchtag, $tagname)) {
|
||||
foreach ($matchattrs as $matchattr => $valary) {
|
||||
if (preg_match($matchattr, $attname)) {
|
||||
/**
|
||||
* There are two arrays in valary.
|
||||
* First is matches.
|
||||
* Second one is replacements
|
||||
*/
|
||||
list($valmatch, $valrepl) = $valary;
|
||||
$newvalue = preg_replace($valmatch, $valrepl, $attvalue);
|
||||
if ($newvalue != $attvalue) {
|
||||
$attary{$attname} = $newvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* See if we need to append any attributes to this tag.
|
||||
*/
|
||||
foreach ($add_attr_to_tag as $matchtag => $addattary) {
|
||||
if (preg_match($matchtag, $tagname)) {
|
||||
$attary = array_merge($attary, $addattary);
|
||||
}
|
||||
}
|
||||
return $attary;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $body The HTML you wish to filter
|
||||
* @param array $tag_list see description above
|
||||
* @param array $rm_tags_with_content see description above
|
||||
* @param array $self_closing_tags see description above
|
||||
* @param boolean $force_tag_closing see description above
|
||||
* @param array $rm_attnames see description above
|
||||
* @param array $bad_attvals see description above
|
||||
* @param array $add_attr_to_tag see description above
|
||||
* @return string Sanitized html safe to show on your pages.
|
||||
*/
|
||||
function tln_sanitize(
|
||||
$body,
|
||||
$tag_list,
|
||||
$rm_tags_with_content,
|
||||
$self_closing_tags,
|
||||
$force_tag_closing,
|
||||
$rm_attnames,
|
||||
$bad_attvals,
|
||||
$add_attr_to_tag
|
||||
) {
|
||||
/**
|
||||
* Normalize rm_tags and rm_tags_with_content.
|
||||
*/
|
||||
$rm_tags = array_shift($tag_list);
|
||||
@array_walk($tag_list, 'tln_casenormalize');
|
||||
@array_walk($rm_tags_with_content, 'tln_casenormalize');
|
||||
@array_walk($self_closing_tags, 'tln_casenormalize');
|
||||
/**
|
||||
* See if tag_list is of tags to remove or tags to allow.
|
||||
* false means remove these tags
|
||||
* true means allow these tags
|
||||
*/
|
||||
$curpos = 0;
|
||||
$open_tags = array();
|
||||
$trusted = "<!-- begin tln_sanitized html -->\n";
|
||||
$skip_content = false;
|
||||
/**
|
||||
* Take care of netscape's stupid javascript entities like
|
||||
* &{alert('boo')};
|
||||
*/
|
||||
$body = preg_replace('/&(\{.*?\};)/si', '&\\1', $body);
|
||||
while (($curtag = tln_getnxtag($body, $curpos)) != false) {
|
||||
list($tagname, $attary, $tagtype, $lt, $gt) = $curtag;
|
||||
$free_content = substr($body, $curpos, $lt - $curpos);
|
||||
if ($skip_content == false) {
|
||||
$trusted .= $free_content;
|
||||
} else {
|
||||
}
|
||||
if ($tagname != false) {
|
||||
if ($tagtype == 2) {
|
||||
if ($skip_content == $tagname) {
|
||||
/**
|
||||
* Got to the end of tag we needed to remove.
|
||||
*/
|
||||
$tagname = false;
|
||||
$skip_content = false;
|
||||
} else {
|
||||
if ($skip_content == false) {
|
||||
if (isset($open_tags{$tagname}) &&
|
||||
$open_tags{$tagname} > 0
|
||||
) {
|
||||
$open_tags{$tagname}--;
|
||||
} else {
|
||||
$tagname = false;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* $rm_tags_with_content
|
||||
*/
|
||||
if ($skip_content == false) {
|
||||
/**
|
||||
* See if this is a self-closing type and change
|
||||
* tagtype appropriately.
|
||||
*/
|
||||
if ($tagtype == 1
|
||||
&& in_array($tagname, $self_closing_tags)
|
||||
) {
|
||||
$tagtype = 3;
|
||||
}
|
||||
/**
|
||||
* See if we should skip this tag and any content
|
||||
* inside it.
|
||||
*/
|
||||
if ($tagtype == 1
|
||||
&& in_array($tagname, $rm_tags_with_content)
|
||||
) {
|
||||
$skip_content = $tagname;
|
||||
} else {
|
||||
if (($rm_tags == false
|
||||
&& in_array($tagname, $tag_list)) ||
|
||||
($rm_tags == true
|
||||
&& !in_array($tagname, $tag_list))
|
||||
) {
|
||||
$tagname = false;
|
||||
} else {
|
||||
if ($tagtype == 1) {
|
||||
if (isset($open_tags{$tagname})) {
|
||||
$open_tags{$tagname}++;
|
||||
} else {
|
||||
$open_tags{$tagname} = 1;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This is where we run other checks.
|
||||
*/
|
||||
if (is_array($attary) && sizeof($attary) > 0) {
|
||||
$attary = tln_fixatts(
|
||||
$tagname,
|
||||
$attary,
|
||||
$rm_attnames,
|
||||
$bad_attvals,
|
||||
$add_attr_to_tag
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
if ($tagname != false && $skip_content == false) {
|
||||
$trusted .= tln_tagprint($tagname, $attary, $tagtype);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
$curpos = $gt + 1;
|
||||
}
|
||||
$trusted .= substr($body, $curpos, strlen($body) - $curpos);
|
||||
if ($force_tag_closing == true) {
|
||||
foreach ($open_tags as $tagname => $opentimes) {
|
||||
while ($opentimes > 0) {
|
||||
$trusted .= '</' . $tagname . '>';
|
||||
$opentimes--;
|
||||
}
|
||||
}
|
||||
$trusted .= "\n";
|
||||
}
|
||||
$trusted .= "<!-- end tln_sanitized html -->\n";
|
||||
return $trusted;
|
||||
}
|
||||
|
||||
//
|
||||
// Use the nifty htmlfilter library
|
||||
//
|
||||
|
||||
|
||||
function HTMLFilter($body, $trans_image_path, $block_external_images = false)
|
||||
{
|
||||
|
||||
$tag_list = array(
|
||||
false,
|
||||
"object",
|
||||
"meta",
|
||||
"html",
|
||||
"head",
|
||||
"base",
|
||||
"link",
|
||||
"frame",
|
||||
"iframe",
|
||||
"plaintext",
|
||||
"marquee"
|
||||
);
|
||||
|
||||
$rm_tags_with_content = array(
|
||||
"script",
|
||||
"applet",
|
||||
"embed",
|
||||
"title",
|
||||
"frameset",
|
||||
"xmp",
|
||||
"xml"
|
||||
);
|
||||
|
||||
$self_closing_tags = array(
|
||||
"img",
|
||||
"br",
|
||||
"hr",
|
||||
"input",
|
||||
"outbind"
|
||||
);
|
||||
|
||||
$force_tag_closing = true;
|
||||
|
||||
$rm_attnames = array(
|
||||
"/.*/" =>
|
||||
array(
|
||||
// "/target/i",
|
||||
"/^on.*/i",
|
||||
"/^dynsrc/i",
|
||||
"/^data.*/i",
|
||||
"/^lowsrc.*/i"
|
||||
)
|
||||
);
|
||||
|
||||
$bad_attvals = array(
|
||||
"/.*/" =>
|
||||
array(
|
||||
"/^src|background/i" =>
|
||||
array(
|
||||
array(
|
||||
'/^([\'"])\s*\S+script\s*:.*([\'"])/si',
|
||||
'/^([\'"])\s*mocha\s*:*.*([\'"])/si',
|
||||
'/^([\'"])\s*about\s*:.*([\'"])/si'
|
||||
),
|
||||
array(
|
||||
"\\1$trans_image_path\\2",
|
||||
"\\1$trans_image_path\\2",
|
||||
"\\1$trans_image_path\\2",
|
||||
"\\1$trans_image_path\\2"
|
||||
)
|
||||
),
|
||||
"/^href|action/i" =>
|
||||
array(
|
||||
array(
|
||||
'/^([\'"])\s*\S+script\s*:.*([\'"])/si',
|
||||
'/^([\'"])\s*mocha\s*:*.*([\'"])/si',
|
||||
'/^([\'"])\s*about\s*:.*([\'"])/si'
|
||||
),
|
||||
array(
|
||||
"\\1#\\1",
|
||||
"\\1#\\1",
|
||||
"\\1#\\1",
|
||||
"\\1#\\1"
|
||||
)
|
||||
),
|
||||
"/^style/i" =>
|
||||
array(
|
||||
array(
|
||||
"/expression/i",
|
||||
"/binding/i",
|
||||
"/behaviou*r/i",
|
||||
"/include-source/i",
|
||||
'/position\s*:\s*absolute/i',
|
||||
'/url\s*\(\s*([\'"])\s*\S+script\s*:.*([\'"])\s*\)/si',
|
||||
'/url\s*\(\s*([\'"])\s*mocha\s*:.*([\'"])\s*\)/si',
|
||||
'/url\s*\(\s*([\'"])\s*about\s*:.*([\'"])\s*\)/si',
|
||||
'/(.*)\s*:\s*url\s*\(\s*([\'"]*)\s*\S+script\s*:.*([\'"]*)\s*\)/si'
|
||||
),
|
||||
array(
|
||||
"idiocy",
|
||||
"idiocy",
|
||||
"idiocy",
|
||||
"idiocy",
|
||||
"",
|
||||
"url(\\1#\\1)",
|
||||
"url(\\1#\\1)",
|
||||
"url(\\1#\\1)",
|
||||
"url(\\1#\\1)",
|
||||
"url(\\1#\\1)",
|
||||
"\\1:url(\\2#\\3)"
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ($block_external_images) {
|
||||
array_push(
|
||||
$bad_attvals{'/.*/'}{'/^src|background/i'}[0],
|
||||
'/^([\'\"])\s*https*:.*([\'\"])/si'
|
||||
);
|
||||
array_push(
|
||||
$bad_attvals{'/.*/'}{'/^src|background/i'}[1],
|
||||
"\\1$trans_image_path\\1"
|
||||
);
|
||||
array_push(
|
||||
$bad_attvals{'/.*/'}{'/^style/i'}[0],
|
||||
'/url\(([\'\"])\s*https*:.*([\'\"])\)/si'
|
||||
);
|
||||
array_push(
|
||||
$bad_attvals{'/.*/'}{'/^style/i'}[1],
|
||||
"url(\\1$trans_image_path\\1)"
|
||||
);
|
||||
}
|
||||
|
||||
$add_attr_to_tag = array(
|
||||
"/^a$/i" =>
|
||||
array('target' => '"_blank"')
|
||||
);
|
||||
|
||||
$trusted = tln_sanitize(
|
||||
$body,
|
||||
$tag_list,
|
||||
$rm_tags_with_content,
|
||||
$self_closing_tags,
|
||||
$force_tag_closing,
|
||||
$rm_attnames,
|
||||
$bad_attvals,
|
||||
$add_attr_to_tag
|
||||
);
|
||||
return $trusted;
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* ntlm_sasl_client.php
|
||||
*
|
||||
* @(#) $Id: ntlm_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $
|
||||
*
|
||||
**
|
||||
** Source: http://www.phpclasses.org/browse/file/7495.html
|
||||
** License: BSD (http://www.phpclasses.org/package/1888-PHP-Single-API-for-standard-authentication-mechanisms.html)
|
||||
** Bundled with Permission
|
||||
**
|
||||
*/
|
||||
|
||||
define("SASL_NTLM_STATE_START", 0);
|
||||
define("SASL_NTLM_STATE_IDENTIFY_DOMAIN", 1);
|
||||
define("SASL_NTLM_STATE_RESPOND_CHALLENGE", 2);
|
||||
define("SASL_NTLM_STATE_DONE", 3);
|
||||
|
||||
class ntlm_sasl_client_class
|
||||
{
|
||||
var $credentials=array();
|
||||
var $state=SASL_NTLM_STATE_START;
|
||||
|
||||
Function Initialize(&$client)
|
||||
{
|
||||
if(!function_exists($function="mcrypt_encrypt")
|
||||
|| !function_exists($function="mhash"))
|
||||
{
|
||||
$extensions=array(
|
||||
"mcrypt_encrypt"=>"mcrypt",
|
||||
"mhash"=>"mhash"
|
||||
);
|
||||
$client->error="the extension ".$extensions[$function]." required by the NTLM SASL client class is not available in this PHP configuration";
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
Function ASCIIToUnicode($ascii)
|
||||
{
|
||||
for($unicode="",$a=0;$a<strlen($ascii);$a++)
|
||||
$unicode.=substr($ascii,$a,1).chr(0);
|
||||
return($unicode);
|
||||
}
|
||||
|
||||
Function TypeMsg1($domain,$workstation)
|
||||
{
|
||||
$domain_length=strlen($domain);
|
||||
$workstation_length=strlen($workstation);
|
||||
$workstation_offset=32;
|
||||
$domain_offset=$workstation_offset+$workstation_length;
|
||||
return(
|
||||
"NTLMSSP\0".
|
||||
"\x01\x00\x00\x00".
|
||||
"\x07\x32\x00\x00".
|
||||
pack("v",$domain_length).
|
||||
pack("v",$domain_length).
|
||||
pack("V",$domain_offset).
|
||||
pack("v",$workstation_length).
|
||||
pack("v",$workstation_length).
|
||||
pack("V",$workstation_offset).
|
||||
$workstation.
|
||||
$domain
|
||||
);
|
||||
}
|
||||
|
||||
Function NTLMResponse($challenge,$password)
|
||||
{
|
||||
$unicode=$this->ASCIIToUnicode($password);
|
||||
$md4=mhash(MHASH_MD4,$unicode);
|
||||
$padded=$md4.str_repeat(chr(0),21-strlen($md4));
|
||||
$iv_size=mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_ECB);
|
||||
$iv=mcrypt_create_iv($iv_size,MCRYPT_RAND);
|
||||
for($response="",$third=0;$third<21;$third+=7)
|
||||
{
|
||||
for($packed="",$p=$third;$p<$third+7;$p++)
|
||||
$packed.=str_pad(decbin(ord(substr($padded,$p,1))),8,"0",STR_PAD_LEFT);
|
||||
for($key="",$p=0;$p<strlen($packed);$p+=7)
|
||||
{
|
||||
$s=substr($packed,$p,7);
|
||||
$b=$s.((substr_count($s,"1") % 2) ? "0" : "1");
|
||||
$key.=chr(bindec($b));
|
||||
}
|
||||
$ciphertext=mcrypt_encrypt(MCRYPT_DES,$key,$challenge,MCRYPT_MODE_ECB,$iv);
|
||||
$response.=$ciphertext;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
Function TypeMsg3($ntlm_response,$user,$domain,$workstation)
|
||||
{
|
||||
$domain_unicode=$this->ASCIIToUnicode($domain);
|
||||
$domain_length=strlen($domain_unicode);
|
||||
$domain_offset=64;
|
||||
$user_unicode=$this->ASCIIToUnicode($user);
|
||||
$user_length=strlen($user_unicode);
|
||||
$user_offset=$domain_offset+$domain_length;
|
||||
$workstation_unicode=$this->ASCIIToUnicode($workstation);
|
||||
$workstation_length=strlen($workstation_unicode);
|
||||
$workstation_offset=$user_offset+$user_length;
|
||||
$lm="";
|
||||
$lm_length=strlen($lm);
|
||||
$lm_offset=$workstation_offset+$workstation_length;
|
||||
$ntlm=$ntlm_response;
|
||||
$ntlm_length=strlen($ntlm);
|
||||
$ntlm_offset=$lm_offset+$lm_length;
|
||||
$session="";
|
||||
$session_length=strlen($session);
|
||||
$session_offset=$ntlm_offset+$ntlm_length;
|
||||
return(
|
||||
"NTLMSSP\0".
|
||||
"\x03\x00\x00\x00".
|
||||
pack("v",$lm_length).
|
||||
pack("v",$lm_length).
|
||||
pack("V",$lm_offset).
|
||||
pack("v",$ntlm_length).
|
||||
pack("v",$ntlm_length).
|
||||
pack("V",$ntlm_offset).
|
||||
pack("v",$domain_length).
|
||||
pack("v",$domain_length).
|
||||
pack("V",$domain_offset).
|
||||
pack("v",$user_length).
|
||||
pack("v",$user_length).
|
||||
pack("V",$user_offset).
|
||||
pack("v",$workstation_length).
|
||||
pack("v",$workstation_length).
|
||||
pack("V",$workstation_offset).
|
||||
pack("v",$session_length).
|
||||
pack("v",$session_length).
|
||||
pack("V",$session_offset).
|
||||
"\x01\x02\x00\x00".
|
||||
$domain_unicode.
|
||||
$user_unicode.
|
||||
$workstation_unicode.
|
||||
$lm.
|
||||
$ntlm
|
||||
);
|
||||
}
|
||||
|
||||
Function Start(&$client, &$message, &$interactions)
|
||||
{
|
||||
if($this->state!=SASL_NTLM_STATE_START)
|
||||
{
|
||||
$client->error="NTLM authentication state is not at the start";
|
||||
return(SASL_FAIL);
|
||||
}
|
||||
$this->credentials=array(
|
||||
"user"=>"",
|
||||
"password"=>"",
|
||||
"realm"=>"",
|
||||
"workstation"=>""
|
||||
);
|
||||
$defaults=array();
|
||||
$status=$client->GetCredentials($this->credentials,$defaults,$interactions);
|
||||
if($status==SASL_CONTINUE)
|
||||
$this->state=SASL_NTLM_STATE_IDENTIFY_DOMAIN;
|
||||
Unset($message);
|
||||
return($status);
|
||||
}
|
||||
|
||||
Function Step(&$client, $response, &$message, &$interactions)
|
||||
{
|
||||
switch($this->state)
|
||||
{
|
||||
case SASL_NTLM_STATE_IDENTIFY_DOMAIN:
|
||||
$message=$this->TypeMsg1($this->credentials["realm"],$this->credentials["workstation"]);
|
||||
$this->state=SASL_NTLM_STATE_RESPOND_CHALLENGE;
|
||||
break;
|
||||
case SASL_NTLM_STATE_RESPOND_CHALLENGE:
|
||||
$ntlm_response=$this->NTLMResponse(substr($response,24,8),$this->credentials["password"]);
|
||||
$message=$this->TypeMsg3($ntlm_response,$this->credentials["user"],$this->credentials["realm"],$this->credentials["workstation"]);
|
||||
$this->state=SASL_NTLM_STATE_DONE;
|
||||
break;
|
||||
case SASL_NTLM_STATE_DONE:
|
||||
$client->error="NTLM authentication was finished without success";
|
||||
return(SASL_FAIL);
|
||||
default:
|
||||
$client->error="invalid NTLM authentication step state";
|
||||
return(SASL_FAIL);
|
||||
}
|
||||
return(SASL_CONTINUE);
|
||||
}
|
||||
};
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* reCAPTCHA client.
|
||||
*/
|
||||
class ReCaptcha
|
||||
{
|
||||
/**
|
||||
* Version of this client library.
|
||||
* @const string
|
||||
*/
|
||||
const VERSION = 'php_1.1.1';
|
||||
|
||||
/**
|
||||
* Shared secret for the site.
|
||||
* @var type string
|
||||
*/
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Method used to communicate with service. Defaults to POST request.
|
||||
* @var RequestMethod
|
||||
*/
|
||||
private $requestMethod;
|
||||
|
||||
/**
|
||||
* Create a configured instance to use the reCAPTCHA service.
|
||||
*
|
||||
* @param string $secret shared secret between site and reCAPTCHA server.
|
||||
* @param RequestMethod $requestMethod method used to send the request. Defaults to POST.
|
||||
*/
|
||||
public function __construct($secret, RequestMethod $requestMethod = null)
|
||||
{
|
||||
if (empty($secret)) {
|
||||
throw new \RuntimeException('No secret provided');
|
||||
}
|
||||
|
||||
if (!is_string($secret)) {
|
||||
throw new \RuntimeException('The provided secret must be a string');
|
||||
}
|
||||
|
||||
$this->secret = $secret;
|
||||
|
||||
if (!is_null($requestMethod)) {
|
||||
$this->requestMethod = $requestMethod;
|
||||
} else {
|
||||
$this->requestMethod = new RequestMethod\Post();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the reCAPTCHA siteverify API to verify whether the user passes
|
||||
* CAPTCHA test.
|
||||
*
|
||||
* @param string $response The value of 'g-recaptcha-response' in the submitted form.
|
||||
* @param string $remoteIp The end user's IP address.
|
||||
* @return Response Response from the service.
|
||||
*/
|
||||
public function verify($response, $remoteIp = null)
|
||||
{
|
||||
// Discard empty solution submissions
|
||||
if (empty($response)) {
|
||||
$recaptchaResponse = new Response(false, array('missing-input-response'));
|
||||
return $recaptchaResponse;
|
||||
}
|
||||
|
||||
$params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION);
|
||||
$rawResponse = $this->requestMethod->submit($params);
|
||||
return Response::fromJson($rawResponse);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* Method used to send the request to the service.
|
||||
*/
|
||||
interface RequestMethod
|
||||
{
|
||||
|
||||
/**
|
||||
* Submit the request with the specified parameters.
|
||||
*
|
||||
* @param RequestParameters $params Request parameters
|
||||
* @return string Body of the reCAPTCHA response
|
||||
*/
|
||||
public function submit(RequestParameters $params);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha\RequestMethod;
|
||||
|
||||
use ReCaptcha\RequestMethod;
|
||||
use ReCaptcha\RequestParameters;
|
||||
|
||||
/**
|
||||
* Sends POST requests to the reCAPTCHA service.
|
||||
*/
|
||||
class Post implements RequestMethod
|
||||
{
|
||||
/**
|
||||
* URL to which requests are POSTed.
|
||||
* @const string
|
||||
*/
|
||||
const SITE_VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
|
||||
/**
|
||||
* Submit the POST request with the specified parameters.
|
||||
*
|
||||
* @param RequestParameters $params Request parameters
|
||||
* @return string Body of the reCAPTCHA response
|
||||
*/
|
||||
public function submit(RequestParameters $params)
|
||||
{
|
||||
/**
|
||||
* PHP 5.6.0 changed the way you specify the peer name for SSL context options.
|
||||
* Using "CN_name" will still work, but it will raise deprecated errors.
|
||||
*/
|
||||
$peer_key = version_compare(PHP_VERSION, '5.6.0', '<') ? 'CN_name' : 'peer_name';
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
|
||||
'method' => 'POST',
|
||||
'content' => $params->toQueryString(),
|
||||
// Force the peer to validate (not needed in 5.6.0+, but still works
|
||||
'verify_peer' => true,
|
||||
// Force the peer validation to use www.google.com
|
||||
$peer_key => 'www.google.com',
|
||||
),
|
||||
);
|
||||
$context = stream_context_create($options);
|
||||
return file_get_contents(self::SITE_VERIFY_URL, false, $context);
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha\RequestMethod;
|
||||
|
||||
/**
|
||||
* Convenience wrapper around native socket and file functions to allow for
|
||||
* mocking.
|
||||
*/
|
||||
class Socket
|
||||
{
|
||||
private $handle = null;
|
||||
|
||||
/**
|
||||
* fsockopen
|
||||
*
|
||||
* @see http://php.net/fsockopen
|
||||
* @param string $hostname
|
||||
* @param int $port
|
||||
* @param int $errno
|
||||
* @param string $errstr
|
||||
* @param float $timeout
|
||||
* @return resource
|
||||
*/
|
||||
public function fsockopen($hostname, $port = -1, &$errno = 0, &$errstr = '', $timeout = null)
|
||||
{
|
||||
$this->handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout));
|
||||
|
||||
if ($this->handle != false && $errno === 0 && $errstr === '') {
|
||||
return $this->handle;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fwrite
|
||||
*
|
||||
* @see http://php.net/fwrite
|
||||
* @param string $string
|
||||
* @param int $length
|
||||
* @return int | bool
|
||||
*/
|
||||
public function fwrite($string, $length = null)
|
||||
{
|
||||
return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length));
|
||||
}
|
||||
|
||||
/**
|
||||
* fgets
|
||||
*
|
||||
* @see http://php.net/fgets
|
||||
* @param int $length
|
||||
*/
|
||||
public function fgets($length = null)
|
||||
{
|
||||
return fgets($this->handle, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* feof
|
||||
*
|
||||
* @see http://php.net/feof
|
||||
* @return bool
|
||||
*/
|
||||
public function feof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* fclose
|
||||
*
|
||||
* @see http://php.net/fclose
|
||||
* @return bool
|
||||
*/
|
||||
public function fclose()
|
||||
{
|
||||
return fclose($this->handle);
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha\RequestMethod;
|
||||
|
||||
use ReCaptcha\RequestMethod;
|
||||
use ReCaptcha\RequestParameters;
|
||||
|
||||
/**
|
||||
* Sends a POST request to the reCAPTCHA service, but makes use of fsockopen()
|
||||
* instead of get_file_contents(). This is to account for people who may be on
|
||||
* servers where allow_furl_open is disabled.
|
||||
*/
|
||||
class SocketPost implements RequestMethod
|
||||
{
|
||||
/**
|
||||
* reCAPTCHA service host.
|
||||
* @const string
|
||||
*/
|
||||
const RECAPTCHA_HOST = 'www.google.com';
|
||||
|
||||
/**
|
||||
* @const string reCAPTCHA service path
|
||||
*/
|
||||
const SITE_VERIFY_PATH = '/recaptcha/api/siteverify';
|
||||
|
||||
/**
|
||||
* @const string Bad request error
|
||||
*/
|
||||
const BAD_REQUEST = '{"success": false, "error-codes": ["invalid-request"]}';
|
||||
|
||||
/**
|
||||
* @const string Bad response error
|
||||
*/
|
||||
const BAD_RESPONSE = '{"success": false, "error-codes": ["invalid-response"]}';
|
||||
|
||||
/**
|
||||
* Socket to the reCAPTCHA service
|
||||
* @var Socket
|
||||
*/
|
||||
private $socket;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \ReCaptcha\RequestMethod\Socket $socket optional socket, injectable for testing
|
||||
*/
|
||||
public function __construct(Socket $socket = null)
|
||||
{
|
||||
if (!is_null($socket)) {
|
||||
$this->socket = $socket;
|
||||
} else {
|
||||
$this->socket = new Socket();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the POST request with the specified parameters.
|
||||
*
|
||||
* @param RequestParameters $params Request parameters
|
||||
* @return string Body of the reCAPTCHA response
|
||||
*/
|
||||
public function submit(RequestParameters $params)
|
||||
{
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
|
||||
if ($this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30) !== false) {
|
||||
$content = $params->toQueryString();
|
||||
|
||||
$request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n";
|
||||
$request .= "Host: " . self::RECAPTCHA_HOST . "\r\n";
|
||||
$request .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
$request .= "Content-length: " . strlen($content) . "\r\n";
|
||||
$request .= "Connection: close\r\n\r\n";
|
||||
$request .= $content . "\r\n\r\n";
|
||||
|
||||
$this->socket->fwrite($request);
|
||||
$response = '';
|
||||
|
||||
while (!$this->socket->feof()) {
|
||||
$response .= $this->socket->fgets(4096);
|
||||
}
|
||||
|
||||
$this->socket->fclose();
|
||||
|
||||
if (0 === strpos($response, 'HTTP/1.1 200 OK')) {
|
||||
$parts = preg_split("#\n\s*\n#Uis", $response);
|
||||
return $parts[1];
|
||||
}
|
||||
|
||||
return self::BAD_RESPONSE;
|
||||
}
|
||||
|
||||
return self::BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* Stores and formats the parameters for the request to the reCAPTCHA service.
|
||||
*/
|
||||
class RequestParameters
|
||||
{
|
||||
/**
|
||||
* Site secret.
|
||||
* @var string
|
||||
*/
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Form response.
|
||||
* @var string
|
||||
*/
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* Remote user's IP address.
|
||||
* @var string
|
||||
*/
|
||||
private $remoteIp;
|
||||
|
||||
/**
|
||||
* Client version.
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* Initialise parameters.
|
||||
*
|
||||
* @param string $secret Site secret.
|
||||
* @param string $response Value from g-captcha-response form field.
|
||||
* @param string $remoteIp User's IP address.
|
||||
* @param string $version Version of this client library.
|
||||
*/
|
||||
public function __construct($secret, $response, $remoteIp = null, $version = null)
|
||||
{
|
||||
$this->secret = $secret;
|
||||
$this->response = $response;
|
||||
$this->remoteIp = $remoteIp;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array representation.
|
||||
*
|
||||
* @return array Array formatted parameters.
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$params = array('secret' => $this->secret, 'response' => $this->response);
|
||||
|
||||
if (!is_null($this->remoteIp)) {
|
||||
$params['remoteip'] = $this->remoteIp;
|
||||
}
|
||||
|
||||
if (!is_null($this->version)) {
|
||||
$params['version'] = $this->version;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query string representation for HTTP request.
|
||||
*
|
||||
* @return string Query string formatted parameters.
|
||||
*/
|
||||
public function toQueryString()
|
||||
{
|
||||
return http_build_query($this->toArray(), '', '&');
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* This is a PHP library that handles calling reCAPTCHA.
|
||||
*
|
||||
* @copyright Copyright (c) 2015, Google Inc.
|
||||
* @link http://www.google.com/recaptcha
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace ReCaptcha;
|
||||
|
||||
/**
|
||||
* The response returned from the service.
|
||||
*/
|
||||
class Response
|
||||
{
|
||||
/**
|
||||
* Succes or failure.
|
||||
* @var boolean
|
||||
*/
|
||||
private $success = false;
|
||||
|
||||
/**
|
||||
* Error code strings.
|
||||
* @var array
|
||||
*/
|
||||
private $errorCodes = array();
|
||||
|
||||
/**
|
||||
* Build the response from the expected JSON returned by the service.
|
||||
*
|
||||
* @param string $json
|
||||
* @return \ReCaptcha\Response
|
||||
*/
|
||||
public static function fromJson($json)
|
||||
{
|
||||
$responseData = json_decode($json, true);
|
||||
|
||||
if (!$responseData) {
|
||||
return new Response(false, array('invalid-json'));
|
||||
}
|
||||
|
||||
if (isset($responseData['success']) && $responseData['success'] == true) {
|
||||
return new Response(true);
|
||||
}
|
||||
|
||||
if (isset($responseData['error-codes']) && is_array($responseData['error-codes'])) {
|
||||
return new Response(false, $responseData['error-codes']);
|
||||
}
|
||||
|
||||
return new Response(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param boolean $success
|
||||
* @param array $errorCodes
|
||||
*/
|
||||
public function __construct($success, array $errorCodes = array())
|
||||
{
|
||||
$this->success = $success;
|
||||
$this->errorCodes = $errorCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is success?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSuccess()
|
||||
{
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error codes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrorCodes()
|
||||
{
|
||||
return $this->errorCodes;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PSR-0 compliant autoloader for libs
|
||||
*
|
||||
* @param string $class The fully-qualified class name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
spl_autoload_register(
|
||||
function ($class) {
|
||||
// Only continue if the class is in our namespace.
|
||||
if (strpos($class, 'libs\\') === 0) {
|
||||
// Replace namespace separators with directory separators in the class name, append
|
||||
// with .php
|
||||
$file = NN_ROOT . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
|
||||
|
||||
// if the file exists, require it
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $class The fully-qualified class name.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
spl_autoload_register(
|
||||
function($class) {
|
||||
// base directory for the namespace prefix
|
||||
$base_dir = __DIR__ . DIRECTORY_SEPARATOR;
|
||||
|
||||
// replace the namespace prefix with the base directory, replace namespace
|
||||
// separators with directory separators in the relative class name, append
|
||||
// with .php
|
||||
$file = $base_dir . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
|
||||
|
||||
// if the file exists, require it
|
||||
if (file_exists($file) && is_readable($file)) {
|
||||
require_once $file;
|
||||
} else {
|
||||
// Let's try the old style format with 'class.' prefixed to the lower-cased filename.
|
||||
// This bypasses the concept of a Vendor namespace as older libs don't use it.
|
||||
|
||||
$filename = 'class.' . strtolower($class) . '.php';
|
||||
$DirIterator = new \DirectoryIterator($base_dir);
|
||||
foreach ($DirIterator as $fileInfo) {
|
||||
if ($fileInfo->isDir() && !$fileInfo->isDot()) {
|
||||
$file = $fileInfo->getPathname() . DIRECTORY_SEPARATOR . $filename;
|
||||
if (file_exists($file) && is_readable($file)) {
|
||||
require_once $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
?>
|
||||
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2013 Barracuda Networks, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,20 +0,0 @@
|
||||
# PHP Fork Daemon
|
||||
A library to make setup and management of forking daemons in PHP easy.
|
||||
|
||||
## Features
|
||||
- Easy management of PHP forks
|
||||
- Return result of children by callback or polling parent for results
|
||||
- Splitting work units into buckets
|
||||
- Preforking callbacks to manage resources before forking
|
||||
- Dynamic setting of number of children / work per child
|
||||
|
||||
## Usage
|
||||
Check out the examples in the examples directory
|
||||
``php example/blocking.php``
|
||||
|
||||
## Caveats
|
||||
- You need to specify ``declare(ticks=1);`` before inclusion of the fork-daemon library, otherwise signals wont be handled. This *must* be done in the main PHP file, as ``declare(ticks=N);`` only works for the file in which it is declared and the files which that file includes. Reference: [PHP Documentation](http://php.net/manual/en/control-structures.declare.php#control-structures.declare.ticks)
|
||||
|
||||
## License
|
||||
Copyright 2013 Barracuda Networks, Inc.
|
||||
Licensed under the MIT License
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "barracudanetworks/forkdaemon-php",
|
||||
"type": "library",
|
||||
"description": "A library to make setup and management of forking daemons in PHP easy.",
|
||||
"keywords": ["forking", "daemons", "php"],
|
||||
"homepage": "https://github.com/barracudanetworks/forkdaemon-php",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [ "fork_daemon.php" ]
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(ticks=1);
|
||||
|
||||
require_once(__DIR__ . '/../fork_daemon.php');
|
||||
|
||||
/* setup forking daemon */
|
||||
$server = new fork_daemon();
|
||||
$server->max_children_set(5);
|
||||
$server->max_work_per_child_set(3);
|
||||
$server->register_child_run("process_child_run");
|
||||
$server->register_parent_child_exit("process_child_exit");
|
||||
$server->register_logging("logger", fork_daemon::LOG_LEVEL_ALL);
|
||||
|
||||
test_blocking();
|
||||
|
||||
function test_blocking()
|
||||
{
|
||||
global $server;
|
||||
|
||||
echo "Adding 10 units of work\n";
|
||||
|
||||
$data_set = array();
|
||||
for($i=0; $i<10; $i++) $data_set[] = $i;
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set);
|
||||
|
||||
/* process work blocking mode */
|
||||
$server->process_work(true);
|
||||
|
||||
echo "Adding 15 more units of work\n";
|
||||
|
||||
$data_set = array();
|
||||
for($i=10; $i<25; $i++) $data_set[] = $i;
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set);
|
||||
|
||||
/* process work blocking mode */
|
||||
$server->process_work(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACK FUNCTIONS
|
||||
*/
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_run($data_set, $identifier = "")
|
||||
{
|
||||
echo "I'm child working on: " . implode(",", $data_set) . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
sleep(rand(4,8));
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_exit($pid, $identifier = "")
|
||||
{
|
||||
echo "Child $pid just finished" . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function logger($message)
|
||||
{
|
||||
echo "logger: " . $message . PHP_EOL;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(ticks=1);
|
||||
|
||||
require_once(__DIR__ . '/../fork_daemon.php');
|
||||
|
||||
/* setup forking daemon */
|
||||
$server = new fork_daemon();
|
||||
$server->max_children_set(5);
|
||||
$server->max_work_per_child_set(3);
|
||||
$server->register_child_run("process_child_run");
|
||||
$server->register_parent_child_exit("process_child_exit");
|
||||
$server->register_logging("logger", fork_daemon::LOG_LEVEL_ALL);
|
||||
|
||||
test_bucket();
|
||||
|
||||
function test_bucket()
|
||||
{
|
||||
global $server;
|
||||
|
||||
define("BUCKET1", 1);
|
||||
define("BUCKET2", 2);
|
||||
|
||||
$server->add_bucket(BUCKET1);
|
||||
$server->add_bucket(BUCKET2);
|
||||
$server->max_children_set(2, BUCKET1);
|
||||
$server->max_children_set(5, BUCKET2);
|
||||
|
||||
$data_set = array();
|
||||
for($i=0; $i<100; $i++) $data_set[] = $i;
|
||||
|
||||
/* add work to bucket 1 */
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set, "", BUCKET1);
|
||||
|
||||
/* add work to bucket 2 */
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set, "", BUCKET2);
|
||||
|
||||
/* wait until all work allocated */
|
||||
while ($server->work_sets_count(BUCKET1) > 0 || $server->work_sets_count(BUCKET2) > 0)
|
||||
{
|
||||
echo "work set count(1): " . $server->work_sets_count(BUCKET1) . ", count(2): " . $server->work_sets_count(BUCKET2) . "\n";
|
||||
if ($server->work_sets_count(BUCKET1) > 0) $server->process_work(false, BUCKET1);
|
||||
if ($server->work_sets_count(BUCKET2) > 0) $server->process_work(false, BUCKET2);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* wait until all children finish */
|
||||
while ($server->children_running() > 0)
|
||||
{
|
||||
echo "waiting for " . $server->children_running() . " children to finish\n";
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACK FUNCTIONS
|
||||
*/
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_run($data_set, $identifier = "")
|
||||
{
|
||||
echo "I'm child working on: " . implode(",", $data_set) . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
sleep(rand(4,8));
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_exit($pid, $identifier = "")
|
||||
{
|
||||
echo "Child $pid just finished" . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function logger($message)
|
||||
{
|
||||
echo "logger: " . $message . PHP_EOL;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(ticks=1);
|
||||
|
||||
require_once(__DIR__ . '/../fork_daemon.php');
|
||||
|
||||
/* setup forking daemon */
|
||||
$server = new fork_daemon();
|
||||
$server->max_children_set(5);
|
||||
$server->max_work_per_child_set(3);
|
||||
$server->register_child_run("process_child_run");
|
||||
$server->register_parent_child_exit("process_child_exit");
|
||||
$server->register_logging("logger", fork_daemon::LOG_LEVEL_ALL);
|
||||
|
||||
test_identifier();
|
||||
|
||||
function test_identifier()
|
||||
{
|
||||
global $server;
|
||||
|
||||
$server->child_single_work_item_set(true);
|
||||
$server->max_work_per_child_set(1);
|
||||
|
||||
echo "Adding 100 units of work\n";
|
||||
|
||||
/* add work */
|
||||
$data_set = array();
|
||||
for($i=0; $i<100; $i++) $data_set[] = $i;
|
||||
shuffle($data_set);
|
||||
$data_set = array_chunk($data_set, 3);
|
||||
|
||||
$i = 0;
|
||||
foreach ($data_set as $item)
|
||||
{
|
||||
$server->addwork($item, "IDn$i");
|
||||
$i++;
|
||||
}
|
||||
|
||||
echo "Processing work in non-blocking mode\n";
|
||||
|
||||
/* process work non blocking mode */
|
||||
$server->process_work(false);
|
||||
|
||||
/* wait until all work allocated */
|
||||
while ($server->work_sets_count() > 0)
|
||||
{
|
||||
echo "work set count: " . $server->work_sets_count() . "\n";
|
||||
$server->process_work(false);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* wait until all children finish */
|
||||
while ($server->children_running() > 0)
|
||||
{
|
||||
echo "waiting for " . $server->children_running() . " children to finish\n";
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACK FUNCTIONS
|
||||
*/
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_run($data_set, $identifier = "")
|
||||
{
|
||||
echo "I'm child working on: " . implode(",", $data_set) . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
sleep(rand(4,8));
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_exit($pid, $identifier = "")
|
||||
{
|
||||
echo "Child $pid just finished" . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function logger($message)
|
||||
{
|
||||
echo "logger: " . $message . PHP_EOL;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(ticks=1);
|
||||
|
||||
require_once(__DIR__ . '/../fork_daemon.php');
|
||||
|
||||
/* setup forking daemon */
|
||||
$server = new fork_daemon();
|
||||
$server->max_children_set(5);
|
||||
$server->max_work_per_child_set(3);
|
||||
$server->register_child_run("process_child_run");
|
||||
$server->register_parent_child_exit("process_child_exit");
|
||||
$server->register_logging("logger", fork_daemon::LOG_LEVEL_ALL);
|
||||
|
||||
test_nonblocking();
|
||||
|
||||
function test_nonblocking()
|
||||
{
|
||||
global $server;
|
||||
|
||||
echo "Adding 100 units of work\n";
|
||||
|
||||
/* add work */
|
||||
$data_set = array();
|
||||
for($i=0; $i<100; $i++) $data_set[] = $i;
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set);
|
||||
|
||||
echo "Processing work in non-blocking mode\n";
|
||||
|
||||
/* process work non blocking mode */
|
||||
$server->process_work(false);
|
||||
|
||||
/* wait until all work allocated */
|
||||
while ($server->work_sets_count() > 0)
|
||||
{
|
||||
echo "work set count: " . $server->work_sets_count() . "\n";
|
||||
$server->process_work(false);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* wait until all children finish */
|
||||
while ($server->children_running() > 0)
|
||||
{
|
||||
echo "waiting for " . $server->children_running() . " children to finish\n";
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACK FUNCTIONS
|
||||
*/
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_run($data_set, $identifier = "")
|
||||
{
|
||||
echo "I'm child working on: " . implode(",", $data_set) . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
sleep(rand(4,8));
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_exit($pid, $identifier = "")
|
||||
{
|
||||
echo "Child $pid just finished" . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function logger($message)
|
||||
{
|
||||
echo "logger: " . $message . PHP_EOL;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sample of passing in work and getting back results using a callback
|
||||
*/
|
||||
|
||||
declare(ticks=1);
|
||||
|
||||
require_once(__DIR__ . '/../fork_daemon.php');
|
||||
|
||||
/* setup forking daemon */
|
||||
$server = new fork_daemon();
|
||||
$server->max_children_set(5);
|
||||
$server->max_work_per_child_set(3);
|
||||
$server->register_child_run("process_child_run");
|
||||
$server->register_parent_child_exit("process_child_exit");
|
||||
$server->register_logging("logger", fork_daemon::LOG_LEVEL_ALL);
|
||||
$server->register_parent_results("process_results");
|
||||
|
||||
test_nonblocking();
|
||||
|
||||
function test_nonblocking()
|
||||
{
|
||||
global $server;
|
||||
|
||||
echo "Adding 100 units of work\n";
|
||||
|
||||
/* add work */
|
||||
$data_set = array();
|
||||
for($i=0; $i<100; $i++) $data_set[] = $i;
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set);
|
||||
|
||||
echo "Processing work in non-blocking mode\n";
|
||||
|
||||
/* process work non blocking mode */
|
||||
$server->process_work(false);
|
||||
|
||||
/* wait until all work allocated */
|
||||
while ($server->work_sets_count() > 0)
|
||||
{
|
||||
echo "work set count: " . $server->work_sets_count() . "\n";
|
||||
$server->process_work(false);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* wait until all children finish */
|
||||
while ($server->children_running() > 0)
|
||||
{
|
||||
echo "waiting for " . $server->children_running() . " children to finish\n";
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACK FUNCTIONS
|
||||
*/
|
||||
|
||||
function process_results($results, $identifier = "")
|
||||
{
|
||||
echo "Results came back: " . implode(",", $results) . ($identifier == "" ? "" : " (id:$identifier)") . PHP_EOL;
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_run($data_set, $identifier = "")
|
||||
{
|
||||
echo "I'm child working on: " . implode(",", $data_set) . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
|
||||
$result = array_sum($data_set);
|
||||
sleep(rand(1,3));
|
||||
|
||||
// return results
|
||||
return $result;
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_exit($pid, $identifier = "")
|
||||
{
|
||||
echo "Child $pid just finished" . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function logger($message)
|
||||
{
|
||||
echo "logger: " . $message . PHP_EOL;
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sample of passing in work and getting back results using a call at the
|
||||
* end of the child processing
|
||||
*/
|
||||
|
||||
declare(ticks=1);
|
||||
|
||||
require_once(__DIR__ . '/../fork_daemon.php');
|
||||
|
||||
/* setup forking daemon */
|
||||
$server = new fork_daemon();
|
||||
$server->max_children_set(100);
|
||||
$server->max_work_per_child_set(3);
|
||||
$server->store_result_set(true);
|
||||
$server->register_child_run("process_child_run");
|
||||
$server->register_parent_child_exit("process_child_exit");
|
||||
$server->register_logging("logger", fork_daemon::LOG_LEVEL_ALL);
|
||||
// no callback with this method since we check results at the end
|
||||
|
||||
test_nonblocking();
|
||||
|
||||
// since deferred results, check at the end
|
||||
$results = $server->get_all_results();
|
||||
var_dump($results);
|
||||
echo "Sum: " . array_sum($results) . PHP_EOL;
|
||||
echo "Count: " . count($results) . PHP_EOL;
|
||||
|
||||
function test_nonblocking()
|
||||
{
|
||||
global $server;
|
||||
|
||||
echo "Adding 100 units of work\n";
|
||||
|
||||
/* add work */
|
||||
$data_set = array();
|
||||
for($i=0; $i<100; $i++) $data_set[] = $i;
|
||||
shuffle($data_set);
|
||||
$server->addwork($data_set);
|
||||
|
||||
echo "Processing work in non-blocking mode\n";
|
||||
echo "Sum: " . array_sum($data_set) . PHP_EOL;
|
||||
|
||||
/* process work non blocking mode */
|
||||
$server->process_work(false);
|
||||
|
||||
/* wait until all work allocated */
|
||||
while ($server->work_sets_count() > 0)
|
||||
{
|
||||
echo "work set count: " . $server->work_sets_count() . "\n";
|
||||
$server->process_work(false);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
/* wait until all children finish */
|
||||
while ($server->children_running() > 0)
|
||||
{
|
||||
echo "waiting for " . $server->children_running() . " children to finish\n";
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CALLBACK FUNCTIONS
|
||||
*/
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_run($data_set, $identifier = "")
|
||||
{
|
||||
echo "I'm child working on: " . implode(",", $data_set) . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
|
||||
sleep(rand(1,3));
|
||||
|
||||
// just do a sum and return it as the result
|
||||
$result = array_sum($data_set);
|
||||
|
||||
// return results
|
||||
return $result;
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function process_child_exit($pid, $identifier = "")
|
||||
{
|
||||
echo "Child $pid just finished" . ($identifier == "" ? "" : " (id:$identifier)") . "\n";
|
||||
}
|
||||
|
||||
/* registered call back function */
|
||||
function logger($message)
|
||||
{
|
||||
echo "logger: " . $message . PHP_EOL;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
@@ -1,163 +0,0 @@
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.vspscc
|
||||
.builds
|
||||
*.dotCover
|
||||
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment this
|
||||
#packages/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish
|
||||
|
||||
# Others
|
||||
[Bb]in
|
||||
[Oo]bj
|
||||
sql
|
||||
TestResults
|
||||
*.Cache
|
||||
ClientBin
|
||||
stylecop.*
|
||||
~$*
|
||||
*.dbmdl
|
||||
Generated_Code #added for RIA/Silverlight projects
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
|
||||
|
||||
|
||||
############
|
||||
## Windows
|
||||
############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user