diff --git a/_sakura/changelog.json b/_sakura/changelog.json index 34096f8..4ede54f 100644 --- a/_sakura/changelog.json +++ b/_sakura/changelog.json @@ -25,7 +25,8 @@ "20150621", "20150627", "20150628", - "20150629" + "20150629", + "20150630" ] @@ -1363,6 +1364,28 @@ "change": "Changed SAKURA_VTYPE to a SAKURA_STABLE boolean that can be used for only showing things on stable or development builds." } + ], + + "20150630": [ + + { + "type": "ADD", + "change": "Added Payments class (and some transaction function with help from kamilrakowski)." + }, + { + "type": "ADD", + "change": "Added automatic premium after payment." + } + + ], + + "20150701": [ + + { + "type": "FIX", + "change": "Fixed a multitude of fuckups." + } + ] } diff --git a/_sakura/components/Configuration.php b/_sakura/components/Configuration.php index cddc7d1..07c176f 100644 --- a/_sakura/components/Configuration.php +++ b/_sakura/components/Configuration.php @@ -8,8 +8,8 @@ namespace Sakura; class Configuration { // Configuration data - public static $_LCNF; - public static $_DCNF; + private static $_LCNF; + private static $_DCNF; // Initialise configuration, does not contain database initialisation because explained below public static function init($local) { diff --git a/_sakura/components/Payments.php b/_sakura/components/Payments.php index 672533b..325f442 100644 --- a/_sakura/components/Payments.php +++ b/_sakura/components/Payments.php @@ -1,14 +1,141 @@ setPaymentMethod('paypal'); + + // Create the item + $item = new Item(); + + // Set the item details + $item ->setName($itemName) + ->setCurrency('EUR') + ->setQuantity(1) + ->setPrice($total); + + // Create itemlist + $list = new ItemList(); + + // Add the items + $list->setItems([$item]); + + // Create details + $details = new Details(); + + // Set details + $details->setSubtotal($total); + + // Create amount + $amount = new Amount(); + + // Set amount data + $amount ->setCurrency('EUR') + ->setTotal($total) + ->setDetails($details); + + // Create transaction + $trans = new Transaction(); + + // Set transaction data (aka shit we already set but whatever who cares we need to set it again 500 times over again anyway, YAY TECHNOLOGY!) + $trans ->setAmount($amount) + ->setItemList($list) + ->setDescription($transDescription) + ->setInvoiceNumber(uniqid()); + + // Create redirect url object + $redir = new RedirectUrls(); + + // Set redirect url data + $redir ->setReturnUrl($returnUrl. '?mode=finish&success=true') + ->setCancelUrl($returnUrl. '?mode=finish&success=false'); + + // Create payment object + $payment = new Payment(); + + // Set payment data (finally) + $payment->setIntent('sale') + ->setPayer($payer) + ->setRedirectUrls($redir) + ->setTransactions([$trans]); + + // Try to create payment + try { + $payment->create(self::$paypal); + } catch(Exception $ex) { + return false; + } + + // Return the approval link if everything is gucci + return $payment->getApprovalLink(); + + } + + // Complete the PayPal transaction + public static function completeTransaction($paymentId, $payerId) { + + // Attempt to get the payment + $payment = Payment::get($paymentId, self::$paypal); + + // Create payment execution object + $execute = new PaymentExecution(); + + // Set the payer ID + $execute->setPayerId($payerId); + + // Attempt to charge the fucker + try { + $payment->execute($execute, self::$paypal); + } catch(Exception $ex) { + return false; + } + + // If everything was cute return true + return true; + + } } diff --git a/_sakura/components/Permissions.php b/_sakura/components/Permissions.php index 501c3fb..b5f6afb 100644 --- a/_sakura/components/Permissions.php +++ b/_sakura/components/Permissions.php @@ -26,7 +26,7 @@ class Permissions { 'SITE' => [ 'DEACTIVATED' => 1, // Is a user in this group deactivated - 'VIEW_ONLINE' => 2, // Can view the extended online list + 'STATIC_PREMIUM' => 2, // Is always premium 'ALTER_PROFILE' => 4, // Can alter their profile data 'CHANGE_AVATAR' => 8, // Can change their avatar 'CREATE_BACKGROUND' => 16, // Can create a background (different from changing) diff --git a/_sakura/components/Users.php b/_sakura/components/Users.php index 4f6cf2d..5ebd3a9 100644 --- a/_sakura/components/Users.php +++ b/_sakura/components/Users.php @@ -40,8 +40,7 @@ class Users { 'rankname' => 'Sakura Rank', 'multi' => 0, 'colour' => '#444', - 'description' => 'A hardcoded dummy rank for fallback.', - 'is_premium' => 0 + 'description' => 'A hardcoded dummy rank for fallback.' ]; // Check if a user is logged in @@ -852,22 +851,9 @@ class Users { } - // Check if user has Tenshi + // Check if user has Tenshi [ REWRITE THIS ] public static function checkUserTenshi($id) { - // Get user's ranks - $ranks = json_decode(self::getUser($id)['ranks'], true); - - // Check premium flag - foreach($ranks as $rank) { - - // If premium rank was found return true - if(self::getRank($rank)['is_premium']) - return true; - - } - - // Else return false return false; } diff --git a/_sakura/composer.lock b/_sakura/composer.lock index 0006a0e..946aa63 100644 --- a/_sakura/composer.lock +++ b/_sakura/composer.lock @@ -47,16 +47,16 @@ }, { "name": "paypal/rest-api-sdk-php", - "version": "v1.3.2", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/paypal/PayPal-PHP-SDK.git", - "reference": "0a32a6323c829e0e424e9f4d15e7b346c8472c08" + "reference": "18e4eaaf319b48de2457abb7b2b1807cfe704c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paypal/PayPal-PHP-SDK/zipball/0a32a6323c829e0e424e9f4d15e7b346c8472c08", - "reference": "0a32a6323c829e0e424e9f4d15e7b346c8472c08", + "url": "https://api.github.com/repos/paypal/PayPal-PHP-SDK/zipball/18e4eaaf319b48de2457abb7b2b1807cfe704c0a", + "reference": "18e4eaaf319b48de2457abb7b2b1807cfe704c0a", "shasum": "" }, "require": { @@ -84,27 +84,27 @@ } ], "description": "PayPal's PHP SDK for REST APIs", - "homepage": "https://github.com/paypal/rest-api-sdk-php", + "homepage": "http://paypal.github.io/PayPal-PHP-SDK/", "keywords": [ "payments", "paypal", "rest", "sdk" ], - "time": "2015-03-18 20:40:42" + "time": "2015-06-25 17:12:03" }, { "name": "phpmailer/phpmailer", - "version": "v5.2.9", + "version": "v5.2.10", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "73b61679809615850706f1dbf88e6df2ddc05745" + "reference": "07005ecbb80d11ec8c0f067bb37e8909cc7fcbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/73b61679809615850706f1dbf88e6df2ddc05745", - "reference": "73b61679809615850706f1dbf88e6df2ddc05745", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/07005ecbb80d11ec8c0f067bb37e8909cc7fcbb7", + "reference": "07005ecbb80d11ec8c0f067bb37e8909cc7fcbb7", "shasum": "" }, "require": { @@ -112,14 +112,16 @@ }, "require-dev": { "phpdocumentor/phpdocumentor": "*", - "phpunit/phpunit": "4.1.*" + "phpunit/phpunit": "4.3.*" }, "type": "library", "autoload": { "classmap": [ "class.phpmailer.php", + "class.smtp.php", "class.pop3.php", - "class.smtp.php" + "extras/EasyPeasyICS.php", + "extras/ntlm_sasl_client.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -144,20 +146,20 @@ } ], "description": "PHPMailer is a full-featured email creation and transfer class for PHP", - "time": "2014-09-26 18:33:30" + "time": "2015-05-04 12:37:21" }, { "name": "twig/twig", - "version": "v1.18.1", + "version": "v1.18.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f" + "reference": "e8e6575abf6102af53ec283f7f14b89e304fa602" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f", - "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/e8e6575abf6102af53ec283f7f14b89e304fa602", + "reference": "e8e6575abf6102af53ec283f7f14b89e304fa602", "shasum": "" }, "require": { @@ -201,7 +203,7 @@ "keywords": [ "templating" ], - "time": "2015-04-19 08:30:27" + "time": "2015-06-06 23:31:24" } ], "packages-dev": [], diff --git a/_sakura/sakura.php b/_sakura/sakura.php index 414a8f6..f41ef20 100644 --- a/_sakura/sakura.php +++ b/_sakura/sakura.php @@ -8,7 +8,7 @@ namespace Sakura; // Define Sakura version -define('SAKURA_VERSION', '20150629'); +define('SAKURA_VERSION', '20150701'); define('SAKURA_VLABEL', 'Eminence'); define('SAKURA_STABLE', false); define('SAKURA_COLOUR', '#6C3082'); @@ -83,8 +83,8 @@ $renderData = [ 'perms' => [ - 'canViewOnline' => Permissions::check('SITE', 'USE_CHAT', Session::$userId, 1), - 'canUseForums' => Permissions::check('FORUM', 'USE_FORUM', Session::$userId, 1) + 'canGetPremium' => Permissions::check('SITE', 'OBTAIN_PREMIUM', Session::$userId, 1), + 'canUseForums' => Permissions::check('FORUM', 'USE_FORUM', Session::$userId, 1) ], @@ -103,6 +103,7 @@ $renderData = [ 'data' => ($_init_udata = Users::getUser(Session::$userId)), 'rank' => ($_init_rdata = Users::getRank($_init_udata['rank_main'])), 'colour' => ($_init_udata['name_colour'] == null ? $_init_rdata['colour'] : $_init_udata['name_colour']) + ] ]; diff --git a/_sakura/templates/yuuno/errors/premiumComplete.tpl b/_sakura/templates/yuuno/errors/premiumComplete.tpl new file mode 100644 index 0000000..de1bfeb --- /dev/null +++ b/_sakura/templates/yuuno/errors/premiumComplete.tpl @@ -0,0 +1,6 @@ +{% include 'global/header.tpl' %} +
+

Thank you for your contribution!

+

+
+{% include 'global/footer.tpl' %} diff --git a/_sakura/templates/yuuno/main/donate.tpl b/_sakura/templates/yuuno/main/donate.tpl index 3b45983..f2e2e75 100644 --- a/_sakura/templates/yuuno/main/donate.tpl +++ b/_sakura/templates/yuuno/main/donate.tpl @@ -1,7 +1,12 @@ {% include 'global/header.tpl' %} + {% if page.fail %} +
+

The payment failed or was cancelled!

+

Something went wrong while processing the transaction, your PayPal account wasn't charged.

+
+ {% endif %} diff --git a/_sakura/vendor/composer/autoload_classmap.php b/_sakura/vendor/composer/autoload_classmap.php index f5743ab..e178ff6 100644 --- a/_sakura/vendor/composer/autoload_classmap.php +++ b/_sakura/vendor/composer/autoload_classmap.php @@ -6,8 +6,10 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'EasyPeasyICS' => $vendorDir . '/phpmailer/phpmailer/extras/EasyPeasyICS.php', 'PHPMailer' => $vendorDir . '/phpmailer/phpmailer/class.phpmailer.php', 'POP3' => $vendorDir . '/phpmailer/phpmailer/class.pop3.php', 'SMTP' => $vendorDir . '/phpmailer/phpmailer/class.smtp.php', + 'ntlm_sasl_client_class' => $vendorDir . '/phpmailer/phpmailer/extras/ntlm_sasl_client.php', 'phpmailerException' => $vendorDir . '/phpmailer/phpmailer/class.phpmailer.php', ); diff --git a/_sakura/vendor/composer/installed.json b/_sakura/vendor/composer/installed.json index d1d1ebc..6b350a6 100644 --- a/_sakura/vendor/composer/installed.json +++ b/_sakura/vendor/composer/installed.json @@ -1,59 +1,4 @@ [ - { - "name": "phpmailer/phpmailer", - "version": "v5.2.9", - "version_normalized": "5.2.9.0", - "source": { - "type": "git", - "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "73b61679809615850706f1dbf88e6df2ddc05745" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/73b61679809615850706f1dbf88e6df2ddc05745", - "reference": "73b61679809615850706f1dbf88e6df2ddc05745", - "shasum": "" - }, - "require": { - "php": ">=5.0.0" - }, - "require-dev": { - "phpdocumentor/phpdocumentor": "*", - "phpunit/phpunit": "4.1.*" - }, - "time": "2014-09-26 18:33:30", - "type": "library", - "installation-source": "dist", - "autoload": { - "classmap": [ - "class.phpmailer.php", - "class.pop3.php", - "class.smtp.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" - }, { "name": "flashwave/parsedown", "version": "1.5.1", @@ -97,23 +42,23 @@ }, { "name": "twig/twig", - "version": "v1.18.1", - "version_normalized": "1.18.1.0", + "version": "v1.18.2", + "version_normalized": "1.18.2.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f" + "reference": "e8e6575abf6102af53ec283f7f14b89e304fa602" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f", - "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/e8e6575abf6102af53ec283f7f14b89e304fa602", + "reference": "e8e6575abf6102af53ec283f7f14b89e304fa602", "shasum": "" }, "require": { "php": ">=5.2.7" }, - "time": "2015-04-19 08:30:27", + "time": "2015-06-06 23:31:24", "type": "library", "extra": { "branch-alias": { @@ -155,18 +100,75 @@ ] }, { - "name": "paypal/rest-api-sdk-php", - "version": "v1.3.2", - "version_normalized": "1.3.2.0", + "name": "phpmailer/phpmailer", + "version": "v5.2.10", + "version_normalized": "5.2.10.0", "source": { "type": "git", - "url": "https://github.com/paypal/PayPal-PHP-SDK.git", - "reference": "0a32a6323c829e0e424e9f4d15e7b346c8472c08" + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "07005ecbb80d11ec8c0f067bb37e8909cc7fcbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paypal/PayPal-PHP-SDK/zipball/0a32a6323c829e0e424e9f4d15e7b346c8472c08", - "reference": "0a32a6323c829e0e424e9f4d15e7b346c8472c08", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/07005ecbb80d11ec8c0f067bb37e8909cc7fcbb7", + "reference": "07005ecbb80d11ec8c0f067bb37e8909cc7fcbb7", + "shasum": "" + }, + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpdocumentor/phpdocumentor": "*", + "phpunit/phpunit": "4.3.*" + }, + "time": "2015-05-04 12:37:21", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "class.phpmailer.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" + }, + { + "name": "paypal/rest-api-sdk-php", + "version": "v1.5.0", + "version_normalized": "1.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/paypal/PayPal-PHP-SDK.git", + "reference": "18e4eaaf319b48de2457abb7b2b1807cfe704c0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paypal/PayPal-PHP-SDK/zipball/18e4eaaf319b48de2457abb7b2b1807cfe704c0a", + "reference": "18e4eaaf319b48de2457abb7b2b1807cfe704c0a", "shasum": "" }, "require": { @@ -177,7 +179,7 @@ "require-dev": { "phpunit/phpunit": "3.7.*" }, - "time": "2015-03-18 20:40:42", + "time": "2015-06-25 17:12:03", "type": "library", "installation-source": "dist", "autoload": { @@ -196,7 +198,7 @@ } ], "description": "PayPal's PHP SDK for REST APIs", - "homepage": "https://github.com/paypal/rest-api-sdk-php", + "homepage": "http://paypal.github.io/PayPal-PHP-SDK/", "keywords": [ "payments", "paypal", diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/README.md b/_sakura/vendor/paypal/rest-api-sdk-php/README.md index 533fd4a..b0fc253 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/README.md +++ b/_sakura/vendor/paypal/rest-api-sdk-php/README.md @@ -2,7 +2,8 @@ ![Home Image](https://raw.githubusercontent.com/wiki/paypal/PayPal-PHP-SDK/images/homepage.jpg) -[![Build Status](https://travis-ci.org/paypal/PayPal-PHP-SDK.png?branch=master)](https://travis-ci.org/paypal/PayPal-PHP-SDK) [![Coverage Status](https://img.shields.io/coveralls/paypal/PayPal-PHP-SDK.svg)](https://coveralls.io/r/paypal/PayPal-PHP-SDK?branch=master) +[![Build Status](https://travis-ci.org/paypal/PayPal-PHP-SDK.png?branch=master)](https://travis-ci.org/paypal/PayPal-PHP-SDK) +[![Coverage Status](https://coveralls.io/repos/paypal/PayPal-PHP-SDK/badge.svg?branch=master)](https://coveralls.io/r/paypal/PayPal-PHP-SDK?branch=master) __Welcome to PayPal PHP SDK__. This repository contains PayPal's PHP SDK and samples for REST API. @@ -21,8 +22,7 @@ __Welcome to PayPal PHP SDK__. This repository contains PayPal's PHP SDK and sam ## Latest Updates -> **Seeing this error: `'Method PayPal\Api\Sale::getTransactionFee() does not exist' in paypal/vendor/paypal/rest-api-sdk-php/lib/PayPal/Common/PPReflectionUtil.php:73`, Please upgrade the SDK to latest version [v1.3.0](https://github.com/paypal/PayPal-PHP-SDK/releases/tag/v1.3.0).** - +- Vault APIs now have List Credit Card with Filters, new Fields to help you find the object easily. Checkout the latest release. - Checkout the latest 1.0.0 release. Here are all the [ breaking Changes in v1.0.0 ](https://github.com/paypal/PayPal-PHP-SDK/wiki/Breaking-Changes---1.0.0) if you are migrating from older versions. - Now we have a [Github Page](http://paypal.github.io/PayPal-PHP-SDK/), that helps you find all helpful resources building applications using PayPal-PHP-SDK. - Introduced `DEBUG` level to logging. Deprecated `FINE`. Ability to restrict `DEBUG` level on `live` mode. [Read More](https://github.com/paypal/PayPal-PHP-SDK/wiki/Logging). diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/composer.json b/_sakura/vendor/paypal/rest-api-sdk-php/composer.json index 488ef2d..1c2ab95 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/composer.json +++ b/_sakura/vendor/paypal/rest-api-sdk-php/composer.json @@ -4,7 +4,7 @@ "keywords": ["paypal", "payments", "rest", "sdk"], "type": "library", "license": "Apache2", - "homepage": "https://github.com/paypal/rest-api-sdk-php", + "homepage": "http://paypal.github.io/PayPal-PHP-SDK/", "authors": [ { "name": "PayPal", diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCard.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCard.php index 2a98fbb..e528272 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCard.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCard.php @@ -3,9 +3,9 @@ namespace PayPal\Api; use PayPal\Common\PayPalResourceModel; +use PayPal\Transport\PayPalRestCall; use PayPal\Validation\ArgumentValidator; use PayPal\Rest\ApiContext; -use PayPal\Transport\PayPalRestCall; /** * Class CreditCard @@ -24,10 +24,14 @@ use PayPal\Transport\PayPalRestCall; * @property string last_name * @property \PayPal\Api\Address billing_address * @property string external_customer_id + * @property string merchant_id + * @property string payer_id + * @property string external_card_id * @property string state - * @property string valid_until * @property string create_time * @property string update_time + * @property string valid_until + * @property \PayPal\Api\Links[] links */ class CreditCard extends PayPalResourceModel { @@ -78,7 +82,8 @@ class CreditCard extends PayPalResourceModel } /** - * Type of the Card (eg. Visa, Mastercard, etc.). + * Type of the Card. Currently supporting Visa, Mastercard, Amex, Discover and Maestro + * Valid Values: ["visa", "mastercard", "amex", "discover", "maestro"] * * @param string $type * @@ -91,7 +96,7 @@ class CreditCard extends PayPalResourceModel } /** - * Type of the Card (eg. Visa, Mastercard, etc.). + * Type of the Card. Currently supporting Visa, Mastercard, Amex, Discover and Maestro * * @return string */ @@ -261,6 +266,75 @@ class CreditCard extends PayPalResourceModel return $this->external_customer_id; } + /** + * A user provided, optional convenvience field that functions as a unique identifier for the merchant on behalf of whom this credit card is being stored for. Note that this has no relation to PayPal merchant id + * + * @param string $merchant_id + * + * @return $this + */ + public function setMerchantId($merchant_id) + { + $this->merchant_id = $merchant_id; + return $this; + } + + /** + * A user provided, optional convenvience field that functions as a unique identifier for the merchant on behalf of whom this credit card is being stored for. Note that this has no relation to PayPal merchant id + * + * @return string + */ + public function getMerchantId() + { + return $this->merchant_id; + } + + /** + * A unique identifier that you can assign and track when storing a credit card or using a stored credit card. This ID can help to avoid unintentional use or misuse of credit cards. This ID can be any value you would like to associate with the saved card, such as a UUID, username, or email address. Required when using a stored credit card if a payer_id was originally provided when storing the credit card in vault. + * @deprecated This is being deprecated in favor of the `external_customer_id` property. + * @param string $payer_id + * + * @return $this + */ + public function setPayerId($payer_id) + { + $this->payer_id = $payer_id; + return $this; + } + + /** + * A unique identifier that you can assign and track when storing a credit card or using a stored credit card. This ID can help to avoid unintentional use or misuse of credit cards. This ID can be any value you would like to associate with the saved card, such as a UUID, username, or email address. Required when using a stored credit card if a payer_id was originally provided when storing the credit card in vault. + * @deprecated This is being deprecated in favor of the `external_customer_id` property. + * @return string + */ + public function getPayerId() + { + return $this->payer_id; + } + + /** + * A unique identifier of the bank account resource. Generated and provided by the facilitator so it can be used to restrict the usage of the bank account to the specific merchant. + * + * @param string $external_card_id + * + * @return $this + */ + public function setExternalCardId($external_card_id) + { + $this->external_card_id = $external_card_id; + return $this; + } + + /** + * A unique identifier of the bank account resource. Generated and provided by the facilitator so it can be used to restrict the usage of the bank account to the specific merchant. + * + * @return string + */ + public function getExternalCardId() + { + return $this->external_card_id; + } + /** * State of the funding instrument. * Valid Values: ["expired", "ok"] @@ -285,6 +359,52 @@ class CreditCard extends PayPalResourceModel return $this->state; } + /** + * Resource creation time as ISO8601 date-time format (ex: 1994-11-05T13:15:30Z) that indicates creation time. + * + * @param string $create_time + * + * @return $this + */ + public function setCreateTime($create_time) + { + $this->create_time = $create_time; + return $this; + } + + /** + * Resource creation time as ISO8601 date-time format (ex: 1994-11-05T13:15:30Z) that indicates creation time. + * + * @return string + */ + public function getCreateTime() + { + return $this->create_time; + } + + /** + * Resource creation time as ISO8601 date-time format (ex: 1994-11-05T13:15:30Z) that indicates the updation time. + * + * @param string $update_time + * + * @return $this + */ + public function setUpdateTime($update_time) + { + $this->update_time = $update_time; + return $this; + } + + /** + * Resource creation time as ISO8601 date-time format (ex: 1994-11-05T13:15:30Z) that indicates the updation time. + * + * @return string + */ + public function getUpdateTime() + { + return $this->update_time; + } + /** * Date/Time until this resource can be used fund a payment. * @@ -308,52 +428,6 @@ class CreditCard extends PayPalResourceModel return $this->valid_until; } - /** - * Time the resource was created in UTC ISO8601 format. - * - * @param string $create_time - * - * @return $this - */ - public function setCreateTime($create_time) - { - $this->create_time = $create_time; - return $this; - } - - /** - * Time the resource was created in UTC ISO8601 format. - * - * @return string - */ - public function getCreateTime() - { - return $this->create_time; - } - - /** - * Time the resource was created in UTC ISO8601 format. - * - * @param string $update_time - * - * @return $this - */ - public function setUpdateTime($update_time) - { - $this->update_time = $update_time; - return $this; - } - - /** - * Time the resource was created in UTC ISO8601 format. - * - * @return string - */ - public function getUpdateTime() - { - return $this->update_time; - } - /** * Creates a new Credit Card Resource (aka Tokenize). * @@ -448,4 +522,43 @@ class CreditCard extends PayPalResourceModel return $this; } + /** + * Retrieves a list of Credit Card resources. + * + * @param array $params + * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials. + * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls + * @return CreditCardList + */ + public static function all($params, $apiContext = null, $restCall = null) + { + if (is_null($params)) { + $params = array(); + } + ArgumentValidator::validate($params, 'params'); + $payLoad = ""; + $allowedParams = array( + 'page_size' => 1, + 'page' => 1, + 'start_time' => 1, + 'end_time' => 1, + 'sort_order' => 1, + 'sort_by' => 1, + 'merchant_id' => 1, + 'external_card_id' => 1, + 'external_customer_id' => 1, + ); + $json = self::executeCall( + "/v1/vault/credit-cards" . "?" . http_build_query(array_intersect_key($params, $allowedParams)), + "GET", + $payLoad, + null, + $apiContext, + $restCall + ); + $ret = new CreditCardList(); + $ret->fromJson($json); + return $ret; + } + } diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCardList.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCardList.php index fa92e9e..97ba6aa 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCardList.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/CreditCardList.php @@ -2,7 +2,7 @@ namespace PayPal\Api; -use PayPal\Common\PayPalModel; +use PayPal\Common\PayPalResourceModel; /** * Class CreditCardList @@ -11,22 +11,23 @@ use PayPal\Common\PayPalModel; * * @package PayPal\Api * - * @property \PayPal\Api\CreditCard[] credit_cards - * @property int count - * @property string next_id + * @property \PayPal\Api\CreditCard[] items + * @property \PayPal\Api\Links[] links + * @property int total_items + * @property int total_pages */ -class CreditCardList extends PayPalModel +class CreditCardList extends PayPalResourceModel { /** * A list of credit card resources * - * @param \PayPal\Api\CreditCard[] $credit_cards + * @param \PayPal\Api\CreditCard[] $items * * @return $this */ - public function setCreditCards($credit_cards) + public function setItems($items) { - $this->{"credit-cards"} = $credit_cards; + $this->items = $items; return $this; } @@ -35,85 +36,85 @@ class CreditCardList extends PayPalModel * * @return \PayPal\Api\CreditCard[] */ - public function getCreditCards() + public function getItems() { - return $this->{"credit-cards"}; + return $this->items; } /** - * Append CreditCards to the list. + * Append Items to the list. * * @param \PayPal\Api\CreditCard $creditCard * @return $this */ - public function addCreditCard($creditCard) + public function addItem($creditCard) { - if (!$this->getCreditCards()) { - return $this->setCreditCards(array($creditCard)); + if (!$this->getItems()) { + return $this->setItems(array($creditCard)); } else { - return $this->setCreditCards( - array_merge($this->getCreditCards(), array($creditCard)) + return $this->setItems( + array_merge($this->getItems(), array($creditCard)) ); } } /** - * Remove CreditCards from the list. + * Remove Items from the list. * * @param \PayPal\Api\CreditCard $creditCard * @return $this */ - public function removeCreditCard($creditCard) + public function removeItem($creditCard) { - return $this->setCreditCards( - array_diff($this->getCreditCards(), array($creditCard)) + return $this->setItems( + array_diff($this->getItems(), array($creditCard)) ); } /** - * Number of items returned in each range of results. Note that the last results range could have fewer items than the requested number of items. + * Total number of items present in the given list. Note that the number of items might be larger than the records in the current page. * - * @param int $count + * @param int $total_items * * @return $this */ - public function setCount($count) + public function setTotalItems($total_items) { - $this->count = $count; + $this->total_items = $total_items; return $this; } /** - * Number of items returned in each range of results. Note that the last results range could have fewer items than the requested number of items. + * Total number of items present in the given list. Note that the number of items might be larger than the records in the current page. * * @return int */ - public function getCount() + public function getTotalItems() { - return $this->count; + return $this->total_items; } /** - * Identifier of the next element to get the next range of results. + * Total number of pages that exist, for the total number of items, with the given page size. * - * @param string $next_id + * @param int $total_pages * * @return $this */ - public function setNextId($next_id) + public function setTotalPages($total_pages) { - $this->next_id = $next_id; + $this->total_pages = $total_pages; return $this; } /** - * Identifier of the next element to get the next range of results. + * Total number of pages that exist, for the total number of items, with the given page size. * - * @return string + * @return int */ - public function getNextId() + public function getTotalPages() { - return $this->next_id; + return $this->total_pages; } } diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/InvoiceItem.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/InvoiceItem.php index 14cfe9b..3375762 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/InvoiceItem.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/InvoiceItem.php @@ -3,6 +3,8 @@ namespace PayPal\Api; use PayPal\Common\PayPalModel; +use PayPal\Converter\FormatConverter; +use PayPal\Validation\NumericValidator; /** * Class InvoiceItem @@ -70,12 +72,14 @@ class InvoiceItem extends PayPalModel /** * Quantity of the item. Range of 0 to 9999.999. * - * @param \PayPal\Api\number $quantity + * @param string|double $quantity * * @return $this */ public function setQuantity($quantity) { + NumericValidator::validate($quantity, "Percent"); + $quantity = FormatConverter::formatToPrice($quantity); $this->quantity = $quantity; return $this; } @@ -83,7 +87,7 @@ class InvoiceItem extends PayPalModel /** * Quantity of the item. Range of 0 to 9999.999. * - * @return \PayPal\Api\number + * @return string */ public function getQuantity() { diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Patch.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Patch.php index 9420a0e..739ff9c 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Patch.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Patch.php @@ -19,8 +19,8 @@ use PayPal\Common\PayPalModel; class Patch extends PayPalModel { /** - * Patch operation to perform.Value required for add & remove operation can be any JSON value. - * Valid Values: ["add", "remove", "replace"] + * The operation to perform. + * Valid Values: ["add", "remove", "replace", "move", "copy", "test"] * * @param string $op * @@ -33,7 +33,7 @@ class Patch extends PayPalModel } /** - * Patch operation to perform.Value required for add & remove operation can be any JSON value. + * The operation to perform. * * @return string */ @@ -43,7 +43,7 @@ class Patch extends PayPalModel } /** - * string containing a JSON-Pointer value that references a location within the target document (the target location) where the operation is performed. + * String containing a JSON-Pointer value that references a location within the target document where the operation is performed. * * @param string $path * @@ -56,7 +56,7 @@ class Patch extends PayPalModel } /** - * string containing a JSON-Pointer value that references a location within the target document (the target location) where the operation is performed. + * String containing a JSON-Pointer value that references a location within the target document where the operation is performed. * * @return string */ @@ -89,7 +89,7 @@ class Patch extends PayPalModel } /** - * A string containing a JSON Pointer value that references the location in the target document to move the value from. + * A string containing a JSON Pointer value that references the location in the target document from which to move the value. Required for use where op=move. * * @param string $from * @@ -102,7 +102,7 @@ class Patch extends PayPalModel } /** - * A string containing a JSON Pointer value that references the location in the target document to move the value from. + * A string containing a JSON Pointer value that references the location in the target document from which to move the value. Required for use where op=move. * * @return string */ diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Tax.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Tax.php index d5b99ab..ce6b9f2 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Tax.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/Tax.php @@ -3,6 +3,8 @@ namespace PayPal\Api; use PayPal\Common\PayPalModel; +use PayPal\Converter\FormatConverter; +use PayPal\Validation\NumericValidator; /** * Class Tax @@ -67,12 +69,14 @@ class Tax extends PayPalModel /** * Rate of the specified tax. Range of 0.001 to 99.999. * - * @param \PayPal\Api\number $percent + * @param string|double $percent * * @return $this */ public function setPercent($percent) { + NumericValidator::validate($percent, "Percent"); + $percent = FormatConverter::formatToPrice($percent); $this->percent = $percent; return $this; } @@ -80,7 +84,7 @@ class Tax extends PayPalModel /** * Rate of the specified tax. Range of 0.001 to 99.999. * - * @return \PayPal\Api\number + * @return string */ public function getPercent() { diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/WebhookEvent.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/WebhookEvent.php index 353f4e2..5c786f9 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/WebhookEvent.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Api/WebhookEvent.php @@ -2,12 +2,12 @@ namespace PayPal\Api; -use PayPal\Common\PayPalModel; use PayPal\Common\PayPalResourceModel; +use PayPal\Exception\PayPalConnectionException; use PayPal\Validation\ArgumentValidator; -use PayPal\Api\WebhookEventList; use PayPal\Rest\ApiContext; use PayPal\Transport\PayPalRestCall; +use PayPal\Validation\JsonValidator; /** * Class WebhookEvent @@ -163,6 +163,44 @@ class WebhookEvent extends PayPalResourceModel return $this->resource; } + /** + * Validates Received Event from Webhook, and returns the webhook event object. Because security verifications by verifying certificate chain is not enabled in PHP yet, + * we need to fallback to default behavior of retrieving the ID attribute of the data, and make a separate GET call to PayPal APIs, to retrieve the data. + * This is important to do again, as hacker could have faked the data, and the retrieved data cannot be trusted without either doing client side security validation, or making a separate call + * to PayPal APIs to retrieve the actual data. This limits the hacker to mimick a fake data, as hacker wont be able to predict the Id correctly. + * + * NOTE: PLEASE DO NOT USE THE DATA PROVIDED IN WEBHOOK DIRECTLY, AS HACKER COULD PASS IN FAKE DATA. IT IS VERY IMPORTANT THAT YOU RETRIEVE THE ID AND MAKE A SEPARATE CALL TO PAYPAL API. + * + * @param string $body + * @param ApiContext $apiContext + * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls + * @return WebhookEvent + * @throws \InvalidArgumentException if input arguments are incorrect, or Id is not found. + * @throws PayPalConnectionException if any exception from PayPal APIs other than not found is sent. + */ + public static function validateAndGetReceivedEvent($body, $apiContext = null, $restCall = null) + { + if ($body == null | empty($body)){ + throw new \InvalidArgumentException("Body cannot be null or empty"); + } + if (!JsonValidator::validate($body, true)) { + throw new \InvalidArgumentException("Request Body is not a valid JSON."); + } + $object = new WebhookEvent($body); + if ($object->getId() == null) { + throw new \InvalidArgumentException("Id attribute not found in JSON. Possible reason could be invalid JSON Object"); + } + try { + return self::get($object->getId(), $apiContext, $restCall); + } catch(PayPalConnectionException $ex) { + if ($ex->getCode() == 404) { + // It means that the given webhook event Id is not found for this merchant. + throw new \InvalidArgumentException("Webhook Event Id provided in the data is incorrect. This could happen if anyone other than PayPal is faking the incoming webhook data."); + } + throw $ex; + } + } + /** * Retrieves the Webhooks event resource identified by event_id. Can be used to retrieve the payload for an event. * diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalModel.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalModel.php index d90287a..e216577 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalModel.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalModel.php @@ -58,7 +58,7 @@ class PayPalModel } /** - * Returns a list of Object from Array or Json String. It is generally used when you json + * Returns a list of Object from Array or Json String. It is generally used when your json * contains an array of this object * * @param mixed $data Array object or json string representation @@ -66,21 +66,38 @@ class PayPalModel */ public static function getList($data) { - if (!is_array($data) && JsonValidator::validate($data)) { - //Convert to Array if Json Data Sent - $data = json_decode($data, true); + // Return Null if Null + if ($data === null) { return null; } + + if (is_a($data, get_class(new \stdClass()))) { + //This means, root element is object + return new static(json_encode($data)); } - if (!ArrayUtil::isAssocArray($data)) { - $list = array(); - //This means, root element is array - foreach ($data as $k => $v) { - $obj = new static; - $obj->fromArray($v); - $list[] = $obj; + + $list = array(); + + if (is_array($data)) { + $data = json_encode($data); + } + + if (JsonValidator::validate($data)) { + // It is valid JSON + $decoded = json_decode($data); + if ($decoded === null) { + return $list; + } + if (is_array($decoded)) { + foreach ($decoded as $k => $v) { + $list[] = self::getList($v); + } + } + if (is_a($decoded, get_class(new \stdClass()))) { + //This means, root element is object + $list[] = new static(json_encode($decoded)); } - return $list; } - return array(); + + return $list; } /** @@ -106,7 +123,7 @@ class PayPalModel public function __set($key, $value) { ModelAccessorValidator::validate($this, $this->convertToCamelCase($key)); - if (!is_array($value) && $value == null) { + if (!is_array($value) && $value === null) { $this->__unset($key); } else { $this->_propMap[$key] = $value; diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalConstants.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalConstants.php index a92ebd6..077120e 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalConstants.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalConstants.php @@ -12,7 +12,7 @@ class PayPalConstants { const SDK_NAME = 'PayPal-PHP-SDK'; - const SDK_VERSION = '1.3.2'; + const SDK_VERSION = '1.5.0'; /** * Approval URL for Payment diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php index 57bf623..ffc05d2 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php @@ -95,6 +95,7 @@ class PayPalHttpConnection curl_setopt($ch, CURLOPT_POST, true); case 'PUT': case 'PATCH': + case 'DELETE': curl_setopt($ch, CURLOPT_POSTFIELDS, $data); break; } diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalLoggingManager.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalLoggingManager.php index 0d430ac..5d2ae0f 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalLoggingManager.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalLoggingManager.php @@ -100,7 +100,7 @@ class PayPalLoggingManager if ($this->isLoggingEnabled) { $config = PayPalConfigManager::getInstance()->getConfigHashmap(); // Check if logging in live - if ($config['mode'] == 'live') { + if (array_key_exists('mode', $config) && $config['mode'] == 'live') { // Live should not have logging level above INFO. if ($this->loggingLevel >= PayPalLoggingLevel::INFO) { // If it is at Debug Level, throw an warning in the log. diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Rest/ApiContext.php b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Rest/ApiContext.php index b691571..a1be160 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Rest/ApiContext.php +++ b/_sakura/vendor/paypal/rest-api-sdk-php/lib/PayPal/Rest/ApiContext.php @@ -83,7 +83,7 @@ class ApiContext * * @return string */ - public function getrequestId() + public function getRequestId() { if ($this->requestId == null) { $this->requestId = $this->generateRequestId(); @@ -102,7 +102,7 @@ class ApiContext public function resetRequestId() { $this->requestId = $this->generateRequestId(); - return $this->getrequestId(); + return $this->getRequestId(); } /** diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/release_notes.md b/_sakura/vendor/paypal/rest-api-sdk-php/release_notes.md index 1933c56..c44ce5d 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/release_notes.md +++ b/_sakura/vendor/paypal/rest-api-sdk-php/release_notes.md @@ -1,5 +1,17 @@ PayPal PHP SDK release notes ============================ +v1.5.0 +---- +* Enabled Vault List API +* Added More Fields to Vault Credit Card Object +* Minor Fixes + +v1.4.0 +---- +* Ability to validate Webhook +* Fixes to Logging Manager to skip if mode is not set +* SDK updates and fixes + v1.3.2 ---- * Minor Fix for Agreement Details diff --git a/_sakura/vendor/paypal/rest-api-sdk-php/sample/README.md b/_sakura/vendor/paypal/rest-api-sdk-php/sample/README.md index ce1e81a..286f0f6 100644 --- a/_sakura/vendor/paypal/rest-api-sdk-php/sample/README.md +++ b/_sakura/vendor/paypal/rest-api-sdk-php/sample/README.md @@ -1,57 +1,71 @@ -Rest API Samples -=================== +# Rest API Samples -This sample project is a simple web app that you can explore to understand what the payment APIs can do for you. +![Home Image](https://raw.githubusercontent.com/wiki/paypal/PayPal-PHP-SDK/images/homepage.jpg) -To try out the sample, run `composer update --no-dev` from the PayPal-PHP-SDK folder and you are all set. +These examples are created to experiment with the PayPal-PHP-SDK capabilities. Each examples are designed to demonstrate the default use-cases in each segment. -#### Running Samples +This sample project is a simple web app that you can explore to understand what each PayPal APIs can do for you. Irrespective of how you [installed your SDK](https://github.com/paypal/PayPal-PHP-SDK/wiki/Installation), you should be able to get the samples running by following the instructions below: -##### PHP 5.4 or higher -* If you are running PHP 5.4 or greater, PHP provides a built-in support for hosting PHP sites. -* The fastest way to get it running is -```bash -php -f sample/index.php -``` -* This would get the [built-in web server](http://php.net/manual/en/features.commandline.webserver.php) started, and hosted on `http://localhost:5000' +## Viewing Sample Code +You can [view sample source codes here](http://paypal.github.io/PayPal-PHP-SDK/sample/). However, we recommend you run samples locally to get a better idea. -```bash -LM-AUN-00876403:PayPal-PHP-SDK japatel$ php -f sample/index.php -PHP 5.5.14 Development Server started at Wed Nov 19 21:07:52 2014 -Listening on http://localhost:5000 -Document root is /Users/japatel/Documents/workspace/Server-SDK/PayPal-PHP-SDK/sample -Press Ctrl-C to quit. -[Wed Nov 19 21:07:56 2014] ::1:60826 [200]: /index.php -... -``` +## Instructions -##### PHP 5.3 or less +If you are running PHP 5.4 or greater, PHP provides a [ built-in support ]( http://php.net/manual/en/features.commandline.webserver.php) for hosting PHP sites. -* You could host the entire project in your local web server, by using tools like [MAMP](http://www.mamp.info/en/) or [XAMPP](https://www.apachefriends.org/index.html). -* Once done, you could easily open the samples by opening the matching URL. For e.g.: -`http://localhost/PayPal-PHP-SDK/sample/index.html` +Note: The root directory for composer based download would be `vendor` and for direct download it would be `PayPal-PHP-SDK`. Please update the commands accordingly. -You should see a sample dashboard page as shown below: -![Web Output!](/sample/images/sample_web.png) +1. Run `php -f PayPal-PHP-SDK/paypal/rest-api-sdk-php/sample/index.php` from your project root directory. +2. This would host a PHP server at `localhost:5000`. The output should look something like this: + + ``` + ', $pos); - if ($gt === false) { - $gt = strlen($body); - } else { - $gt += 2; - } - return array(false, false, false, $lt, $gt); + $gt = strpos($body, '-->', $pos); + if ($gt === false) { + $gt = strlen($body); } else { - $gt = tln_findnxstr($body, $pos, '>'); - return array(false, false, false, $lt, $gt); + $gt += 2; } - break; - default: - /** - * Assume tagtype 1 for now. If it's type 3, we'll switch values - * later. - */ - $tagtype = 1; - break; + 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; } /** @@ -223,48 +224,48 @@ function tln_getnxtag($body, $offset) /** * $match can be either of these: - * '>' indicating the end of the tag entirely. + * '>' indicating the end of the tag entirely. * '\s' indicating the end of the tag name. - * '/' indicating that this is type-3 xhtml tag. + * '/' 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: . 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; - } + case '/': + /** + * This is an xhtml-style tag with a closing / at the + * end, like so: . 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: + case '>': + return array($tagname, false, $tagtype, $lt, $pos); + break; + default: + /** + * Check if it's whitespace + */ + if (!preg_match('/\s/', $match)) { /** - * Check if it's whitespace + * This is an invalid tag! Look for the next closing ">". */ - 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); - } + $gt = tln_findnxstr($body, $lt, '>'); + return array(false, false, false, $lt, $gt); + } + break; } /** * At this point we're here: - * + * * \-------^ * * At this point we loop in order to find all attributes. @@ -284,8 +285,7 @@ function tln_getnxtag($body, $offset) * the end of the tag. */ $matches = array(); - preg_match('%^(\s*)(>|/>)%s', substr($body, $pos), $matches); - if (isset($matches[0]) && $matches[0]) { + if (preg_match('%^(\s*)(>|/>)%s', substr($body, $pos), $matches)) { /** * Yep. So we did. */ @@ -301,13 +301,13 @@ function tln_getnxtag($body, $offset) * There are several types of attributes, with optional * [:space:] between members. * Type 1: - * attrname[:space:]=[:space:]'CDATA' + * attrname[:space:]=[:space:]'CDATA' * Type 2: - * attrname[:space:]=[:space:]"CDATA" + * attrname[:space:]=[:space:]"CDATA" * Type 3: - * attr[:space:]=[:space:]CDATA + * attr[:space:]=[:space:]CDATA * Type 4: - * attrname + * attrname * * We leave types 1 and 2 the same, type 3 we check for * '"' and convert to """ if needed, then wrap in @@ -326,102 +326,99 @@ function tln_getnxtag($body, $offset) /** * 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 + * '>' 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. + * anything else means the attribute is invalid. */ switch ($match) { - case '/': - /** - * This is an xhtml-style tag with a closing / at the - * end, like so: . 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; - } + case '/': + /** + * This is an xhtml-style tag with a closing / at the + * end, like so: . 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. - */ + 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); - $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. + * Here are 3 possibilities: + * "'" attribute type 1 + * '"' attribute type 2 + * everything else is the content of tag type 3 */ - 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 == '\'') { + $quot = substr($body, $pos, 1); + if ($quot == '\'') { $regary = tln_findnxreg($body, $pos + 1, '\''); - if ($regary == false) { - return array(false, false, false, $lt, strlen($body)); - } - list($pos, $attval, $match) = $regary; - $pos++; - $attary{$attname} = '\'' . $attval . '\''; - } else { - if ($quot == '"') { - $regary = tln_findnxreg($body, $pos + 1, '\"'); - if ($regary == false) { - return array(false, false, false, $lt, strlen($body)); - } - list($pos, $attval, $match) = $regary; - $pos++; - $attary{$attname} = '"' . $attval . '"'; - } else { - /** - * These are hateful. Look for \s, or >. - */ - $regary = tln_findnxreg($body, $pos, '[\s>]'); - if ($regary == false) { - return array(false, false, false, $lt, strlen($body)); - } - list($pos, $attval, $match) = $regary; - /** - * If it's ">" it will be caught at the top. - */ - $attval = preg_replace('/\"/s', '"', $attval); - $attary{$attname} = '"' . $attval . '"'; - } + if ($regary == false) { + return array(false, false, false, $lt, strlen($body)); } + list($pos, $attval, $match) = $regary; + $pos++; + $attary{$attname} = '\'' . $attval . '\''; + } elseif ($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 (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); + /** + * These are hateful. Look for \s, or >. + */ + $regary = tln_findnxreg($body, $pos, '[\s>]'); + if ($regary == false) { + return array(false, false, false, $lt, strlen($body)); } + list($pos, $attval, $match) = $regary; + /** + * If it's ">" it will be caught at the top. + */ + $attval = preg_replace('/\"/s', '"', $attval); + $attary{$attname} = '"' . $attval . '"'; } + } elseif (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); + } + break; } } /** @@ -512,14 +509,18 @@ function tln_unspace(&$attvalue) * @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. + * @param string $trans_image_path + * @param boolean $block_external_images + * @return Array with modified attributes. */ function tln_fixatts( $tagname, $attary, $rm_attnames, $bad_attvals, - $add_attr_to_tag + $add_attr_to_tag, + $trans_image_path, + $block_external_images ) { while (list($attname, $attvalue) = each($attary)) { /** @@ -538,7 +539,12 @@ function tln_fixatts( /** * Remove any backslashes, entities, or extraneous whitespace. */ + $oldattvalue = $attvalue; tln_defang($attvalue); + if ($attname == 'style' && $attvalue !== $oldattvalue) { + $attvalue = "idiocy"; + $attary{$attname} = $attvalue; + } tln_unspace($attvalue); /** @@ -560,12 +566,26 @@ function tln_fixatts( $newvalue = preg_replace($valmatch, $valrepl, $attvalue); if ($newvalue != $attvalue) { $attary{$attname} = $newvalue; + $attvalue = $newvalue; } } } } } - } + if ($attname == 'style') { + if (preg_match('/[\0-\37\200-\377]+/', $attvalue)) { + $attary{$attname} = '"disallowed character"'; + } + preg_match_all("/url\s*\((.+)\)/si", $attvalue, $aMatch); + if (count($aMatch)) { + foreach($aMatch[1] as $sMatch) { + $urlvalue = $sMatch; + tln_fixurl($attname, $urlvalue, $trans_image_path, $block_external_images); + $attary{$attname} = str_replace($sMatch, $urlvalue, $attvalue); + } + } + } + } /** * See if we need to append any attributes to this tag. */ @@ -577,6 +597,240 @@ function tln_fixatts( return $attary; } +function tln_fixurl($attname, &$attvalue, $trans_image_path, $block_external_images) +{ + $sQuote = '"'; + $attvalue = trim($attvalue); + if ($attvalue && ($attvalue[0] =='"'|| $attvalue[0] == "'")) { + // remove the double quotes + $sQuote = $attvalue[0]; + $attvalue = trim(substr($attvalue,1,-1)); + } + + /** + * Replace empty src tags with the blank image. src is only used + * for frames, images, and image inputs. Doing a replace should + * not affect them working as should be, however it will stop + * IE from being kicked off when src for img tags are not set + */ + if ($attvalue == '') { + $attvalue = $sQuote . $trans_image_path . $sQuote; + } else { + // first, disallow 8 bit characters and control characters + if (preg_match('/[\0-\37\200-\377]+/',$attvalue)) { + switch ($attname) { + case 'href': + $attvalue = $sQuote . 'http://invalid-stuff-detected.example.com' . $sQuote; + break; + default: + $attvalue = $sQuote . $trans_image_path . $sQuote; + break; + } + } else { + $aUrl = parse_url($attvalue); + if (isset($aUrl['scheme'])) { + switch(strtolower($aUrl['scheme'])) { + case 'mailto': + case 'http': + case 'https': + case 'ftp': + if ($attname != 'href') { + if ($block_external_images == true) { + $attvalue = $sQuote . $trans_image_path . $sQuote; + } else { + if (!isset($aUrl['path'])) { + $attvalue = $sQuote . $trans_image_path . $sQuote; + } + } + } else { + $attvalue = $sQuote . $attvalue . $sQuote; + } + break; + case 'outbind': + $attvalue = $sQuote . $attvalue . $sQuote; + break; + case 'cid': + $attvalue = $sQuote . $attvalue . $sQuote; + break; + default: + $attvalue = $sQuote . $trans_image_path . $sQuote; + break; + } + } else { + if (!isset($aUrl['path']) || $aUrl['path'] != $trans_image_path) { + $$attvalue = $sQuote . $trans_image_path . $sQuote; + } + } + } + } +} + +function tln_fixstyle($body, $pos, $trans_image_path, $block_external_images) +{ + $me = 'tln_fixstyle'; + // workaround for in between comments + $iCurrentPos = $pos; + $content = ''; + $sToken = ''; + $bSucces = false; + $bEndTag = false; + for ($i=$pos,$iCount=strlen($body);$i<$iCount;++$i) { + $char = $body{$i}; + switch ($char) { + case '<': + $sToken = $char; + break; + case '/': + if ($sToken == '<') { + $sToken .= $char; + $bEndTag = true; + } else { + $content .= $char; + } + break; + case '>': + if ($bEndTag) { + $sToken .= $char; + if (preg_match('/\<\/\s*style\s*\>/i',$sToken,$aMatch)) { + $newpos = $i + 1; + $bSucces = true; + break 2; + } else { + $content .= $sToken; + } + $bEndTag = false; + } else { + $content .= $char; + } + break; + case '!': + if ($sToken == '<') { + // possible comment + if (isset($body{$i+2}) && substr($body,$i,3) == '!--') { + $i = strpos($body,'-->',$i+3); + if ($i === false) { // no end comment + $i = strlen($body); + } + $sToken = ''; + } + } else { + $content .= $char; + } + break; + default: + if ($bEndTag) { + $sToken .= $char; + } else { + $content .= $char; + } + break; + } + } + if ($bSucces == FALSE){ + return array(FALSE, strlen($body)); + } + + + + /** + * First look for general BODY style declaration, which would be + * like so: + * body {background: blah-blah} + * and change it to .bodyclass so we can just assign it to a
+ */ + $content = preg_replace("|body(\s*\{.*?\})|si", ".bodyclass\\1", $content); + + $trans_image_path = $trans_image_path; + + /** + * Fix url('blah') declarations. + */ + // $content = preg_replace("|url\s*\(\s*([\'\"])\s*\S+script\s*:.*?([\'\"])\s*\)|si", + // "url(\\1$trans_image_path\\2)", $content); + + // first check for 8bit sequences and disallowed control characters + if (preg_match('/[\16-\37\200-\377]+/',$content)) { + $content = ''; + return array($content, $newpos); + } + + // remove @import line + $content = preg_replace("/^\s*(@import.*)$/mi","\n\n",$content); + + $content = preg_replace("/(\\\\)?u(\\\\)?r(\\\\)?l(\\\\)?/i", 'url', $content); + preg_match_all("/url\s*\((.+)\)/si",$content,$aMatch); + if (count($aMatch)) { + $aValue = $aReplace = array(); + foreach($aMatch[1] as $sMatch) { + // url value + $urlvalue = $sMatch; + tln_fixurl('style',$urlvalue, $trans_image_path, $block_external_images); + $aValue[] = $sMatch; + $aReplace[] = $urlvalue; + } + $content = str_replace($aValue,$aReplace,$content); + } + + /** + * Remove any backslashes, entities, and extraneous whitespace. + */ + $contentTemp = $content; + tln_defang($contentTemp); + tln_unspace($contentTemp); + + $match = Array('/\/\*.*\*\//', + '/expression/i', + '/behaviou*r/i', + '/binding/i', + '/include-source/i', + '/javascript/i', + '/script/i', + '/position/i'); + $replace = Array('','idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy', 'idiocy', ''); + $contentNew = preg_replace($match, $replace, $contentTemp); + if ($contentNew !== $contentTemp) { + $content = $contentNew; + } + return array($content, $newpos); +} + +function tln_body2div($attary, $trans_image_path) +{ + $me = 'tln_body2div'; + $divattary = array('class' => "'bodyclass'"); + $text = '#000000'; + $has_bgc_stl = $has_txt_stl = false; + $styledef = ''; + if (is_array($attary) && sizeof($attary) > 0){ + foreach ($attary as $attname=>$attvalue){ + $quotchar = substr($attvalue, 0, 1); + $attvalue = str_replace($quotchar, "", $attvalue); + switch ($attname){ + case 'background': + $styledef .= "background-image: url('$trans_image_path'); "; + break; + case 'bgcolor': + $has_bgc_stl = true; + $styledef .= "background-color: $attvalue; "; + break; + case 'text': + $has_txt_stl = true; + $styledef .= "color: $attvalue; "; + break; + } + } + // Outlook defines a white bgcolor and no text color. This can lead to + // white text on a white bg with certain themes. + if ($has_bgc_stl && !$has_txt_stl) { + $styledef .= "color: $text; "; + } + if (strlen($styledef) > 0){ + $divattary{"style"} = "\"$styledef\""; + } + } + return $divattary; +} + /** * * @param string $body The HTML you wish to filter @@ -587,6 +841,9 @@ function tln_fixatts( * @param array $rm_attnames see description above * @param array $bad_attvals see description above * @param array $add_attr_to_tag see description above + * @param string $trans_image_path + * @param boolean $block_external_images + * @return string Sanitized html safe to show on your pages. */ function tln_sanitize( @@ -597,7 +854,9 @@ function tln_sanitize( $force_tag_closing, $rm_attnames, $bad_attvals, - $add_attr_to_tag + $add_attr_to_tag, + $trans_image_path, + $block_external_images ) { /** * Normalize rm_tags and rm_tags_with_content. @@ -609,7 +868,7 @@ function tln_sanitize( /** * See if tag_list is of tags to remove or tags to allow. * false means remove these tags - * true means allow these tags + * true means allow these tags */ $curpos = 0; $open_tags = array(); @@ -622,10 +881,32 @@ function tln_sanitize( $body = preg_replace('/&(\{.*?\};)/si', '&\\1', $body); while (($curtag = tln_getnxtag($body, $curpos)) != false) { list($tagname, $attary, $tagtype, $lt, $gt) = $curtag; - $free_content = substr($body, $curpos, $lt - $curpos); - if ($skip_content == false) { + $free_content = substr($body, $curpos, $lt-$curpos); + /** + * Take care of