TimeTrex Community Edition v16.2.0
This commit is contained in:
438
classes/misc/MimeMailParser.class.php
Normal file
438
classes/misc/MimeMailParser.class.php
Normal file
@@ -0,0 +1,438 @@
|
||||
<?php
|
||||
|
||||
require_once('attachment.class.php');
|
||||
|
||||
/**
|
||||
* Fast Mime Mail parser Class using PHP's MailParse Extension
|
||||
* @author gabe@fijiwebdesign.com
|
||||
* @url http://www.fijiwebdesign.com/
|
||||
* @license http://creativecommons.org/licenses/by-sa/3.0/us/
|
||||
* @version $Id$
|
||||
*/
|
||||
class MimeMailParser {
|
||||
|
||||
/**
|
||||
* PHP MimeParser Resource ID
|
||||
*/
|
||||
public $resource;
|
||||
|
||||
/**
|
||||
* A file pointer to email
|
||||
*/
|
||||
public $stream;
|
||||
|
||||
/**
|
||||
* A text of an email
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* Stream Resources for Attachments
|
||||
*/
|
||||
public $attachment_streams;
|
||||
|
||||
/**
|
||||
* Inialize some stuff
|
||||
* @return
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->attachment_streams = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the held resouces
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct() {
|
||||
// clear the email file resource
|
||||
if (is_resource($this->stream)) {
|
||||
fclose($this->stream);
|
||||
}
|
||||
// clear the MailParse resource
|
||||
if (is_resource($this->resource)) {
|
||||
mailparse_msg_free($this->resource);
|
||||
}
|
||||
// remove attachment resources
|
||||
foreach($this->attachment_streams as $stream) {
|
||||
fclose($stream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file path we use to get the email text
|
||||
* @return Object MimeMailParser Instance
|
||||
* @param $mail_path Object
|
||||
*/
|
||||
public function setPath($path) {
|
||||
// should parse message incrementally from file
|
||||
$this->resource = mailparse_msg_parse_file($path);
|
||||
$this->stream = fopen($path, 'r');
|
||||
$this->parse();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Stream resource we use to get the email text
|
||||
* @return Object MimeMailParser Instance
|
||||
* @param $stream Resource
|
||||
*/
|
||||
public function setStream($stream) {
|
||||
|
||||
// streams have to be cached to file first
|
||||
if (get_resource_type($stream) == 'stream') {
|
||||
$tmp_fp = tmpfile();
|
||||
if ($tmp_fp) {
|
||||
while(!feof($stream)) {
|
||||
fwrite($tmp_fp, fread($stream, 2028));
|
||||
}
|
||||
fseek($tmp_fp, 0);
|
||||
$this->stream =& $tmp_fp;
|
||||
} else {
|
||||
throw new Exception('Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.');
|
||||
return false;
|
||||
}
|
||||
fclose($stream);
|
||||
} else {
|
||||
$this->stream = $stream;
|
||||
}
|
||||
|
||||
$this->resource = mailparse_msg_create();
|
||||
// parses the message incrementally low memory usage but slower
|
||||
while(!feof($this->stream)) {
|
||||
mailparse_msg_parse($this->resource, fread($this->stream, 2082));
|
||||
}
|
||||
$this->parse();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the email text
|
||||
* @return Object MimeMailParser Instance
|
||||
* @param $data String
|
||||
*/
|
||||
public function setText($data) {
|
||||
$this->resource = mailparse_msg_create();
|
||||
// does not parse incrementally, fast memory hog might explode
|
||||
mailparse_msg_parse($this->resource, $data);
|
||||
$this->data = $data;
|
||||
$this->parse();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Message into parts
|
||||
* @return void
|
||||
* @private
|
||||
*/
|
||||
private function parse() {
|
||||
$structure = mailparse_msg_get_structure($this->resource);
|
||||
$this->parts = array();
|
||||
foreach($structure as $part_id) {
|
||||
$part = mailparse_msg_get_part($this->resource, $part_id);
|
||||
$this->parts[$part_id] = mailparse_msg_get_part_data($part);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Email Headers
|
||||
* @return Array
|
||||
*/
|
||||
public function getHeaders() {
|
||||
if (isset($this->parts[1])) {
|
||||
return $this->getPartHeaders($this->parts[1]);
|
||||
} else {
|
||||
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email headers.');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Retrieve the raw Email Headers
|
||||
* @return string
|
||||
*/
|
||||
public function getHeadersRaw() {
|
||||
if (isset($this->parts[1])) {
|
||||
return $this->getPartHeaderRaw($this->parts[1]);
|
||||
} else {
|
||||
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email headers.');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific Email Header
|
||||
* @return String
|
||||
* @param $name String Header name
|
||||
*/
|
||||
public function getHeader($name) {
|
||||
if (isset($this->parts[1])) {
|
||||
$headers = $this->getPartHeaders($this->parts[1]);
|
||||
if (isset($headers[$name])) {
|
||||
return $headers[$name];
|
||||
}
|
||||
} else {
|
||||
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email headers.');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the email message body in the specified format
|
||||
* @return Mixed String Body or False if not found
|
||||
* @param $type Object[optional]
|
||||
*/
|
||||
public function getMessageBody($type = 'text') {
|
||||
$body = false;
|
||||
$mime_types = array(
|
||||
'text'=> 'text/plain',
|
||||
'html'=> 'text/html'
|
||||
);
|
||||
if (in_array($type, array_keys($mime_types))) {
|
||||
foreach($this->parts as $part) {
|
||||
if ($this->getPartContentType($part) == $mime_types[$type]) {
|
||||
$headers = $this->getPartHeaders($part);
|
||||
$body = $this->decode($this->getPartBody($part), array_key_exists('content-transfer-encoding', $headers) ? $headers['content-transfer-encoding'] : '');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Exception('Invalid type specified for MimeMailParser::getMessageBody. "type" can either be text or html.');
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the headers for the message body part.
|
||||
* @return Array
|
||||
* @param $type Object[optional]
|
||||
*/
|
||||
public function getMessageBodyHeaders($type = 'text') {
|
||||
$headers = false;
|
||||
$mime_types = array(
|
||||
'text'=> 'text/plain',
|
||||
'html'=> 'text/html'
|
||||
);
|
||||
if (in_array($type, array_keys($mime_types))) {
|
||||
foreach($this->parts as $part) {
|
||||
if ($this->getPartContentType($part) == $mime_types[$type]) {
|
||||
$headers = $this->getPartHeaders($part);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Exception('Invalid type specified for MimeMailParser::getMessageBody. "type" can either be text or html.');
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the attachments contents in order of appearance
|
||||
* @return Array
|
||||
* @param $type Object[optional]
|
||||
*/
|
||||
public function getAttachments() {
|
||||
$attachments = array();
|
||||
$dispositions = array("attachment","inline");
|
||||
foreach($this->parts as $part) {
|
||||
$disposition = $this->getPartContentDisposition($part);
|
||||
if (in_array($disposition, $dispositions)) {
|
||||
$attachments[] = new MimeMailParser_attachment(
|
||||
$part['disposition-filename'],
|
||||
$this->getPartContentType($part),
|
||||
$this->getAttachmentStream($part),
|
||||
$disposition,
|
||||
$this->getPartHeaders($part)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Headers for a MIME part
|
||||
* @return Array
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartHeaders($part) {
|
||||
if (isset($part['headers'])) {
|
||||
return $part['headers'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Specific Header for a MIME part
|
||||
* @return Array
|
||||
* @param $part Array
|
||||
* @param $header String Header Name
|
||||
*/
|
||||
private function getPartHeader($part, $header) {
|
||||
if (isset($part['headers'][$header])) {
|
||||
return $part['headers'][$header];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ContentType of the MIME part
|
||||
* @return String
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartContentType($part) {
|
||||
if (isset($part['content-type'])) {
|
||||
return $part['content-type'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Content Disposition
|
||||
* @return String
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartContentDisposition($part) {
|
||||
if (isset($part['content-disposition'])) {
|
||||
return $part['content-disposition'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the raw Header of a MIME part
|
||||
* @return String
|
||||
* @param $part Object
|
||||
*/
|
||||
private function getPartHeaderRaw(&$part) {
|
||||
$header = '';
|
||||
if ($this->stream) {
|
||||
$header = $this->getPartHeaderFromFile($part);
|
||||
} else if ($this->data) {
|
||||
$header = $this->getPartHeaderFromText($part);
|
||||
} else {
|
||||
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email parts.');
|
||||
}
|
||||
return $header;
|
||||
}
|
||||
/**
|
||||
* Retrieve the Body of a MIME part
|
||||
* @return String
|
||||
* @param $part Object
|
||||
*/
|
||||
private function getPartBody(&$part) {
|
||||
$body = '';
|
||||
if ($this->stream) {
|
||||
$body = $this->getPartBodyFromFile($part);
|
||||
} else if ($this->data) {
|
||||
$body = $this->getPartBodyFromText($part);
|
||||
} else {
|
||||
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email parts.');
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Header from a MIME part from file
|
||||
* @return String Mime Header Part
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartHeaderFromFile(&$part) {
|
||||
$start = $part['starting-pos'];
|
||||
$end = $part['starting-pos-body'];
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$header = @fread($this->stream, $end-$start);
|
||||
return $header;
|
||||
}
|
||||
/**
|
||||
* Retrieve the Body from a MIME part from file
|
||||
* @return String Mime Body Part
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartBodyFromFile(&$part) {
|
||||
$start = $part['starting-pos-body'];
|
||||
$end = $part['ending-pos-body'];
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$body = @fread($this->stream, $end-$start);
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Header from a MIME part from text
|
||||
* @return String Mime Header Part
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartHeaderFromText(&$part) {
|
||||
$start = $part['starting-pos'];
|
||||
$end = $part['starting-pos-body'];
|
||||
$header = substr($this->data, $start, $end-$start);
|
||||
return $header;
|
||||
}
|
||||
/**
|
||||
* Retrieve the Body from a MIME part from text
|
||||
* @return String Mime Body Part
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getPartBodyFromText(&$part) {
|
||||
$start = $part['starting-pos-body'];
|
||||
$end = $part['ending-pos-body'];
|
||||
$body = substr($this->data, $start, $end-$start);
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the attachment Body and save temporary file resource
|
||||
* @return String Mime Body Part
|
||||
* @param $part Array
|
||||
*/
|
||||
private function getAttachmentStream(&$part) {
|
||||
$temp_fp = tmpfile();
|
||||
|
||||
array_key_exists('content-transfer-encoding', $part['headers']) ? $encoding = $part['headers']['content-transfer-encoding'] : $encoding = '';
|
||||
|
||||
if ($temp_fp) {
|
||||
if ($this->stream) {
|
||||
$start = $part['starting-pos-body'];
|
||||
$end = $part['ending-pos-body'];
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$len = $end-$start;
|
||||
$written = 0;
|
||||
$write = 2028;
|
||||
$body = '';
|
||||
while($written < $len) {
|
||||
if (($written+$write < $len )) {
|
||||
$write = $len - $written;
|
||||
}
|
||||
$part = fread($this->stream, $write);
|
||||
fwrite($temp_fp, $this->decode($part, $encoding));
|
||||
$written += $write;
|
||||
}
|
||||
} else if ($this->data) {
|
||||
$attachment = $this->decode($this->getPartBodyFromText($part), $encoding);
|
||||
fwrite($temp_fp, $attachment, strlen($attachment));
|
||||
}
|
||||
fseek($temp_fp, 0, SEEK_SET);
|
||||
} else {
|
||||
throw new Exception('Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.');
|
||||
return false;
|
||||
}
|
||||
return $temp_fp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode the string depending on encoding type.
|
||||
* @return String the decoded string.
|
||||
* @param $encodedString The string in its original encoded state.
|
||||
* @param $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
|
||||
*/
|
||||
private function decode($encodedString, $encodingType) {
|
||||
if (strtolower($encodingType) == 'base64') {
|
||||
return base64_decode($encodedString);
|
||||
} else if (strtolower($encodingType) == 'quoted-printable') {
|
||||
return quoted_printable_decode($encodedString);
|
||||
} else {
|
||||
return $encodedString;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
302
classes/misc/MultiCurl.class.php
Normal file
302
classes/misc/MultiCurl.class.php
Normal file
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
/**
|
||||
* MultiCurl class provides a convenient way to execute parallel HTTP(S)
|
||||
* requests via PHP MULTI CURL extension with additional restrictions.
|
||||
* For example: start 100 downloads with 2 parallel sessions, and get only
|
||||
* first 100 Kb per session.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* @author Vadym Timofeyev <tvad@mail333.com> http://weblancer.net/users/tvv/
|
||||
* @copyright 2007-2010 Vadym Timofeyev
|
||||
* @license http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
* @version 1.07
|
||||
* @since PHP 5.0
|
||||
* @example examples/example.php How to use MultiCurl class library.
|
||||
*/
|
||||
abstract class MultiCurl {
|
||||
/**
|
||||
* Maximal number of CURL multi sessions. Default: 10 sessions.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $maxSessions = 10;
|
||||
|
||||
/**
|
||||
* Maximal size of downloaded content. Default: 10 Mb (10 * 1024 * 1024).
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $maxSize = 10485760;
|
||||
|
||||
/**
|
||||
* Common CURL options (used for all requests).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $curlOptions;
|
||||
|
||||
/**
|
||||
* Current CURL multi sessions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $sessions = array();
|
||||
|
||||
/**
|
||||
* Class constructor. Setup primary parameters.
|
||||
*
|
||||
* @param array $curlOptions Common CURL options.
|
||||
*/
|
||||
public function __construct($curlOptions = array()) {
|
||||
if(empty($curlOptions))
|
||||
{
|
||||
$header[] = "Accept: */*";
|
||||
$header[] = "Cache-Control: max-age=0";
|
||||
$header[] = "Accept-Charset: utf-8;q=0.7,*;q=0.7";
|
||||
$header[] = "Accept-Language: en-us,en;q=0.5";
|
||||
$header[] = "Pragma: ";
|
||||
|
||||
$curlOptions=array(
|
||||
CURLOPT_HEADER => true,
|
||||
CURLOPT_HTTPHEADER => $header,
|
||||
CURLOPT_USERAGENT => 'Googlebot/2.1 (+http://www.google.com/bot.html)',
|
||||
CURLOPT_CONNECTTIMEOUT => 20,
|
||||
CURLOPT_TIMEOUT => 10
|
||||
);
|
||||
}
|
||||
$this->setCurlOptions($curlOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class destructor. Close opened sessions.
|
||||
*/
|
||||
public function __destruct() {
|
||||
foreach ($this->sessions as $i => $sess) {
|
||||
$this->destroySession($i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new URL to query.
|
||||
*
|
||||
* @param mixed $url URL for downloading.
|
||||
* @param array $curlOptions CURL options for current request.
|
||||
*/
|
||||
public function addUrl($url, $extra_data = NULL, $curlOptions = array()) {
|
||||
// Check URL
|
||||
if (!$url) {
|
||||
throw new Exception('URL is empty!');
|
||||
}
|
||||
|
||||
// Check array of URLs
|
||||
if (is_array($url)) {
|
||||
foreach ($url as $s) {
|
||||
$this->addUrl($s, $curlOptions);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check query
|
||||
while (count($this->sessions) == $this->maxSessions) {
|
||||
$this->checkSessions();
|
||||
}
|
||||
|
||||
// Init new CURL session
|
||||
$ch = curl_init($url);
|
||||
foreach ($this->curlOptions as $option => $value) {
|
||||
curl_setopt($ch, $option, $value);
|
||||
}
|
||||
foreach ($curlOptions as $option => $value) {
|
||||
curl_setopt($ch, $option, $value);
|
||||
}
|
||||
|
||||
// Init new CURL multi session
|
||||
$mh = curl_multi_init();
|
||||
curl_multi_add_handle($mh, $ch);
|
||||
$this->sessions[] = array($mh, $ch, $url, $extra_data);
|
||||
$sessions_key = array_keys($this->sessions);
|
||||
$this->execSession(array_pop($sessions_key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits CURL milti sessions.
|
||||
*/
|
||||
public function wait() {
|
||||
while (count($this->sessions)) {
|
||||
$this->checkSessions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all active CURL multi sessions.
|
||||
*/
|
||||
protected function checkSessions() {
|
||||
foreach ($this->sessions as $i => $sess) {
|
||||
if ($this->multiSelect($sess[0]) != -1) {
|
||||
$this->execSession($i);
|
||||
}
|
||||
else {
|
||||
throw new Exception('Multicurl loop detected!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes CURL multi session, check session status and downloaded size.
|
||||
*
|
||||
* @param integer $i A session id.
|
||||
*/
|
||||
protected function execSession($i) {
|
||||
list($mh, $ch) = $this->sessions[$i];
|
||||
if ($mh) {
|
||||
do {
|
||||
$mrc = curl_multi_exec($mh, $act);
|
||||
} while ($act > 0);
|
||||
if (!$act || $mrc !== CURLM_OK || curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD) >= $this->maxSize) {
|
||||
$this->closeSession($i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace curl_multi_select.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.curl-multi-select.php#110869
|
||||
* @param resource $mh A cURL multi handle returned by curl_multi_init().
|
||||
* @param float $timeout Time, in seconds, to wait for a response.
|
||||
*/
|
||||
protected function multiSelect($mh, $timeout = 1.0) {
|
||||
$ts = microtime(true);
|
||||
|
||||
do {
|
||||
$mrc = curl_multi_exec($mh, $act);
|
||||
$ct = microtime(true);
|
||||
$t = $ct - $ts;
|
||||
if ($t >= $timeout) {
|
||||
return CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes session.
|
||||
*
|
||||
* @param integer $i A session id.
|
||||
*/
|
||||
protected function closeSession($i) {
|
||||
list(, $ch, $url, $extra_data) = $this->sessions[$i];
|
||||
|
||||
$content = !curl_error($ch) ? curl_multi_getcontent($ch) : null;
|
||||
$info = curl_getinfo($ch);
|
||||
$this->destroySession($i);
|
||||
$this->onLoad($url, $content, $info, $extra_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys session.
|
||||
*
|
||||
* @param integer $i A session id.
|
||||
*/
|
||||
protected function destroySession($i) {
|
||||
list($mh, $ch,) = $this->sessions[$i];
|
||||
|
||||
curl_multi_remove_handle($mh, $ch);
|
||||
curl_close($ch);
|
||||
curl_multi_close($mh);
|
||||
|
||||
unset($this->sessions[$i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets maximal number of CURL multi sessions.
|
||||
*
|
||||
* @return integer Maximal number of CURL multi sessions.
|
||||
*/
|
||||
public function getMaxSessions() {
|
||||
return $this->maxSessions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximal number of CURL multi sessions.
|
||||
*
|
||||
* @param integer $maxSessions Maximal number of CURL multi sessions.
|
||||
*/
|
||||
public function setMaxSessions($maxSessions) {
|
||||
if ((int)$maxSessions <= 0) {
|
||||
throw new Exception('Max sessions number must be bigger then zero!');
|
||||
}
|
||||
|
||||
$this->maxSessions = (int)$maxSessions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets maximal size limit for downloaded content.
|
||||
*
|
||||
* @return integer Maximal size limit for downloaded content.
|
||||
*/
|
||||
public function getMaxSize() {
|
||||
return $this->maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximal size limit for downloaded content.
|
||||
*
|
||||
* @param integer $maxSize Maximal size limit for downloaded content.
|
||||
*/
|
||||
public function setMaxSize($maxSize) {
|
||||
if ((int)$maxSize <= 0) {
|
||||
throw new Exception('Max size limit must be bigger then zero!');
|
||||
}
|
||||
|
||||
$this->maxSize = (int)$maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets CURL options for all requests.
|
||||
*
|
||||
* @return array CURL options.
|
||||
*/
|
||||
public function getCurlOptions() {
|
||||
return $this->curlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets CURL options for all requests.
|
||||
*
|
||||
* @param array $curlOptions CURL options.
|
||||
*/
|
||||
public function setCurlOptions($curlOptions) {
|
||||
if (!array_key_exists(CURLOPT_FOLLOWLOCATION, $curlOptions)) {
|
||||
$curlOptions[CURLOPT_FOLLOWLOCATION] = 1;
|
||||
}
|
||||
$curlOptions[CURLOPT_RETURNTRANSFER] = 1;
|
||||
$this->curlOptions = $curlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* OnLoad callback event.
|
||||
*
|
||||
* @param string $url URL for downloading.
|
||||
* @param string $content Downloaded content.
|
||||
* @param array $info CURL session information.
|
||||
*/
|
||||
protected abstract function onLoad($url, $content, $info, $extra_data);
|
||||
|
||||
/**
|
||||
* Checks CURL extension, etc.
|
||||
*/
|
||||
public static function checkEnvironment() {
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new Exception('CURL extension not loaded');
|
||||
}
|
||||
}
|
||||
}
|
120
classes/misc/UUID.class.php
Normal file
120
classes/misc/UUID.class.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
class UUID {
|
||||
public static function v3($namespace, $name) {
|
||||
if(!self::is_valid($namespace)) return false;
|
||||
|
||||
// Get hexadecimal components of namespace
|
||||
$nhex = str_replace(array('-','{','}'), '', $namespace);
|
||||
|
||||
// Binary Value
|
||||
$nstr = '';
|
||||
|
||||
// Convert Namespace UUID to bits
|
||||
for($i = 0; $i < strlen($nhex); $i+=2) {
|
||||
$nstr .= chr(hexdec($nhex[$i].$nhex[$i+1]));
|
||||
}
|
||||
|
||||
// Calculate hash value
|
||||
$hash = md5($nstr . $name);
|
||||
|
||||
return sprintf('%08s-%04s-%04x-%04x-%12s',
|
||||
|
||||
// 32 bits for "time_low"
|
||||
substr($hash, 0, 8),
|
||||
|
||||
// 16 bits for "time_mid"
|
||||
substr($hash, 8, 4),
|
||||
|
||||
// 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 3
|
||||
(hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x3000,
|
||||
|
||||
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
(hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
|
||||
|
||||
// 48 bits for "node"
|
||||
substr($hash, 20, 12)
|
||||
);
|
||||
}
|
||||
|
||||
public static function v4() {
|
||||
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
|
||||
// 32 bits for "time_low"
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||
|
||||
// 16 bits for "time_mid"
|
||||
mt_rand(0, 0xffff),
|
||||
|
||||
// 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 4
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
|
||||
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
mt_rand(0, 0x3fff) | 0x8000,
|
||||
|
||||
// 48 bits for "node"
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||
);
|
||||
}
|
||||
|
||||
public static function v5($namespace, $name) {
|
||||
if(!self::is_valid($namespace)) return false;
|
||||
|
||||
// Get hexadecimal components of namespace
|
||||
$nhex = str_replace(array('-','{','}'), '', $namespace);
|
||||
|
||||
// Binary Value
|
||||
$nstr = '';
|
||||
|
||||
// Convert Namespace UUID to bits
|
||||
for($i = 0; $i < strlen($nhex); $i+=2) {
|
||||
$nstr .= chr(hexdec($nhex[$i].$nhex[$i+1]));
|
||||
}
|
||||
|
||||
// Calculate hash value
|
||||
$hash = sha1($nstr . $name);
|
||||
|
||||
return sprintf('%08s-%04s-%04x-%04x-%12s',
|
||||
|
||||
// 32 bits for "time_low"
|
||||
substr($hash, 0, 8),
|
||||
|
||||
// 16 bits for "time_mid"
|
||||
substr($hash, 8, 4),
|
||||
|
||||
// 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 5
|
||||
(hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x5000,
|
||||
|
||||
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
(hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
|
||||
|
||||
// 48 bits for "node"
|
||||
substr($hash, 20, 12)
|
||||
);
|
||||
}
|
||||
|
||||
public static function is_valid($uuid) {
|
||||
return preg_match('/^\{?[0-9a-f]{8}\-?[0-9a-f]{4}\-?[0-9a-f]{4}\-?'.
|
||||
'[0-9a-f]{4}\-?[0-9a-f]{12}\}?$/i', $uuid) === 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Usage
|
||||
// Named-based UUID.
|
||||
|
||||
$v3uuid = UUID::v3('1546058f-5a25-4334-85ae-e68f2a44bbaf', 'SomeRandomString');
|
||||
$v5uuid = UUID::v5('1546058f-5a25-4334-85ae-e68f2a44bbaf', 'SomeRandomString');
|
||||
|
||||
// Pseudo-random UUID
|
||||
|
||||
$v4uuid = UUID::v4();
|
||||
*/
|
||||
?>
|
152
classes/misc/arr_multisort.class.php
Normal file
152
classes/misc/arr_multisort.class.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/*
|
||||
arr_multisort 1.1
|
||||
Copyright: Left
|
||||
---------------------------------------------------------------------------------
|
||||
Version: 1.1
|
||||
Date: 11 January 2005
|
||||
---------------------------------------------------------------------------------
|
||||
Author: Alexander Minkovsky (a_minkovsky@hotmail.com)
|
||||
---------------------------------------------------------------------------------
|
||||
License: Choose the more appropriated for You - I don't care.
|
||||
---------------------------------------------------------------------------------
|
||||
Description:
|
||||
Class makes multicolumn sorting of associative arrays in format provided for example by mysql_fetch_assoc.
|
||||
Column names to be used when sorting can be specified as well the sorting direction for each column.
|
||||
Optional external to the class compare functions can be specified for each column.
|
||||
Look below for requirements concerning external compare functions.
|
||||
If external compare functions are not supplied, the internal _compare method is used.
|
||||
Dates are sorted correctly using the internal compare if they comply with GNU date syntax
|
||||
(http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html)
|
||||
---------------------------------------------------------------------------------
|
||||
Example usage: see example.php
|
||||
---------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
define("SRT_ASC",1);
|
||||
define("SRT_DESC",-1);
|
||||
|
||||
Class arr_multisort{
|
||||
|
||||
//The array to be sorted
|
||||
var $arr = NULL;
|
||||
|
||||
/*
|
||||
Sorting definition
|
||||
Format: array (
|
||||
array(
|
||||
"colName" => "some column name",
|
||||
"colDir" => SRT_ASC,
|
||||
"compareFunc" => "myCompareFunction"
|
||||
),
|
||||
..........................
|
||||
)
|
||||
"compareFunc" element is optional - NULL by default and by default the class internal compare is used.
|
||||
If External compare function is supplied it must conform to the following requirements:
|
||||
~ Accept two T_STRING parameters and return:
|
||||
0 - if parameters are equal
|
||||
1 - if first parameter is greater than second
|
||||
-1 - if second parameter is greater than first
|
||||
*/
|
||||
var $sortDef = NULL;
|
||||
|
||||
//Constructor
|
||||
function arr_multisort(){
|
||||
$this->arr = array();
|
||||
$this->sortDef = array();
|
||||
}
|
||||
|
||||
//setArray method - sets the array to be sorted
|
||||
function setArray(&$arr){
|
||||
$this->arr = $arr;
|
||||
}
|
||||
|
||||
/*
|
||||
addColumn method - ads entry to sorting definition
|
||||
If column exists, values are overwriten.
|
||||
*/
|
||||
function addColumn($colName="",$colDir=SRT_ASC,$compareFunc=NULL){
|
||||
$idx = $this->_getColIdx($colName);
|
||||
if($idx < 0){
|
||||
$this->sortDef[] = array();
|
||||
$idx = count($this->sortDef)-1;
|
||||
}
|
||||
$this->sortDef[$idx]["colName"] = $colName;
|
||||
$this->sortDef[$idx]["colDir"] = $colDir;
|
||||
$this->sortDef[$idx]["compareFunc"] = $compareFunc;
|
||||
}
|
||||
|
||||
//removeColumn method - removes entry from sorting definition
|
||||
function removeColumn($colName=""){
|
||||
$idx = $this->_getColIdx($colName);
|
||||
if($idx >= 0) array_splice($this->sortDef,$idx,1);
|
||||
}
|
||||
|
||||
//resetColumns - removes any columns from sorting definition. Array to sort is not affected.
|
||||
function resetColumns(){
|
||||
$this->sortDef = array();
|
||||
}
|
||||
|
||||
//sort() method
|
||||
function &sort(){
|
||||
if ( is_array($this->arr) ) {
|
||||
usort($this->arr,array($this,"_compare"));
|
||||
return $this->arr;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//_getColIdx method [PRIVATE]
|
||||
function _getColIdx($colName){
|
||||
$idx = -1;
|
||||
for($i=0;$i<count($this->sortDef);$i++){
|
||||
$colDef = $this->sortDef[$i];
|
||||
if($colDef["colName"] == $colName) $idx = $i;
|
||||
}
|
||||
return $idx;
|
||||
}
|
||||
|
||||
//Comparison function [PRIVATE]
|
||||
function _compare($a,$b,$idx = 0){
|
||||
if(count($this->sortDef) == 0) return 0;
|
||||
$colDef = $this->sortDef[$idx];
|
||||
|
||||
if ( isset($a[$colDef["colName"]]) ) {
|
||||
$a_cmp = $a[$colDef["colName"]];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if ( isset($b[$colDef["colName"]]) ) {
|
||||
$b_cmp = $b[$colDef["colName"]];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(is_null($colDef["compareFunc"])){
|
||||
//$a_dt = strtotime($a_cmp);
|
||||
//$b_dt = strtotime($b_cmp);
|
||||
//if(($a_dt == -1) || ($b_dt == -1)) {
|
||||
$ret = $colDef["colDir"]*strnatcasecmp($a_cmp,$b_cmp);
|
||||
//}
|
||||
//else{
|
||||
// $ret = $colDef["colDir"]*(($a_dt > $b_dt)?1:(($a_dt < $b_dt)?-1:0));
|
||||
//}
|
||||
}
|
||||
else{
|
||||
$code = '$ret = ' . $colDef["compareFunc"] . '("' . $a_cmp . '","' . $b_cmp . '");';
|
||||
eval($code);
|
||||
$ret = $colDef["colDir"]*$ret;
|
||||
}
|
||||
if($ret == 0){
|
||||
if($idx < (count($this->sortDef)-1))
|
||||
return $this->_compare($a,$b,$idx+1);
|
||||
else
|
||||
return $ret;
|
||||
}
|
||||
else
|
||||
return $ret;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
136
classes/misc/attachment.class.php
Normal file
136
classes/misc/attachment.class.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Model of an Attachment
|
||||
*/
|
||||
class MimeMailParser_attachment {
|
||||
|
||||
/**
|
||||
* @var $filename Filename
|
||||
*/
|
||||
public $filename;
|
||||
/**
|
||||
* @var $content_type Mime Type
|
||||
*/
|
||||
public $content_type;
|
||||
/**
|
||||
* @var $content File Content
|
||||
*/
|
||||
private $content;
|
||||
/**
|
||||
* @var $extension Filename extension
|
||||
*/
|
||||
private $extension;
|
||||
/**
|
||||
* @var $content_disposition Content-Disposition (attachment or inline)
|
||||
*/
|
||||
public $content_disposition;
|
||||
/**
|
||||
* @var $headers An Array of the attachment headers
|
||||
*/
|
||||
public $headers;
|
||||
|
||||
private $stream;
|
||||
|
||||
public function __construct($filename, $content_type, $stream, $content_disposition = 'attachment', $headers = array()) {
|
||||
$this->filename = $filename;
|
||||
$this->content_type = $content_type;
|
||||
$this->stream = $stream;
|
||||
$this->content = null;
|
||||
$this->content_disposition = $content_disposition;
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve the attachment filename
|
||||
* @return String
|
||||
*/
|
||||
public function getFilename() {
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Content-Type
|
||||
* @return String
|
||||
*/
|
||||
public function getContentType() {
|
||||
return $this->content_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Content-Disposition
|
||||
* @return String
|
||||
*/
|
||||
public function getContentDisposition() {
|
||||
return $this->content_disposition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Headers
|
||||
* @return String
|
||||
*/
|
||||
public function getHeaders() {
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the file extension
|
||||
* @return String
|
||||
*/
|
||||
public function getFileExtension() {
|
||||
if (!$this->extension) {
|
||||
$ext = substr(strrchr($this->filename, '.'), 1);
|
||||
if ($ext == 'gz') {
|
||||
// special case, tar.gz
|
||||
// todo: other special cases?
|
||||
$ext = preg_match("/\.tar\.gz$/i", $ext) ? 'tar.gz' : 'gz';
|
||||
}
|
||||
$this->extension = $ext;
|
||||
}
|
||||
return $this->extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the contents a few bytes at a time until completed
|
||||
* Once read to completion, it always returns false
|
||||
* @return String
|
||||
* @param $bytes Int[optional]
|
||||
*/
|
||||
public function read($bytes = 2082) {
|
||||
return feof($this->stream) ? false : fread($this->stream, $bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the file content in one go
|
||||
* Once you retreive the content you cannot use MimeMailParser_attachment::read()
|
||||
* @return String
|
||||
*/
|
||||
public function getContent() {
|
||||
if ($this->content === null) {
|
||||
fseek($this->stream, 0);
|
||||
while(($buf = $this->read()) !== false) {
|
||||
$this->content .= $buf;
|
||||
}
|
||||
}
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the properties
|
||||
* MimeMailParser_attachment::$name,
|
||||
* MimeMailParser_attachment::$extension
|
||||
* to be retrieved as public properties
|
||||
* @param $name Object
|
||||
*/
|
||||
public function __get($name) {
|
||||
if ($name == 'content') {
|
||||
return $this->getContent();
|
||||
} else if ($name == 'extension') {
|
||||
return $this->getFileExtension();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
1179
classes/misc/is_email.php
Normal file
1179
classes/misc/is_email.php
Normal file
File diff suppressed because it is too large
Load Diff
94
classes/misc/signature_to_image.class.php
Normal file
94
classes/misc/signature_to_image.class.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Signature to Image: A supplemental script for Signature Pad that
|
||||
* generates an image of the signature’s JSON output server-side using PHP.
|
||||
*
|
||||
* @project ca.thomasjbradley.applications.signaturetoimage
|
||||
* @author Thomas J Bradley <hey@thomasjbradley.ca>
|
||||
* @link http://thomasjbradley.ca/lab/signature-to-image
|
||||
* @link http://github.com/thomasjbradley/signature-to-image
|
||||
* @copyright Copyright MMXI–, Thomas J Bradley
|
||||
* @license New BSD License
|
||||
* @version 1.0.1
|
||||
*/
|
||||
|
||||
/**
|
||||
* Accepts a signature created by signature pad in Json format
|
||||
* Converts it to an image resource
|
||||
* The image resource can then be changed into png, jpg whatever PHP GD supports
|
||||
*
|
||||
* To create a nicely anti-aliased graphic the signature is drawn 12 times it's original size then shrunken
|
||||
*
|
||||
* @param string|array $json
|
||||
* @param array $options OPTIONAL; the options for image creation
|
||||
* imageSize => array(width, height)
|
||||
* bgColour => array(red, green, blue)
|
||||
* penWidth => int
|
||||
* penColour => array(red, green, blue)
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
function sigJsonToImage($json, $options = array())
|
||||
{
|
||||
$defaultOptions = array(
|
||||
'imageSize' => array(198, 55)
|
||||
,'bgColour' => array(0xff, 0xff, 0xff)
|
||||
,'penWidth' => 2
|
||||
,'penColour' => array(0x14, 0x53, 0x94)
|
||||
,'drawMultiplier'=> 12
|
||||
);
|
||||
|
||||
$options = array_merge($defaultOptions, $options);
|
||||
|
||||
$img = imagecreatetruecolor($options['imageSize'][0] * $options['drawMultiplier'], $options['imageSize'][1] * $options['drawMultiplier']);
|
||||
$bg = imagecolorallocate($img, $options['bgColour'][0], $options['bgColour'][1], $options['bgColour'][2]);
|
||||
$pen = imagecolorallocate($img, $options['penColour'][0], $options['penColour'][1], $options['penColour'][2]);
|
||||
imagefill($img, 0, 0, $bg);
|
||||
|
||||
if(is_string($json))
|
||||
$json = json_decode(stripslashes($json));
|
||||
|
||||
foreach($json as $v)
|
||||
drawThickLine($img, $v->lx * $options['drawMultiplier'], $v->ly * $options['drawMultiplier'], $v->mx * $options['drawMultiplier'], $v->my * $options['drawMultiplier'], $pen, $options['penWidth'] * ($options['drawMultiplier'] / 2));
|
||||
|
||||
$imgDest = imagecreatetruecolor($options['imageSize'][0], $options['imageSize'][1]);
|
||||
imagecopyresampled($imgDest, $img, 0, 0, 0, 0, $options['imageSize'][0], $options['imageSize'][0], $options['imageSize'][0] * $options['drawMultiplier'], $options['imageSize'][0] * $options['drawMultiplier']);
|
||||
|
||||
imagedestroy($img);
|
||||
|
||||
return $imgDest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a thick line
|
||||
* Changing the thickness of a line using imagesetthickness doesn't produce as nice of result
|
||||
*
|
||||
* @param object $img
|
||||
* @param int $startX
|
||||
* @param int $startY
|
||||
* @param int $endX
|
||||
* @param int $endY
|
||||
* @param object $colour
|
||||
* @param int $thickness
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function drawThickLine($img, $startX, $startY, $endX, $endY, $colour, $thickness)
|
||||
{
|
||||
$angle = (atan2(($startY - $endY), ($endX - $startX)));
|
||||
|
||||
$dist_x = $thickness * (sin($angle));
|
||||
$dist_y = $thickness * (cos($angle));
|
||||
|
||||
$p1x = ceil(($startX + $dist_x));
|
||||
$p1y = ceil(($startY + $dist_y));
|
||||
$p2x = ceil(($endX + $dist_x));
|
||||
$p2y = ceil(($endY + $dist_y));
|
||||
$p3x = ceil(($endX - $dist_x));
|
||||
$p3y = ceil(($endY - $dist_y));
|
||||
$p4x = ceil(($startX - $dist_x));
|
||||
$p4y = ceil(($startY - $dist_y));
|
||||
|
||||
$array = array(0=>$p1x, $p1y, $p2x, $p2y, $p3x, $p3y, $p4x, $p4y);
|
||||
imagefilledpolygon($img, $array, (count($array)/2), $colour);
|
||||
}
|
Reference in New Issue
Block a user