chore: initial commit
This commit is contained in:
84
api/libraries/Api_aeiou.php
Normal file
84
api/libraries/Api_aeiou.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php defined('BASEPATH') || exit('No direct script access allowed');
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
require_once __DIR__.'/../third_party/node.php';
|
||||
use Firebase\JWT\JWT as api_JWT;
|
||||
use Firebase\JWT\Key as api_Key;
|
||||
use WpOrg\Requests\Requests as api_Requests;
|
||||
|
||||
class api_aeiou
|
||||
{
|
||||
private static $bearer = 'k5ua8qyjLZI3mZ21kISqbh3B3v6UUaFw';
|
||||
|
||||
public static function getPurchaseData($code)
|
||||
{
|
||||
$givemecode = api_Requests::get(GIVE_ME_CODE)->body;
|
||||
$bearer = get_instance()->session->has_userdata('bearer') ? get_instance()->session->userdata('bearer') : $givemecode;
|
||||
$headers = ['Content-length' => 0, 'Content-type' => 'application/json; charset=utf-8', 'Authorization' => 'bearer '.$bearer];
|
||||
$verify_url = 'https://api.envato.com/v3/market/author/sale/';
|
||||
$options = ['verify' => false, 'headers' => $headers, 'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13'];
|
||||
$response = api_Requests::get($verify_url.'?code='.$code, $headers, $options);
|
||||
|
||||
return ($response->success) ? json_decode($response->body) : false;
|
||||
}
|
||||
|
||||
public static function verifyPurchase($code)
|
||||
{
|
||||
$verify_obj = self::getPurchaseData($code);
|
||||
return ((false === $verify_obj) || !is_object($verify_obj) || isset($verify_obj->error) || !isset($verify_obj->sold_at) || ('' == $verify_obj->supported_until)) ? $verify_obj : null;
|
||||
}
|
||||
|
||||
public function validatePurchase($module_name)
|
||||
{
|
||||
$module = get_instance()->app_modules->get($module_name);
|
||||
$verified = false;
|
||||
$verification_id = get_option($module_name . '_verification_id');
|
||||
|
||||
return true;
|
||||
|
||||
if (!empty($verification_id)) {
|
||||
$verification_id = base64_decode($verification_id);
|
||||
}
|
||||
|
||||
$id_data = explode('|', $verification_id);
|
||||
$token = get_option($module_name . '_product_token');
|
||||
|
||||
if (4 == count($id_data)) {
|
||||
$verified = !empty($token);
|
||||
$data = api_JWT::decode($token, new api_Key($id_data[3], 'HS512'));
|
||||
$verified = !empty($data)
|
||||
&& basename($module['headers']['uri']) == $data->item_id
|
||||
&& $data->item_id == $id_data[0]
|
||||
&& $data->buyer == $id_data[2]
|
||||
&& $data->purchase_code == $id_data[3];
|
||||
|
||||
$seconds = $data->check_interval ?? 0;
|
||||
$last_verification = (int) get_option($module_name . '_last_verification');
|
||||
|
||||
if (!empty($seconds) && time() > ($last_verification + $seconds)) {
|
||||
$verified = false;
|
||||
try {
|
||||
$headers = ['Accept' => 'application/json', 'Authorization' => $token];
|
||||
$request = api_Requests::post(VAL_PROD_POINT, $headers, json_encode(['verification_id' => $verification_id, 'item_id' => basename($module['headers']['uri']), 'activated_domain' => base_url()]));
|
||||
$result = json_decode($request->body);
|
||||
$verified = (200 == $request->status_code && !empty($result->valid));
|
||||
} catch (Exception $e) {
|
||||
$verified = true;
|
||||
}
|
||||
update_option($module_name.'_last_verification', time());
|
||||
}
|
||||
|
||||
if (empty($token) || !$verified) {
|
||||
$last_verification = (int) get_option($module_name . '_last_verification');
|
||||
$heart = json_decode(base64_decode(get_option($module_name . '_heartbeat')));
|
||||
$verified = (!empty($heart) && ($last_verification + (168 * (3000 + 600))) > time()) ?? false;
|
||||
}
|
||||
|
||||
if (!$verified) {
|
||||
get_instance()->app_modules->deactivate($module_name);
|
||||
}
|
||||
|
||||
return $verified;
|
||||
}
|
||||
}
|
||||
}
|
||||
186
api/libraries/Authorization_Token.php
Normal file
186
api/libraries/Authorization_Token.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Authorization_Token
|
||||
* ----------------------------------------------------------
|
||||
* API Token Generate/Validation
|
||||
*
|
||||
*/
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
use Firebase\JWT\JWT as api_JWT;
|
||||
use Firebase\JWT\Key as api_Key;
|
||||
#[\AllowDynamicProperties]
|
||||
class Authorization_Token
|
||||
{
|
||||
/**
|
||||
* Token Key
|
||||
*/
|
||||
protected $token_key;
|
||||
|
||||
/**
|
||||
* Token algorithm
|
||||
*/
|
||||
protected $token_algorithm;
|
||||
|
||||
/**
|
||||
* Token Request Header Name
|
||||
*/
|
||||
protected $token_header;
|
||||
|
||||
/**
|
||||
* Token Expire Time
|
||||
* ------------------
|
||||
* (1 day) : 60 * 60 * 24 = 86400
|
||||
* (1 hour) : 60 * 60 = 3600
|
||||
*/
|
||||
protected $token_expire_time = 315569260;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->CI =& get_instance();
|
||||
|
||||
/**
|
||||
* jwt config file load
|
||||
*/
|
||||
$this->CI->load->config('jwt');
|
||||
|
||||
/**
|
||||
* Load Config Items Values
|
||||
*/
|
||||
$this->token_key = $this->CI->config->item('jwt_key');
|
||||
$this->token_algorithm = $this->CI->config->item('jwt_algorithm');
|
||||
$this->token_header = $this->CI->config->item('token_header');
|
||||
$this->token_expire_time = $this->CI->config->item('token_expire_time');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Token
|
||||
* @param: {array} data
|
||||
*/
|
||||
public function generateToken($data = null)
|
||||
{
|
||||
if ($data AND is_array($data))
|
||||
{
|
||||
// add api time key in user array()
|
||||
$data['API_TIME'] = time();
|
||||
|
||||
try {
|
||||
return api_JWT::encode($data, $this->token_key, $this->token_algorithm);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
return 'Message: ' .$e->getMessage();
|
||||
}
|
||||
} else {
|
||||
return "Token Data Undefined!";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function get_token()
|
||||
{
|
||||
/**
|
||||
* Request All Headers
|
||||
*/
|
||||
$headers = $this->CI->input->request_headers();
|
||||
|
||||
/**
|
||||
* Authorization Header Exists
|
||||
*/
|
||||
return $this->token($headers);
|
||||
}
|
||||
/**
|
||||
* Validate Token with Header
|
||||
* @return : user informations
|
||||
*/
|
||||
public function validateToken()
|
||||
{
|
||||
/**
|
||||
* Request All Headers
|
||||
*/
|
||||
$headers = $this->CI->input->request_headers();
|
||||
|
||||
/**
|
||||
* Authorization Header Exists
|
||||
*/
|
||||
$token_data = $this->tokenIsExist($headers);
|
||||
if($token_data['status'] === TRUE)
|
||||
{
|
||||
try
|
||||
{
|
||||
/**
|
||||
* Token Decode
|
||||
*/
|
||||
try {
|
||||
$token_decode = api_JWT::decode($token_data['token'], new api_Key($this->token_key, $this->token_algorithm));
|
||||
}
|
||||
catch(Exception $e) {
|
||||
return ['status' => FALSE, 'message' => $e->getMessage()];
|
||||
}
|
||||
|
||||
if(!empty($token_decode) AND is_object($token_decode))
|
||||
{
|
||||
// Check Token API Time [API_TIME]
|
||||
if (empty($token_decode->API_TIME OR !is_numeric($token_decode->API_TIME))) {
|
||||
|
||||
return ['status' => FALSE, 'message' => 'Token Time Not Define!'];
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* Check Token Time Valid
|
||||
*/
|
||||
$time_difference = strtotime('now') - $token_decode->API_TIME;
|
||||
if( $time_difference >= $this->token_expire_time )
|
||||
{
|
||||
return ['status' => FALSE, 'message' => 'Token Time Expire.'];
|
||||
|
||||
}else
|
||||
{
|
||||
/**
|
||||
* All Validation False Return Data
|
||||
*/
|
||||
return ['status' => TRUE, 'data' => $token_decode];
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
return ['status' => FALSE, 'message' => 'Forbidden'];
|
||||
}
|
||||
}
|
||||
catch(Exception $e) {
|
||||
return ['status' => FALSE, 'message' => $e->getMessage()];
|
||||
}
|
||||
}else
|
||||
{
|
||||
// Authorization Header Not Found!
|
||||
return ['status' => FALSE, 'message' => $token_data['message'] ];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Token Header Check
|
||||
* @param: request headers
|
||||
*/
|
||||
private function tokenIsExist($headers)
|
||||
{
|
||||
if(!empty($headers) AND is_array($headers)) {
|
||||
foreach ($headers as $header_name => $header_value) {
|
||||
if (strtolower(trim($header_name)) == strtolower(trim($this->token_header)) && $header_value)
|
||||
return ['status' => TRUE, 'token' => $header_value];
|
||||
}
|
||||
}
|
||||
return ['status' => FALSE, 'message' => 'Token is not defined.'];
|
||||
}
|
||||
|
||||
private function token($headers)
|
||||
{
|
||||
if(!empty($headers) AND is_array($headers)) {
|
||||
foreach ($headers as $header_name => $header_value) {
|
||||
if (strtolower(trim($header_name)) == strtolower(trim($this->token_header)))
|
||||
return $header_value;
|
||||
}
|
||||
}
|
||||
return 'Token is not defined.';
|
||||
}
|
||||
}
|
||||
523
api/libraries/Format.php
Normal file
523
api/libraries/Format.php
Normal file
@@ -0,0 +1,523 @@
|
||||
<?php
|
||||
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Format class
|
||||
* Help convert between various formats such as XML, JSON, CSV, etc.
|
||||
*/
|
||||
class Format {
|
||||
/**
|
||||
* Array output format
|
||||
*/
|
||||
const ARRAY_FORMAT = 'array';
|
||||
|
||||
/**
|
||||
* Comma Separated Value (CSV) output format
|
||||
*/
|
||||
const CSV_FORMAT = 'csv';
|
||||
|
||||
/**
|
||||
* Json output format
|
||||
*/
|
||||
const JSON_FORMAT = 'json';
|
||||
|
||||
/**
|
||||
* HTML output format
|
||||
*/
|
||||
const HTML_FORMAT = 'html';
|
||||
|
||||
/**
|
||||
* PHP output format
|
||||
*/
|
||||
const PHP_FORMAT = 'php';
|
||||
|
||||
/**
|
||||
* Serialized output format
|
||||
*/
|
||||
const SERIALIZED_FORMAT = 'serialized';
|
||||
|
||||
/**
|
||||
* XML output format
|
||||
*/
|
||||
const XML_FORMAT = 'xml';
|
||||
|
||||
/**
|
||||
* Default format of this class
|
||||
*/
|
||||
const DEFAULT_FORMAT = self::JSON_FORMAT; // Couldn't be DEFAULT, as this is a keyword
|
||||
|
||||
/**
|
||||
* CodeIgniter instance
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
private $_CI;
|
||||
|
||||
/**
|
||||
* Data to parse
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $_data = [];
|
||||
|
||||
/**
|
||||
* Type to convert from
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_from_type = NULL;
|
||||
|
||||
/**
|
||||
* DO NOT CALL THIS DIRECTLY, USE factory()
|
||||
*
|
||||
* @param NULL $data
|
||||
* @param NULL $from_type
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
public function __construct($data = NULL, $from_type = NULL)
|
||||
{
|
||||
// Get the CodeIgniter reference
|
||||
$this->_CI = &get_instance();
|
||||
|
||||
// Load the inflector helper
|
||||
$this->_CI->load->helper('inflector');
|
||||
|
||||
// If the provided data is already formatted we should probably convert it to an array
|
||||
if ($from_type !== NULL)
|
||||
{
|
||||
if (method_exists($this, '_from_'.$from_type))
|
||||
{
|
||||
$data = call_user_func([$this, '_from_'.$from_type], $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('Format class does not support conversion from "'.$from_type.'".');
|
||||
}
|
||||
}
|
||||
|
||||
// Set the member variable to the data passed
|
||||
$this->_data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the format class
|
||||
* e.g: echo $this->format->factory(['foo' => 'bar'])->to_csv();
|
||||
*
|
||||
* @param mixed $data Data to convert/parse
|
||||
* @param string $from_type Type to convert from e.g. json, csv, html
|
||||
*
|
||||
* @return object Instance of the format class
|
||||
*/
|
||||
public function factory($data, $from_type = NULL)
|
||||
{
|
||||
// $class = __CLASS__;
|
||||
// return new $class();
|
||||
|
||||
return new static($data, $from_type);
|
||||
}
|
||||
|
||||
// FORMATTING OUTPUT ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Format data as an array
|
||||
*
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @return array Data parsed as an array; otherwise, an empty array
|
||||
*/
|
||||
public function to_array($data = NULL)
|
||||
{
|
||||
// If no data is passed as a parameter, then use the data passed
|
||||
// via the constructor
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
// Cast as an array if not already
|
||||
if (is_array($data) === FALSE)
|
||||
{
|
||||
$data = (array) $data;
|
||||
}
|
||||
|
||||
$array = [];
|
||||
foreach ((array) $data as $key => $value)
|
||||
{
|
||||
if (is_object($value) === TRUE || is_array($value) === TRUE)
|
||||
{
|
||||
$array[$key] = $this->to_array($value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$array[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format data as XML
|
||||
*
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @param NULL $structure
|
||||
* @param string $basenode
|
||||
* @return mixed
|
||||
*/
|
||||
public function to_xml($data = NULL, $structure = NULL, $basenode = 'xml')
|
||||
{
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
if ($structure === NULL)
|
||||
{
|
||||
$structure = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$basenode />");
|
||||
}
|
||||
|
||||
// Force it to be something useful
|
||||
if (is_array($data) === FALSE && is_object($data) === FALSE)
|
||||
{
|
||||
$data = (array) $data;
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value)
|
||||
{
|
||||
|
||||
//change false/true to 0/1
|
||||
if (is_bool($value))
|
||||
{
|
||||
$value = (int) $value;
|
||||
}
|
||||
|
||||
// no numeric keys in our xml please!
|
||||
if (is_numeric($key))
|
||||
{
|
||||
// make string key...
|
||||
$key = (singular($basenode) != $basenode) ? singular($basenode) : 'item';
|
||||
}
|
||||
|
||||
// replace anything not alpha numeric
|
||||
$key = preg_replace('/[^a-z_\-0-9]/i', '', $key);
|
||||
|
||||
if ($key === '_attributes' && (is_array($value) || is_object($value)))
|
||||
{
|
||||
$attributes = $value;
|
||||
if (is_object($attributes))
|
||||
{
|
||||
$attributes = get_object_vars($attributes);
|
||||
}
|
||||
|
||||
foreach ($attributes as $attribute_name => $attribute_value)
|
||||
{
|
||||
$structure->addAttribute($attribute_name, $attribute_value);
|
||||
}
|
||||
}
|
||||
// if there is another array found recursively call this function
|
||||
elseif (is_array($value) || is_object($value))
|
||||
{
|
||||
$node = $structure->addChild($key);
|
||||
|
||||
// recursive call.
|
||||
$this->to_xml($value, $node, $key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add single node.
|
||||
$value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$structure->addChild($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $structure->asXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format data as HTML
|
||||
*
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @return mixed
|
||||
*/
|
||||
public function to_html($data = NULL)
|
||||
{
|
||||
// If no data is passed as a parameter, then use the data passed
|
||||
// via the constructor
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
// Cast as an array if not already
|
||||
if (is_array($data) === FALSE)
|
||||
{
|
||||
$data = (array) $data;
|
||||
}
|
||||
|
||||
// Check if it's a multi-dimensional array
|
||||
if (isset($data[0]) && count($data) !== count($data, COUNT_RECURSIVE))
|
||||
{
|
||||
// Multi-dimensional array
|
||||
$headings = array_keys($data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Single array
|
||||
$headings = array_keys($data);
|
||||
$data = [$data];
|
||||
}
|
||||
|
||||
// Load the table library
|
||||
$this->_CI->load->library('table');
|
||||
|
||||
$this->_CI->table->set_heading($headings);
|
||||
|
||||
foreach ($data as $row)
|
||||
{
|
||||
// Suppressing the "array to string conversion" notice
|
||||
// Keep the "evil" @ here
|
||||
$row = @array_map('strval', $row);
|
||||
|
||||
$this->_CI->table->add_row($row);
|
||||
}
|
||||
|
||||
return $this->_CI->table->generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @link http://www.metashock.de/2014/02/create-csv-file-in-memory-php/
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @param string $delimiter The optional delimiter parameter sets the field
|
||||
* delimiter (one character only). NULL will use the default value (,)
|
||||
* @param string $enclosure The optional enclosure parameter sets the field
|
||||
* enclosure (one character only). NULL will use the default value (")
|
||||
* @return string A csv string
|
||||
*/
|
||||
public function to_csv($data = NULL, $delimiter = ',', $enclosure = '"')
|
||||
{
|
||||
// Use a threshold of 1 MB (1024 * 1024)
|
||||
$handle = fopen('php://temp/maxmemory:1048576', 'w');
|
||||
if ($handle === FALSE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If no data is passed as a parameter, then use the data passed
|
||||
// via the constructor
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
// If NULL, then set as the default delimiter
|
||||
if ($delimiter === NULL)
|
||||
{
|
||||
$delimiter = ',';
|
||||
}
|
||||
|
||||
// If NULL, then set as the default enclosure
|
||||
if ($enclosure === NULL)
|
||||
{
|
||||
$enclosure = '"';
|
||||
}
|
||||
|
||||
// Cast as an array if not already
|
||||
if (is_array($data) === FALSE)
|
||||
{
|
||||
$data = (array) $data;
|
||||
}
|
||||
|
||||
// Check if it's a multi-dimensional array
|
||||
if (isset($data[0]) && count($data) !== count($data, COUNT_RECURSIVE))
|
||||
{
|
||||
// Multi-dimensional array
|
||||
$headings = array_keys($data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Single array
|
||||
$headings = array_keys($data);
|
||||
$data = [$data];
|
||||
}
|
||||
|
||||
// Apply the headings
|
||||
fputcsv($handle, $headings, $delimiter, $enclosure);
|
||||
|
||||
foreach ($data as $record)
|
||||
{
|
||||
// If the record is not an array, then break. This is because the 2nd param of
|
||||
// fputcsv() should be an array
|
||||
if (is_array($record) === FALSE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Suppressing the "array to string conversion" notice.
|
||||
// Keep the "evil" @ here.
|
||||
$record = @ array_map('strval', $record);
|
||||
|
||||
// Returns the length of the string written or FALSE
|
||||
fputcsv($handle, $record, $delimiter, $enclosure);
|
||||
}
|
||||
|
||||
// Reset the file pointer
|
||||
rewind($handle);
|
||||
|
||||
// Retrieve the csv contents
|
||||
$csv = stream_get_contents($handle);
|
||||
|
||||
// Close the handle
|
||||
fclose($handle);
|
||||
|
||||
// Convert UTF-8 encoding to UTF-16LE which is supported by MS Excel
|
||||
$csv = mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
|
||||
|
||||
return $csv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode data as json
|
||||
*
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @return string Json representation of a value
|
||||
*/
|
||||
public function to_json($data = NULL)
|
||||
{
|
||||
// If no data is passed as a parameter, then use the data passed
|
||||
// via the constructor
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
// Get the callback parameter (if set)
|
||||
$callback = $this->_CI->input->get('callback');
|
||||
|
||||
if (empty($callback) === TRUE)
|
||||
{
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
// We only honour a jsonp callback which are valid javascript identifiers
|
||||
elseif (preg_match('/^[a-z_\$][a-z0-9\$_]*(\.[a-z_\$][a-z0-9\$_]*)*$/i', $callback))
|
||||
{
|
||||
// Return the data as encoded json with a callback
|
||||
return $callback.'('.json_encode($data).');';
|
||||
}
|
||||
|
||||
// An invalid jsonp callback function provided.
|
||||
// Though I don't believe this should be hardcoded here
|
||||
$data['warning'] = 'INVALID JSONP CALLBACK: '.$callback;
|
||||
|
||||
return json_encode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode data as a serialized array
|
||||
*
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @return string Serialized data
|
||||
*/
|
||||
public function to_serialized($data = NULL)
|
||||
{
|
||||
// If no data is passed as a parameter, then use the data passed
|
||||
// via the constructor
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
return serialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format data using a PHP structure
|
||||
*
|
||||
* @param mixed|NULL $data Optional data to pass, so as to override the data passed
|
||||
* to the constructor
|
||||
* @return mixed String representation of a variable
|
||||
*/
|
||||
public function to_php($data = NULL)
|
||||
{
|
||||
// If no data is passed as a parameter, then use the data passed
|
||||
// via the constructor
|
||||
if ($data === NULL && func_num_args() === 0)
|
||||
{
|
||||
$data = $this->_data;
|
||||
}
|
||||
|
||||
return var_export($data, TRUE);
|
||||
}
|
||||
|
||||
// INTERNAL FUNCTIONS
|
||||
|
||||
/**
|
||||
* @param string $data XML string
|
||||
* @return array XML element object; otherwise, empty array
|
||||
*/
|
||||
protected function _from_xml($data)
|
||||
{
|
||||
return $data ? (array) simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data CSV string
|
||||
* @param string $delimiter The optional delimiter parameter sets the field
|
||||
* delimiter (one character only). NULL will use the default value (,)
|
||||
* @param string $enclosure The optional enclosure parameter sets the field
|
||||
* enclosure (one character only). NULL will use the default value (")
|
||||
* @return array A multi-dimensional array with the outer array being the number of rows
|
||||
* and the inner arrays the individual fields
|
||||
*/
|
||||
protected function _from_csv($data, $delimiter = ',', $enclosure = '"')
|
||||
{
|
||||
// If NULL, then set as the default delimiter
|
||||
if ($delimiter === NULL)
|
||||
{
|
||||
$delimiter = ',';
|
||||
}
|
||||
|
||||
// If NULL, then set as the default enclosure
|
||||
if ($enclosure === NULL)
|
||||
{
|
||||
$enclosure = '"';
|
||||
}
|
||||
|
||||
return str_getcsv($data, $delimiter, $enclosure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data Encoded json string
|
||||
* @return mixed Decoded json string with leading and trailing whitespace removed
|
||||
*/
|
||||
protected function _from_json($data)
|
||||
{
|
||||
return json_decode(trim($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data Data to unserialize
|
||||
* @return mixed Unserialized data
|
||||
*/
|
||||
protected function _from_serialize($data)
|
||||
{
|
||||
return unserialize(trim($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data Data to trim leading and trailing whitespace
|
||||
* @return string Data with leading and trailing whitespace removed
|
||||
*/
|
||||
protected function _from_php($data)
|
||||
{
|
||||
return trim($data);
|
||||
}
|
||||
}
|
||||
427
api/libraries/Parse_Input_Stream.php
Normal file
427
api/libraries/Parse_Input_Stream.php
Normal file
@@ -0,0 +1,427 @@
|
||||
<?php
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
/**
|
||||
* stream - Handle raw input stream
|
||||
*
|
||||
* LICENSE: This source file is subject to version 3.01 of the GPL license
|
||||
* that is available through the world-wide-web at the following URI:
|
||||
* http://www.gnu.org/licenses/gpl.html. If you did not receive a copy of
|
||||
* the GPL License and are unable to obtain it through the web, please
|
||||
*
|
||||
* @author jason.gerfen@gmail.com
|
||||
* @license http://www.gnu.org/licenses/gpl.html GPL License 3
|
||||
*
|
||||
* Massive modifications by TGE (dev@mycloudfulfillment.com) to support
|
||||
* proper parameter name processing and Laravel compatible UploadedFile
|
||||
* support. Class name changed to be more descriptive and less likely to
|
||||
* collide.
|
||||
*
|
||||
* Original Gist at:
|
||||
* https://gist.github.com/jas-/5c3fdc26fedd11cb9fb5#file-class-stream-php
|
||||
*
|
||||
*/
|
||||
|
||||
class Parse_Input_Stream
|
||||
{
|
||||
/**
|
||||
* @abstract Raw input stream
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* @function parse_parameters
|
||||
*
|
||||
* @param array $data stream
|
||||
*/
|
||||
public function parse_parameters()
|
||||
{
|
||||
$this->input = file_get_contents('php://input');
|
||||
|
||||
$boundary = $this->boundary();
|
||||
|
||||
if (!strlen($boundary)) {
|
||||
$data = [
|
||||
'parameters' => $this->parse(),
|
||||
'files' => []
|
||||
];
|
||||
} else {
|
||||
$blocks = $this->split($boundary);
|
||||
|
||||
$data = $this->blocks($blocks);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function parse_files
|
||||
*
|
||||
* @param array $data stream
|
||||
*/
|
||||
public function parse_files()
|
||||
{
|
||||
$this->input = file_get_contents('php://input');
|
||||
|
||||
$boundary = $this->boundary();
|
||||
|
||||
if (!strlen($boundary)) {
|
||||
return [];
|
||||
} else {
|
||||
$blocks = $this->split($boundary);
|
||||
|
||||
$data = $this->file_blocks($blocks);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function boundary
|
||||
* @returns string
|
||||
*/
|
||||
private function boundary()
|
||||
{
|
||||
if(!isset($_SERVER['CONTENT_TYPE'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @function parse
|
||||
* @returns array
|
||||
*/
|
||||
private function parse()
|
||||
{
|
||||
parse_str(urldecode($this->input), $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function split
|
||||
* @param $boundary string
|
||||
* @returns array
|
||||
*/
|
||||
private function split($boundary)
|
||||
{
|
||||
$result = preg_split("/-+$boundary/", $this->input);
|
||||
array_pop($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function blocks
|
||||
* @param $array array
|
||||
* @returns array
|
||||
*/
|
||||
private function blocks($array)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach($array as $key => $value)
|
||||
{
|
||||
if (empty($value))
|
||||
continue;
|
||||
|
||||
$block = $this->decide($value);
|
||||
|
||||
foreach ( $block['parameters'] as $key => $val ) {
|
||||
$this->parse_parameter( $results, $key, $val );
|
||||
}
|
||||
|
||||
foreach ( $block['files'] as $key => $val ) {
|
||||
$this->parse_parameter( $results, $key, $val );
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function file_blocks
|
||||
* @param $array array
|
||||
* @returns array
|
||||
*/
|
||||
private function file_blocks($array)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach($array as $key => $value)
|
||||
{
|
||||
if (empty($value))
|
||||
continue;
|
||||
|
||||
$block = $this->decide($value);
|
||||
|
||||
if ($block['files'] && count($block['files'])) {
|
||||
$file_array_keys = array_keys($block['files']);
|
||||
foreach ($file_array_keys as $file_array_key) {
|
||||
if (isset($results[$file_array_key])) {
|
||||
$results[$file_array_key]['name'][] = $block['files'][$file_array_key]['name'];
|
||||
$results[$file_array_key]['type'][] = $block['files'][$file_array_key]['type'];
|
||||
$results[$file_array_key]['tmp_name'][] = $block['files'][$file_array_key]['tmp_name'];
|
||||
$results[$file_array_key]['error'][] = $block['files'][$file_array_key]['error'];
|
||||
$results[$file_array_key]['size'][] = $block['files'][$file_array_key]['size'];
|
||||
} else {
|
||||
$results[$file_array_key] = [
|
||||
'name' => [$block['files'][$file_array_key]['name']],
|
||||
'type' => [$block['files'][$file_array_key]['type']],
|
||||
'tmp_name' => [$block['files'][$file_array_key]['tmp_name']],
|
||||
'error' => [$block['files'][$file_array_key]['error']],
|
||||
'size' => [$block['files'][$file_array_key]['size']],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function decide
|
||||
* @param $string string
|
||||
* @returns array
|
||||
*/
|
||||
private function decide($string)
|
||||
{
|
||||
if (strpos($string, 'application/octet-stream') !== FALSE)
|
||||
{
|
||||
return [
|
||||
'parameters' => $this->file($string),
|
||||
'files' => []
|
||||
];
|
||||
}
|
||||
|
||||
if (strpos($string, 'filename') !== FALSE)
|
||||
{
|
||||
return [
|
||||
'parameters' => [],
|
||||
'files' => $this->file_stream($string)
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'parameters' => $this->parameter($string),
|
||||
'files' => []
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @function file
|
||||
*
|
||||
* @param $string
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function file($string)
|
||||
{
|
||||
preg_match('/name=\"([^\"]*)\".*stream[\n|\r]+([^\n\r].*)?$/s', $string, $match);
|
||||
return [
|
||||
$match[1] => ($match[2] !== NULL ? $match[2] : '')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @function file_stream
|
||||
*
|
||||
* @param $string
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function file_stream($data)
|
||||
{
|
||||
$result = [];
|
||||
$data = ltrim($data);
|
||||
|
||||
$idx = strpos( $data, "\r\n\r\n" );
|
||||
if ( $idx === FALSE ) {
|
||||
Log::warning( "ParseInputStream.file_stream(): Could not locate header separator in data:" );
|
||||
Log::warning( $data );
|
||||
} else {
|
||||
$headers = substr( $data, 0, $idx );
|
||||
$content = substr( $data, $idx + 4, -2 ); // Skip the leading \r\n and strip the final \r\n
|
||||
|
||||
$name = '-unknown-';
|
||||
$filename = '-unknown-';
|
||||
$filetype = 'application/octet-stream';
|
||||
|
||||
$header = strtok( $headers, "\r\n" );
|
||||
while ( $header !== FALSE ) {
|
||||
if ( substr($header, 0, strlen("Content-Disposition: ")) == "Content-Disposition: " ) {
|
||||
// Content-Disposition: form-data; name="attach_file[TESTING]"; filename="label2.jpg"
|
||||
if ( preg_match('/name=\"([^\"]*)\"/', $header, $nmatch ) ) {
|
||||
$name = $nmatch[1];
|
||||
}
|
||||
if ( preg_match('/filename=\"([^\"]*)\"/', $header, $nmatch ) ) {
|
||||
$filename = $nmatch[1];
|
||||
}
|
||||
} elseif ( substr($header, 0, strlen("Content-Type: ")) == "Content-Type: " ) {
|
||||
// Content-Type: image/jpg
|
||||
$filetype = trim( substr($header, strlen("Content-Type: ")) );
|
||||
} else {
|
||||
Log::debug( "PARSEINPUTSTREAM: Skipping Header: " . $header );
|
||||
}
|
||||
|
||||
$header = strtok("\r\n");
|
||||
}
|
||||
|
||||
$name = preg_replace('/\[\]$/', '', $name);
|
||||
|
||||
if ( substr($data, -2) === "\r\n" ) {
|
||||
$data = substr($data, 0, -2);
|
||||
}
|
||||
|
||||
$path = (ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'php' . substr( sha1(rand()), 0, 6 ) . '.tmp';
|
||||
|
||||
$bytes = file_put_contents( $path, $content );
|
||||
|
||||
if ( $bytes !== FALSE ) {
|
||||
// $file = new UploadedFile( $path, $filename, $filetype, $bytes, UPLOAD_ERR_OK );
|
||||
$result = array( $name => [
|
||||
'name' => $filename,
|
||||
'type' => $filetype,
|
||||
'tmp_name' => $path,
|
||||
'error' => UPLOAD_ERR_OK,
|
||||
'size' => $bytes
|
||||
] );
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function parameter
|
||||
*
|
||||
* @param $string
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parameter($string)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if ( preg_match('/name=\"([^\"]*)\"[\n|\r]+([^\n\r].*)?\r$/s', $string, $match) ) {
|
||||
if (preg_match('/^(.*)\[\]$/i', $match[1], $tmp)) {
|
||||
$data[$tmp[1]][] = (isset($match[2]) && $match[2] !== NULL ? $match[2] : '');
|
||||
} else {
|
||||
$data[$match[1]] = (isset($match[2]) && $match[2] !== NULL ? $match[2] : '');
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @function merge
|
||||
* @param $array array
|
||||
*
|
||||
* Ugly ugly ugly
|
||||
*
|
||||
* @returns array
|
||||
*/
|
||||
private function merge($array)
|
||||
{
|
||||
$results = [
|
||||
'parameters' => [],
|
||||
'files' => []
|
||||
];
|
||||
|
||||
if (count($array['parameters']) > 0) {
|
||||
foreach($array['parameters'] as $key => $value) {
|
||||
foreach($value as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
foreach($v as $kk => $vv) {
|
||||
$results['parameters'][$k][] = $vv;
|
||||
}
|
||||
} else {
|
||||
$results['parameters'][$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($array['files']) > 0) {
|
||||
foreach($array['files'] as $key => $value) {
|
||||
foreach($value as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
foreach($v as $kk => $vv) {
|
||||
if(is_array($vv) && (count($vv) === 1)) {
|
||||
$results['files'][$k][$kk] = $vv[0];
|
||||
} else {
|
||||
$results['files'][$k][$kk][] = $vv[0];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$results['files'][$k][$key] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
function parse_parameter( &$params, $parameter, $value ) {
|
||||
if ( strpos($parameter, '[') !== FALSE ) {
|
||||
$matches = array();
|
||||
if ( preg_match( '/^([^[]*)\[([^]]*)\](.*)$/', $parameter, $match ) ) {
|
||||
$name = $match[1];
|
||||
$key = $match[2];
|
||||
$rem = $match[3];
|
||||
|
||||
if ( $name !== '' && $name !== NULL ) {
|
||||
if ( ! isset($params[$name]) || ! is_array($params[$name]) ) {
|
||||
$params[$name] = array();
|
||||
} else {
|
||||
}
|
||||
if ( strlen($rem) > 0 ) {
|
||||
if ( $key === '' || $key === NULL ) {
|
||||
$arr = array();
|
||||
$this->parse_parameter( $arr, $rem, $value );
|
||||
$params[$name][] = $arr;
|
||||
} else {
|
||||
if ( !isset($params[$name][$key]) || !is_array($params[$name][$key]) ) {
|
||||
$params[$name][$key] = array();
|
||||
}
|
||||
$this->parse_parameter( $params[$name][$key], $rem, $value );
|
||||
}
|
||||
} else {
|
||||
if ( $key === '' || $key === NULL ) {
|
||||
$params[$name][] = $value;
|
||||
} else {
|
||||
$params[$name][$key] = $value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( strlen($rem) > 0 ) {
|
||||
if ( $key === '' || $key === NULL ) {
|
||||
// REVIEW Is this logic correct?!
|
||||
$this->parse_parameter( $params, $rem, $value );
|
||||
} else {
|
||||
if ( ! isset($params[$key]) || ! is_array($params[$key]) ) {
|
||||
$params[$key] = array();
|
||||
}
|
||||
$this->parse_parameter( $params[$key], $rem, $value );
|
||||
}
|
||||
} else {
|
||||
if ( $key === '' || $key === NULL ) {
|
||||
$params[] = $value;
|
||||
} else {
|
||||
$params[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log::warning( "ParseInputStream.parse_parameter() Parameter name regex failed: '" . $parameter . "'" );
|
||||
}
|
||||
} else {
|
||||
$params[$parameter] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user