Merge branch 'dev-composer' into dev-regexless

This commit is contained in:
DariusIII
2016-03-18 23:46:20 +01:00
496 changed files with 784 additions and 100810 deletions
Executable
+36
View File
@@ -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
View File
@@ -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
View File
@@ -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/*
+35
View File
@@ -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
+18 -4
View File
@@ -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
View File
@@ -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'
?>
+7
View File
@@ -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}
+14
View File
@@ -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"
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-97
View File
@@ -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);
}
}
-53
View File
@@ -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();
}
-69
View File
@@ -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;
}
}
-55
View File
@@ -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;
}
}
-55
View File
@@ -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;
}
}
-53
View File
@@ -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++;
}
}
-119
View File
@@ -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();
}
-177
View File
@@ -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;
}
}
-113
View File
@@ -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;
}
}
-40
View File
@@ -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);
}
-255
View File
@@ -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()
);
}
}
-166
View File
@@ -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());
}
}
-49
View File
@@ -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;
}
}
-60
View File
@@ -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);
}
}
-436
View File
@@ -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";
}
}
-684
View File
@@ -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 */
-6
View File
@@ -1,6 +0,0 @@
{
"name": "kbjr/Git.php",
"autoload": {
"classmap": ["Git.php"]
}
}
-708
View File
@@ -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>.
-21
View File
@@ -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');
```
-170
View File
@@ -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 */
-46
View 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
-18
View File
@@ -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 = '';
}
}
}
-25
View File
@@ -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 {
};
?>
-24
View File
@@ -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 {
};
?>
-392
View File
@@ -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;
}
}
};
?>
-29
View File
@@ -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'];
}
};
-63
View File
@@ -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']);
}
};
?>
-56
View File
@@ -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'];
}
};
?>
-130
View File
@@ -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);
}
};
?>
-56
View File
@@ -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;
}
}
-96
View File
@@ -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;
}
}
-530
View File
@@ -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;
}
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace libs\Moinax\TVDB;
class CurlException extends \Exception
{
}
-126
View File
@@ -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;
}
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace libs\Moinax\TVDB;
class Exception extends \Exception
{
}
-15
View File
@@ -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;
}
}
-202
View File
@@ -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;
}
}
-38
View File
@@ -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;
}
}
-12
View File
@@ -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);
}
-63
View File
@@ -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
-172
View File
@@ -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));
}
}
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace libs\Moinax\TVDB;
class XmlException extends Exception
{
}
-49
View File
@@ -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
View File
@@ -1 +0,0 @@
5.2.9
File diff suppressed because it is too large Load Diff
-397
View File
@@ -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
));
}
}
-974
View File
@@ -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;
}
}
-90
View File
@@ -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
-21
View File
@@ -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).
-677
View File
@@ -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
'/&gt;/i', // Greater-than
'/&lt;/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>',
'&nbsp;&nbsp;&nbsp;&nbsp;',
'&nbsp;',
'',
''
);
/**
* 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 "&amp;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;
}
}
-874
View File
@@ -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 "&quot" 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', '&quot;', $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, '/\&#0*(\d+);*/s');
$m = $m || tln_deent($attvalue, '/\&#x0*((\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', '&amp;\\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;
}
-183
View File
@@ -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);
}
};
-97
View File
@@ -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);
}
}
-42
View File
@@ -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);
}
-70
View File
@@ -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);
}
}
-104
View File
@@ -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);
}
}
-120
View File
@@ -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;
}
}
-103
View File
@@ -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(), '', '&');
}
}
-102
View File
@@ -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;
}
}
-63
View File
@@ -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;
}
}
}
}
}
);
?>
-19
View 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.
-20
View File
@@ -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
-14
View File
@@ -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" ]
}
}
-63
View File
@@ -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;
}
-78
View File
@@ -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
-22
View File
@@ -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
-163
View File
@@ -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