I'm trying ta make a program that will ask the user for a number and then show all the prime numbers between 0 to this number in an array.
<?php
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
/* YOUR CODE HERE */
function isPrime($n)
{
if ($n <= 1)
return false;
for ($i = 2; $i < $n; $i++)
if ($n % $i == 0)
return false;
return true;
}
function printPrime($n)
{
for ($i = 2; $i <= $n; $i++)
{
if (isPrime($i))
echo $i . " ";
}
}
$n = 7;
printPrime($n);
/*end of your code here */
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}
}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
This code work, but with a $n fixed.
I don't know how to use an input who ask the user a number
It's a code who verify itself and show us when it's ok
The code that i have to complete is this one (we only have this at first):
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
/* YOUR CODE HERE */
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}
}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
This is your script:
<?php
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
function isPrime($n) {
if ($n <= 1) return false;
for ($i = 2; $i < $n; $i++) if ($n % $i == 0) return false;
return true;
}
function printPrime($n) {
for ($i = 2; $i < $n; $i++) if (isPrime($i)) $result[] = $i;
return $result;
}
$result = printPrime($smaller_than);
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
function getSmallerPrimes($smaller_than) {
if ($smaller_than <= 2) {
return [];
}
$result = [2];
$sqrt = sqrt($smaller_than);
for ($n = 3; $n < $smaller_than; $n += 2) {
$isPrime = true;
foreach($result as $prime) {
if ($n % $prime == 0) {
$isPrime = false;
break;
}
if ($prime > $sqrt) {
break;
}
}
if ($isPrime) {
$result[] = $n;
}
}
return $result;
}
$input = 23;
echo implode(' ', getSmallerPrimes($input));
Result: 2 3 5 7 11 13 17 19
I have a situation showed in the PHP code below, and I want to make a recursive function called check_recursive().
I have made the check_recursive() function below, but I want a recursive function, if it is possible.
Thank You!
$menu = '[{"id":"3|case_studies","children":[{"id":"2|case_studies","children":[{"id":"1|custom_links","children":[{"id":"2|faqe"}]}]}]},{"id":"11|klientet","children":[{"id":"8|klientet","children":[{"id":"7|klientet"}]}]},{"id":"9|klientet","children":[{"id":"10|klientet"}]},{"id":"4|klientet"}]';
$old_menu = json_decode($menu, true);
$new_menu = $this->check_recursive($old_menu);
function check_recursive($old_menu)
{
$i = 0;
$new_menu = [];
foreach ($old_menu as $menu_item)
{
if($name = $this->check_menu($menu_item['id']))
{
$new_menu[$i]['id'] = $menu_item['id'] . '|' . $name;
if(isset($menu_item['children']))
{
$e = 0;
foreach ($menu_item['children'] as $menu_item)
{
if($name = $this->check_menu($menu_item['id']))
{
$new_menu[$i]['children'][$e]['id'] = $menu_item['id'] . '|' . $name;
if(isset($menu_item['children']))
{
$y = 0;
foreach ($menu_item['children'] as $menu_item)
{
if($name = $this->check_menu($menu_item['id']))
{
$new_menu[$i]['children'][$e]['children'][$y]['id'] = $menu_item['id'] . '|' . $name;
if(isset($menu_item['children']))
{
$a = 0;
foreach ($menu_item['children'] as $menu_item)
{
if($name = $this->check_menu($menu_item['id']))
{
$new_menu[$i]['children'][$e]['children'][$y]['children'][$a]['id'] = $menu_item['id'] . '|' . $name;
}
$a++;
}
}
}
$y++;
}
}
}
$e++;
}
}
}
$i++;
}
return $new_menu;
}
function check_menu($string){
//Check if string exists in database
if($string){
return 'String exists';
}
return false;
}
I came up with this :
$menu = '[{"id":"3|case_studies","children":[{"id":"2|case_studies","children":[{"id":"1|custom_links","children":[{"id":"2|faqe"}]}]}]},{"id":"11|klientet","children":[{"id":"8|klientet","children":[{"id":"7|klientet"}]}]},{"id":"9|klientet","children":[{"id":"10|klientet"}]},{"id":"4|klientet"}]';
$old_menu = json_decode($menu, true);
$new_menu = check_recursive($old_menu);
function check_recursive($old_menu)
{
$new_menu = array();
foreach ($old_menu as $item) {
$name = check_menu($item['id']);
if($name){
$new_item = array(
'id' => $item['id'] . '|' . $name,
);
if(isset($item['children'])){
$new_item['children'] = check_recursive($item['children']);
}
$new_menu[] = $new_item;
}
}
return $new_menu;
}
function check_menu($string)
{
//Check if string exists in database
if ($string) {
return 'String exists';
}
return false;
}
Let me know if it suits your needs.
I'm trying to scrape Amazon ASIN codes using the below code:
<?php
class Scraper {
const BASE_URL = "http://www.amazon.com";
private $categoryFile = "";
private $outputFile = "";
private $catArray;
private $currentPage = NULL;
private $asin = array();
private $categoriesMatched = 0;
private $categoryProducts = array();
private $pagesMatched = 0;
private $totalPagesMatched = 0;
private $productsMatched = 0;
public function __construct($categoryFile, $outputFile) {
$this->categoryFile = $categoryFile;
$this->outputFile = $outputFile;
}
public function run() {
$this->readCategories($this->categoryFile);
$this->setupASINArray($this->asin);
$x = 1;
foreach ($this->catArray as $cat) {
$this->categoryProducts["$x"] = 0;
if ($this->currentPage == NULL) {
$this->currentPage = $cat;
$this->scrapeASIN($this->currentPage, $x);
$this->pagesMatched++;
}
if ($this->getNextPageLink($this->currentPage)) {
do {
// next page found
$this->pagesMatched++;
$this->scrapeASIN($this->currentPage, $x);
} while ($this->getNextPageLink($this->currentPage));
}
echo "Category complete: $this->pagesMatched Pages" . "\n";
$this->totalPagesMatched += $this->pagesMatched;
$this->pagesMatched = 0;
$this->writeASIN($this->outputFile, $x);
$x++;
$this->currentPage = NULL;
$this->categoriesMatched++;
}
$this->returnStats();
}
private function readCategories($categoryFile) {
$catArray = file($categoryFile, FILE_IGNORE_NEW_LINES);
$this->catArray = $catArray;
}
private function setupASINArray($asinArray) {
$x = 0;
foreach ($this->catArray as $cat) {
$asinArray["$x"][0] = "$cat";
$x++;
}
$this->asin = $asinArray;
}
private function getNextPageLink($currentPage) {
$document = new DOMDocument();
$html = file_get_contents($currentPage);
#$document->loadHTML($html);
$xpath = new DOMXPath($document);
$element = $xpath->query("//a[#id='pagnNextLink']/#href");
if ($element->length != 0) {
$this->currentPage = self::BASE_URL . $element->item(0)->value;
return true;
} else {
return false;
}
}
private function scrapeASIN($currentPage, $catNo) {
$html = file_get_contents($currentPage);
$regex = '~(?:www\.)?ama?zo?n\.(?:com|ca|co\.uk|co\.jp|de|fr)/(?:exec/obidos/ASIN/|o/|gp/product/|(?:(?:[^"\'/]*)/)?dp/|)(B[A-Z0-9]{9})(?:(?:/|\?|\#)(?:[^"\'\s]*))?~isx';
preg_match_all($regex, $html, $asin);
foreach ($asin[1] as $match) {
$this->asin[$catNo-1][] = $match;
}
}
private function writeASIN($outputFile, $catNo) {
$fh = fopen($outputFile, "a+");
$this->fixDupes($catNo);
$this->productsMatched += (count($this->asin[$catNo-1]) - 1);
$this->categoryProducts["$catNo"] = (count($this->asin[$catNo-1]) - 1);
flock($fh, LOCK_EX);
$x = 0;
foreach ($this->asin[$catNo-1] as $asin) {
fwrite($fh, "$asin" . "\n");
$x++;
}
flock($fh, LOCK_UN);
fclose($fh);
$x -= 1;
echo "$x ASIN codes written to file" . "\n";
}
private function fixDupes($catNo) {
$this->asin[$catNo-1] = array_unique($this->asin[$catNo-1], SORT_STRING);
}
public function returnStats() {
echo "Categories matched: " . $this->categoriesMatched . "\n";
echo "Pages parsed: " . $this->totalPagesMatched . "\n";
echo "Products parsed: " . $this->productsMatched . "\n";
echo "Category breakdown:" . "\n";
$x = 1;
foreach ($this->categoryProducts as $catProds) {
echo "Category $x had $catProds products" . "\n";
$x++;
}
}
}
$scraper = new Scraper($argv[1], $argv[2]);
$scraper->run();
?>
But it works fine on XAMPP on Windows but not on Linux. Any ideas as to why this may be? Sometimes it scrapes 0 ASIN's to file, sometimes it only scrapes 1 page in a category of 400+ pages. But the output/functionality is totally fine in Windows/XAMPP.
Any thoughts would be greatly appreciated!
Cheers
- Bryce
So try to change this way, just to avoid the error messages:
private function readCategories($categoryFile) {
if (file_exists($categoryFile)) {
$catArray = file($categoryFile, FILE_IGNORE_NEW_LINES);
$this->catArray = $catArray;
} else {
echo "File ".$categoryFile.' not exists!';
$this->catArray = array();
}
}
I am using the PHP imap function to get emails from a POP3 mailbox and insert the data into a MySQL database.
Here is the PHP code:
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect: ' . imap_last_error());
$emails = imap_search($inbox,'ALL');
if($emails)
{
$output = '';
rsort($emails);
foreach($emails as $email_number)
{
$header=imap_headerinfo($inbox,$email_number);
$from = $header->from[0]->mailbox . "#" . $header->from[0]->host;
$toaddress=$header->toaddress;
$replyto=$header->reply_to[0]->mailbox."#".$header->reply_to[0]->host;
$datetime=date("Y-m-d H:i:s",$header->udate);
$subject=$header->subject;
//remove the " from the $toaddress
$toaddress = str_replace('"','',$toaddress);
echo '<strong>To:</strong> '.$toaddress.'<br>';
echo '<strong>From:</strong> '.$from.'<br>';
echo '<strong>Subject:</strong> '.$subject.'<br>';
//get message body
$message = (imap_fetchbody($inbox,$email_number,1.1));
if($message == '')
{
$message = (imap_fetchbody($inbox,$email_number,1));
}
}
It works fine, however on some emails in the body I get = in between words, or =20 in between words. And other times the emails will just be blank even though they are not blank when sent.
This only happens when coming from certain emails.
How can I get round this and just make the email completely plain text?
This happens because the emails are normally Quoted-printable encoded. The = is a soft line break and =20 is a white space. I think, you could use quoted_printable_decode() on the message so it shows correctly. About the blank emails, I don't know, I would need more details.
Basically:
//get message body
$message = quoted_printable_decode(imap_fetchbody($inbox,$email_number,1.1));
$data = imap_fetchbody($this->imapStream, $Part->uid, $Part->path, FT_UID | FT_PEEK);
if ($Part->format === 'quoted-printable' && $data) {
$data = quoted_printable_decode($data);
}
This is required for mails with
Content-Transfer-Encoding: quoted-printable
But for mails with
Content-Transfer-Encoding: 8bit
simply imap_fetchbody is enough.
Above code was taken from a cake-php component created for fetching mails from mail boxes throgh IMAP.
I made an entire class some years ago, and I'm still using it when I need to get contents from emails. It will help you fetch all email bodies (sometimes you have html and plain text) in a readable format, and get all attached files, just ready to be saved somewhere or sent to a website user.
It is not really optimized so on a big mailbox you may have troubles; but the purpose of this class was to access emails in a readable format to put them on a widget of a website. I let you play with the sample below to get how it works.
ImapReader.class.php Here is the source code.
<?php
class ImapReader
{
private $host;
private $port;
private $user;
private $pass;
private $box;
private $box_list;
private $errors;
private $connected;
private $list;
private $deleted;
const FROM = 0;
const TO = 1;
const REPLY_TO = 2;
const SUBJECT = 3;
const CONTENT = 4;
const ATTACHMENT = 5;
public function __construct($host = null, $port = '143', $user = null, $pass = null)
{
$this->host = $host;
$this->port = $port;
$this->user = $user;
$this->pass = $pass;
$this->box = null;
$this->box_list = null;
$this->errors = array ();
$this->connected = false;
$this->list = null;
$this->deleted = false;
}
public function __destruct()
{
if ($this->isConnected())
{
$this->disconnect();
}
}
public function changeServer($host = null, $port = '143', $user = null, $pass = null)
{
if ($this->isConnected())
{
$this->disconnect();
}
$this->host = $host;
$this->port = $port;
$this->user = $user;
$this->pass = $pass;
$this->box_list = null;
$this->errors = array ();
$this->list = null;
return $this;
}
public function canConnect()
{
return (($this->connected == false) && (is_string($this->host)) && (!empty($this->host))
&& (is_numeric($this->port)) && ($this->port >= 1) && ($this->port <= 65535)
&& (is_string($this->user)) && (!empty($this->user)) && (is_string($this->pass)) && (!empty($this->pass)));
}
public function connect()
{
if ($this->canConnect())
{
$this->box = #imap_open("{{$this->host}:{$this->port}/imap/ssl/novalidate-cert}INBOX", $this->user,
$this->pass);
if ($this->box !== false)
{
$this->_connected();
}
else
{
$this->errors = array_merge($this->errors, imap_errors());
}
}
return $this;
}
public function boxList()
{
if (is_null($this->box_list))
{
$list = imap_getsubscribed($this->box, "{{$this->host}:{$this->port}}", "*");
$this->box_list = array ();
foreach ($list as $box)
{
$this->box_list[] = $box->name;
}
}
return $this->box_list;
}
public function fetchAllHeaders($mbox)
{
if ($this->isConnected())
{
$test = imap_reopen($this->box, "{$mbox}");
if (!$test)
{
return false;
}
$num_msgs = imap_num_msg($this->box);
$this->list = array ();
for ($id = 1; ($id <= $num_msgs); $id++)
{
$this->list[] = $this->_fetchHeader($mbox, $id);
}
return true;
}
return false;
}
public function fetchSearchHeaders($mbox, $criteria)
{
if ($this->isConnected())
{
$test = imap_reopen($this->box, "{$mbox}");
if (!$test)
{
return false;
}
$msgs = imap_search($this->box, $criteria);
if ($msgs)
{
foreach ($msgs as $id)
{
$this->list[] = $this->_fetchHeader($mbox, $id);
}
}
return true;
}
return false;
}
public function isConnected()
{
return $this->connected;
}
public function disconnect()
{
if ($this->connected)
{
if ($this->deleted)
{
imap_expunge($this->box);
$this->deleted = false;
}
imap_close($this->box);
$this->connected = false;
$this->box = null;
}
return $this;
}
/**
* Took from khigashi dot oang at gmail dot com at php.net
* with replacement of ereg family functions by preg's ones.
*
* #param string $str
* #return string
*/
private function _fix($str)
{
if (preg_match("/=\?.{0,}\?[Bb]\?/", $str))
{
$str = preg_split("/=\?.{0,}\?[Bb]\?/", $str);
while (list($key, $value) = each($str))
{
if (preg_match("/\?=/", $value))
{
$arrTemp = preg_split("/\?=/", $value);
$arrTemp[0] = base64_decode($arrTemp[0]);
$str[$key] = join("", $arrTemp);
}
}
$str = join("", $str);
}
if (preg_match("/=\?.{0,}\?Q\?/", $str))
{
$str = quoted_printable_decode($str);
$str = preg_replace("/=\?.{0,}\?[Qq]\?/", "", $str);
$str = preg_replace("/\?=/", "", $str);
}
return trim($str);
}
private function _connected()
{
$this->connected = true;
return $this;
}
public function getErrors()
{
$errors = $this->errors;
$this->errors = array ();
return $errors;
}
public function count()
{
if (is_null($this->list))
{
return 0;
}
return count($this->list);
}
public function get($nbr = null)
{
if (is_null($nbr))
{
return $this->list;
}
if ((is_array($this->list)) && (isset($this->list[$nbr])))
{
return $this->list[$nbr];
}
return null;
}
public function fetch($nbr = null)
{
return $this->_callById('_fetch', $nbr);
}
private function _fetchHeader($mbox, $id)
{
$header = imap_header($this->box, $id);
if (!is_object($header))
{
return;
}
$mail = new stdClass();
$mail->id = $id;
$mail->mbox = $mbox;
$mail->timestamp = (isset($header->udate)) ? ($header->udate) : ('');
$mail->date = date("d/m/Y H:i:s", (isset($header->udate)) ? ($header->udate) : (''));
$mail->from = $this->_fix(isset($header->fromaddress) ? ($header->fromaddress) : (''));
$mail->to = $this->_fix(isset($header->toaddress) ? ($header->toaddress) : (''));
$mail->reply_to = $this->_fix(isset($header->reply_toaddress) ? ($header->reply_toaddress) : (''));
$mail->subject = $this->_fix(isset($header->subject) ? ($header->subject) : (''));
$mail->content = array ();
$mail->attachments = array ();
$mail->deleted = false;
return $mail;
}
private function _fetch($mail)
{
$test = imap_reopen($this->box, "{$mail->mbox}");
if (!$test)
{
return $mail;
}
$structure = imap_fetchstructure($this->box, $mail->id);
if ((!isset($structure->parts)) || (!is_array($structure->parts)))
{
$body = imap_body($this->box, $mail->id);
$content = new stdClass();
$content->type = 'content';
$content->mime = $this->_fetchType($structure);
$content->charset = $this->_fetchParameter($structure->parameters, 'charset');
$content->data = $this->_decode($body, $structure->type);
$content->size = strlen($content->data);
$mail->content[] = $content;
return $mail;
}
else
{
$parts = $this->_fetchPartsStructureRoot($mail, $structure);
foreach ($parts as $part)
{
$content = new stdClass();
$content->type = null;
$content->data = null;
$content->mime = $this->_fetchType($part->data);
if ((isset($part->data->disposition))
&& ((strcmp('attachment', $part->data->disposition) == 0)
|| (strcmp('inline', $part->data->disposition) == 0)))
{
$content->type = $part->data->disposition;
$content->name = null;
if (isset($part->data->dparameters))
{
$content->name = $this->_fetchParameter($part->data->dparameters, 'filename');
}
if (is_null($content->name))
{
if (isset($part->data->parameters))
{
$content->name = $this->_fetchParameter($part->data->parameters, 'name');
}
}
$mail->attachments[] = $content;
}
else if ($part->data->type == 0)
{
$content->type = 'content';
$content->charset = null;
if (isset($part->data->parameters))
{
$content->charset = $this->_fetchParameter($part->data->parameters, 'charset');
}
$mail->content[] = $content;
}
$body = imap_fetchbody($this->box, $mail->id, $part->no);
if (isset($part->data->encoding))
{
$content->data = $this->_decode($body, $part->data->encoding);
}
else
{
$content->data = $body;
}
$content->size = strlen($content->data);
}
}
return $mail;
}
private function _fetchPartsStructureRoot($mail, $structure)
{
$parts = array ();
if ((isset($structure->parts)) && (is_array($structure->parts)) && (count($structure->parts) > 0))
{
foreach ($structure->parts as $key => $data)
{
$this->_fetchPartsStructure($mail, $data, ($key + 1), $parts);
}
}
return $parts;
}
private function _fetchPartsStructure($mail, $structure, $prefix, &$parts)
{
if ((isset($structure->parts)) && (is_array($structure->parts)) && (count($structure->parts) > 0))
{
foreach ($structure->parts as $key => $data)
{
$this->_fetchPartsStructure($mail, $data, $prefix . "." . ($key + 1), $parts);
}
}
$part = new stdClass;
$part->no = $prefix;
$part->data = $structure;
$parts[] = $part;
}
private function _fetchParameter($parameters, $key)
{
foreach ($parameters as $parameter)
{
if (strcmp($key, $parameter->attribute) == 0)
{
return $parameter->value;
}
}
return null;
}
private function _fetchType($structure)
{
$primary_mime_type = array ("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
if ((isset($structure->subtype)) && ($structure->subtype) && (isset($structure->type)))
{
return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype;
}
return "TEXT/PLAIN";
}
private function _decode($message, $coding)
{
switch ($coding)
{
case 2:
$message = imap_binary($message);
break;
case 3:
$message = imap_base64($message);
break;
case 4:
$message = imap_qprint($message);
break;
case 5:
break;
default:
break;
}
return $message;
}
private function _callById($method, $data)
{
$callback = array ($this, $method);
// data is null
if (is_null($data))
{
$result = array ();
foreach ($this->list as $mail)
{
$result[] = $this->_callById($method, $mail);
}
return $result;
}
// data is an array
if (is_array($data))
{
$result = array ();
foreach ($data as $elem)
{
$result[] = $this->_callById($method, $elem);
}
return $result;
}
// data is an object
if ((is_object($data)) && ($data instanceof stdClass) && (isset($data->id)))
{
return call_user_func($callback, $data);
}
// data is numeric
if (($this->isConnected()) && (is_array($this->list)) && (is_numeric($data)))
{
foreach ($this->list as $mail)
{
if ($mail->id == $data)
{
return call_user_func($callback, $mail);
}
}
}
return null;
}
public function delete($nbr)
{
$this->_callById('_delete', $nbr);
return;
}
private function _delete($mail)
{
if ($mail->deleted == false)
{
$test = imap_reopen($this->box, "{$mail->mbox}");
if ($test)
{
$this->deleted = true;
imap_delete($this->box, $mail->id);
$mail->deleted = true;
}
}
}
public function searchBy($pattern, $type)
{
$result = array ();
if (is_array($this->list))
{
foreach ($this->list as $mail)
{
$match = false;
switch ($type)
{
case self::FROM:
$match = $this->_match($mail->from, $pattern);
break;
case self::TO:
$match = $this->_match($mail->to, $pattern);
break;
case self::REPLY_TO:
$match = $this->_match($mail->reply_to, $pattern);
break;
case self::SUBJECT:
$match = $this->_match($mail->subject, $pattern);
break;
case self::CONTENT:
foreach ($mail->content as $content)
{
$match = $this->_match($content->data, $pattern);
if ($match)
{
break;
}
}
break;
case self::ATTACHMENT:
foreach ($mail->attachments as $attachment)
{
$match = $this->_match($attachment->name, $pattern);
if ($match)
{
break;
}
}
break;
}
if ($match)
{
$result[] = $mail;
}
}
}
return $result;
}
private function _nmatch($string, $pattern, $a, $b)
{
if ((!isset($string[$a])) && (!isset($pattern[$b])))
{
return 1;
}
if ((isset($pattern[$b])) && ($pattern[$b] == '*'))
{
if (isset($string[$a]))
{
return ($this->_nmatch($string, $pattern, ($a + 1), $b) + $this->_nmatch($string, $pattern, $a, ($b + 1)));
}
else
{
return ($this->_nmatch($string, $pattern, $a, ($b + 1)));
}
}
if ((isset($string[$a])) && (isset($pattern[$b])) && ($pattern[$b] == '?'))
{
return ($this->_nmatch($string, $pattern, ($a + 1), ($b + 1)));
}
if ((isset($string[$a])) && (isset($pattern[$b])) && ($pattern[$b] == '\\'))
{
if ((isset($pattern[($b + 1)])) && ($string[$a] == $pattern[($b + 1)]))
{
return ($this->_nmatch($string, $pattern, ($a + 1), ($b + 2)));
}
}
if ((isset($string[$a])) && (isset($pattern[$b])) && ($string[$a] == $pattern[$b]))
{
return ($this->_nmatch($string, $pattern, ($a + 1), ($b + 1)));
}
return 0;
}
private function _match($string, $pattern)
{
return $this->_nmatch($string, $pattern, 0, 0);
}
}
ImapReader.demo.php Here is the usage sample
<?php
require_once("ImapReader.class.php");
$box = new ImapReader('example.com', '143', 'somebody#example.com', 'xxxxxxxxxxxx');
$box
->connect()
->fetchAllHeaders()
;
echo $box->count() . " emails in mailbox\n";
for ($i = 0; ($i < $box->count()); $i++)
{
$msg = $box->get($i);
echo "Reception date : {$msg->date}\n";
echo "From : {$msg->from}\n";
echo "To : {$msg->to}\n";
echo "Reply to : {$msg->from}\n";
echo "Subject : {$msg->subject}\n";
$msg = $box->fetch($msg);
echo "Number of readable contents : " . count($msg->content) . "\n";
foreach ($msg->content as $key => $content)
{
echo "\tContent " . ($key + 1) . " :\n";
echo "\t\tContent type : {$content->mime}\n";
echo "\t\tContent charset : {$content->charset}\n";
echo "\t\tContent size : {$content->size}\n";
}
echo "Number of attachments : " . count($msg->attachments) . "\n";
foreach ($msg->attachments as $key => $attachment)
{
echo "\tAttachment " . ($key + 1) . " :\n";
echo "\t\tAttachment type : {$attachment->type}\n";
echo "\t\tContent type : {$attachment->mime}\n";
echo "\t\tFile name : {$attachment->name}\n";
echo "\t\tFile size : {$attachment->size}\n";
}
echo "\n";
}
echo "Searching '*Bob*' ...\n";
$results = $box->searchBy('*Bob*', ImapReader::FROM);
foreach ($results as $result)
{
echo "\tMatched: {$result->from} - {$result->date} - {$result->subject}\n";
}
Enjoy
Regarding the blank emails, check the encoding of the mail.
If it is a binary encoded mail then you will get blank mails when you try to insert them into a mysql text field.
Try shifting every mail to UTF-8 and then insert it
iconv(mb_detect_encoding($mail_content, mb_detect_order(), true), "UTF-8", $mail_content);
function getmsg($mbox,$mid) {
// input $mbox = IMAP stream, $mid = message id
// output all the following:
global $charset,$htmlmsg,$plainmsg,$attachments;
$htmlmsg = $plainmsg = $charset = '';
$attachments = array();
// HEADER
$h = imap_header($mbox,$mid);
// add code here to get date, from, to, cc, subject...
// BODY
$s = imap_fetchstructure($mbox,$mid);
if (!$s->parts) // simple
getpart($mbox,$mid,$s,0); // pass 0 as part-number
else { // multipart: cycle through each part
foreach ($s->parts as $partno0=>$p)
getpart($mbox,$mid,$p,$partno0+1);
}
}
function getpart($mbox,$mid,$p,$partno) {
// $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
global $htmlmsg,$plainmsg,$charset,$attachments;
// DECODE DATA
$data = ($partno)?
imap_fetchbody($mbox,$mid,$partno): // multipart
imap_body($mbox,$mid); // simple
// Any part may be encoded, even plain text messages, so check everything.
if ($p->encoding==4)
$data = quoted_printable_decode($data);
elseif ($p->encoding==3)
$data = base64_decode($data);
// PARAMETERS
// get all parameters, like charset, filenames of attachments, etc.
$params = array();
if ($p->parameters)
foreach ($p->parameters as $x)
$params[strtolower($x->attribute)] = $x->value;
if ($p->dparameters)
foreach ($p->dparameters as $x)
$params[strtolower($x->attribute)] = $x->value;
// ATTACHMENT
// Any part with a filename is an attachment,
// so an attached text file (type 0) is not mistaken as the message.
if ($params['filename'] || $params['name']) {
// filename may be given as 'Filename' or 'Name' or both
$filename = ($params['filename'])? $params['filename'] : $params['name'];
// filename may be encoded, so see imap_mime_header_decode()
$attachments[$filename] = $data; // this is a problem if two files have same name
}
// TEXT
if ($p->type==0 && $data) {
// Messages may be split in different parts because of inline attachments,
// so append parts together with blank row.
if (strtolower($p->subtype)=='plain')
$plainmsg. = trim($data) ."\n\n";
else
$htmlmsg. = $data ."<br><br>";
$charset = $params['charset']; // assume all parts are same charset
}
// EMBEDDED MESSAGE
// Many bounce notifications embed the original message as type 2,
// but AOL uses type 1 (multipart), which is not handled here.
// There are no PHP functions to parse embedded messages,
// so this just appends the raw source to the main message.
elseif ($p->type==2 && $data) {
$plainmsg. = $data."\n\n";
}
// SUBPART RECURSION
if ($p->parts) {
foreach ($p->parts as $partno0=>$p2)
getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc.
}
}
Reference (First user contributed note): http://php.net/manual/en/function.imap-fetchstructure.php
I tried all this answers, but neither one worked for me. Then I hit first user contributed note on this PHP page:
http://php.net/manual/en/function.imap-fetchstructure.php
and this works for all my cases. Quite old answer btw.
I'm Using this PHP IMAP Class: http://code.google.com/p/php-imap/source/browse/trunk/ImapMailbox.php on a current project. After a few modifications the class is working. However whenever the class downloads .docx files they are always corrupt and have to be recovered by office.
protected function initMailPart(IncomingMail $mail, $partStruct, $partNum) {
$data = $partNum ? $this->imap_fetchbody($this->mbox, $mail->mId, $partNum, FT_UID) : $this->imap_body($this->mbox, $mail->mId, FT_UID);
if($partStruct->encoding == 1) {
$data = $this->imap_utf8($data);
}
elseif($partStruct->encoding == 2) {
$data = $this->imap_binary($data);
}
elseif($partStruct->encoding == 3) {
$data = $this->imap_base64($data);
}
elseif($partStruct->encoding == 4) {
$data = $this->imap_qprint($data);
}
$data = trim($data);
$params = array();
if(!empty($partStruct->parameters)) {
foreach($partStruct->parameters as $param) {
$params[strtolower($param->attribute)] = $param->value;
}
}
if(!empty($partStruct->dparameters)) {
foreach($partStruct->dparameters as $param) {
$params[strtolower($param->attribute)] = $param->value;
}
}
if(!empty($params['charset'])) {
$data = iconv($params['charset'], $this->serverEncoding, $data);
}
// attachments
if($this->attachmentsDir) {
$filename = false;
$attachmentId = $partStruct->ifid ? trim($partStruct->id, " <>") : null;
if(empty($params['filename']) && empty($params['name']) && $attachmentId) {
$filename = $attachmentId . '.' . strtolower($partStruct->subtype);
}
elseif(!empty($params['filename']) || !empty($params['name'])) {
$filename = !empty($params['filename']) ? $params['filename'] : $params['name'];
$filename = $this->decodeMimeStr($filename);
$filename = $this->quoteAttachmentFilename($filename);
}
if($filename) {
if($this->attachmentsDir) {
$filepath = rtrim($this->attachmentsDir, '/\\') . DIRECTORY_SEPARATOR . $filename;
file_put_contents($filepath, $data);
$mail->attachments[$filename] = $filepath;
}
else {
$mail->attachments[$filename] = $filename;
}
if($attachmentId) {
$mail->attachmentsIds[$filename] = $attachmentId;
}
}
}
if($partStruct->type == 0 && $data) {
if(strtolower($partStruct->subtype) == 'plain') {
$mail->textPlain .= $data;
}
else {
$mail->textHtml .= $data;
}
}
elseif($partStruct->type == 2 && $data) {
$mail->textPlain .= trim($data);
}
if(!empty($partStruct->parts)) {
foreach($partStruct->parts as $subpartNum => $subpartStruct) {
$this->initMailPart($mail, $subpartStruct, $partNum . '.' . ($subpartNum + 1));
}
}
}
protected function decodeMimeStr($string, $charset = 'UTF-8') {
$newString = '';
$elements = $this->imap_mime_header_decode($string);
for($i = 0; $i < count($elements); $i++) {
if($elements[$i]->charset == 'default') {
$elements[$i]->charset = 'iso-8859-1';
}
$newString .= iconv($elements[$i]->charset, $charset, $elements[$i]->text);
}
return $newString;
}
Try wading into the binary files with a good editor, both before and after the round-trip from IMAP, to see if there's something obvious. I've had similar problems where whitespace made its way into the PHP script (e.g. at the end of a file after the close ?> tag); most formats won't blink but .docx may get kicked into a recovery if there's whitespace left over at the end.