How to solve PHP7.2 database error due to Count() changes - php

I figured I'd test the new PHP 7.2 release to see how many problems it creates on my site (I've been using 7.1 before this without trouble) and I noted that it appeared to disrupt the MySQL database connection in the Dp.php file for one of my scripts with the following error:
An exception occurred: count(): Parameter must be an array or an object that implements Countable in /../Db.php on line 57
The code it references is this bit:
if (!count($dsn)) {
return $parsed;
}
I believe this is related to the 'counting non-countable types' change in 7.2 (http://php.net/manual/en/migration72.incompatible.php) and thing its probably due to a "null" value but I'm no expert in PHP and am not sure how to fix it. Just for context, here's the full code block that relates to $dsn in the Dp.php file:
class Censura_Db
{
protected $connected_server_info; //cache for server information
public static function factory($dsn, $options = false)
{
$class = new self($dsn, $options);
return $class;
}
public static function parseDSN($dsn)
{
$parsed = array();
if (is_array($dsn)) {
$dsn = array_merge($parsed, $dsn);
if (!$dsn['dbsyntax']) {
$dsn['dbsyntax'] = $dsn['phptype'];
}
return $dsn;
}
// Find phptype and dbsyntax
if (($pos = strpos($dsn, '://')) !== false) {
$str = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 3);
} else {
$str = $dsn;
$dsn = null;
}
// Get phptype and dbsyntax
// $str => phptype(dbsyntax)
if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
$parsed['phptype'] = $arr[1];
$parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
} else {
$parsed['phptype'] = $str;
$parsed['dbsyntax'] = $str;
}
if (!count($dsn)) {
return $parsed;
}
// Get (if found): username and password
// $dsn => username:password#protocol+hostspec/database
if (($at = strrpos($dsn, '#')) !== false) {
$str = substr($dsn, 0, $at);
$dsn = substr($dsn, $at + 1);
if (($pos = strpos($str, ':')) !== false) {
$parsed['username'] = rawurldecode(substr($str, 0, $pos));
$parsed['password'] = rawurldecode(substr($str, $pos + 1));
} else {
$parsed['username'] = rawurldecode($str);
}
}
// Find protocol and hostspec
// $dsn => proto(proto_opts)/database
if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
$proto = $match[1];
$proto_opts = $match[2] ? $match[2] : false;
$dsn = $match[3];
// $dsn => protocol+hostspec/database (old format)
} else {
if (strpos($dsn, '+') !== false) {
list($proto, $dsn) = explode('+', $dsn, 2);
}
if (strpos($dsn, '//') === 0
&& strpos($dsn, '/', 2) !== false
&& $parsed['phptype'] == 'oci8'
) {
//oracle's "Easy Connect" syntax:
//"username/password#[//]host[:port][/service_name]"
//e.g. "scott/tiger#//mymachine:1521/oracle"
$proto_opts = $dsn;
$dsn = null;
} elseif (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
} else {
$proto_opts = $dsn;
$dsn = null;
}
}
// process the different protocol options
$parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
$proto_opts = rawurldecode($proto_opts);
if (strpos($proto_opts, ':') !== false) {
list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
}
if ($parsed['protocol'] == 'tcp') {
$parsed['hostspec'] = $proto_opts;
} elseif ($parsed['protocol'] == 'unix') {
$parsed['socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if ($dsn) {
// /database
if (($pos = strpos($dsn, '?')) === false) {
$parsed['database'] = $dsn;
// /database?param1=value1&param2=value2
} else {
$parsed['database'] = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 1);
if (strpos($dsn, '&') !== false) {
$opts = explode('&', $dsn);
} else { // database?param1=value1
$opts = array($dsn);
}
foreach ($opts as $opt) {
list($key, $value) = explode('=', $opt);
if (!isset($parsed[$key])) {
// don't allow params overwrite
$parsed[$key] = rawurldecode($value);
}
}
}
}
return $parsed;
}

You're using count() on values that aren't arrays, apparently to check if they are null.
Use !== null or isset() instead.

Related

php to few arguments to my function when I call her 7.0

I have an error in my code when I compile :
Fatal error: Uncaught ArgumentCountError: Too few arguments to
function getData::QueryWhoisServer(), 0 passed in
C:\xampp\htdocs\testVisitor\index.php on line 19 and exactly 2
expected in C:\xampp\htdocs\testVisitor\Model\getData.php:72 Stack
trace: #0 C:\xampp\htdocs\testVisitor\index.php(19):
getData->QueryWhoisServer() #1 {main} thrown in
C:\xampp\htdocs\testVisitor\Model\getData.php on line 72
I know that since php 7.0 I need to pass argument but the argument are not recognize...
here is my code:
index.php :
require_Once('Model/getData.php');
require_Once('Controller/writeData.php');
$getData = new getData();
$writeData =new writeData();
$getData->get_ip();
$getData->LookupIP($domain);
$getData->ValidateIP($domain);
$getData->QueryWhoisServer();
if($domain && $pageEnCours != preg_match("#localhost/testVisitor/$#",$pageEnCours)) {
$domain = trim($domain);
if($getData->ValidateIP($domain)) {
$result = $getData->LookupIP($domain);
$writeData->write_domain($result);
}
else{
write_error();
};
}
echo $domain;
echo "cc";
and getData.php :
$urlPart1 = $_SERVER['HTTP_HOST'] ;
$urlPart2 = $_SERVER['REQUEST_URI'];
$pageEnCours = $urlPart1 .= $urlPart2;
$domain ='0.0.0.0';
class getData
{
// For the full list of TLDs/Whois servers see http://www.iana.org/domains/root/db/ and http://www.whois365.com/en/listtld/
/**
* Récupérer la véritable adresse IP d'un visiteur
*/
function get_ip() {
// IP si internet partagé
global $domain;
if (isset($_SERVER['HTTP_CLIENT_IP'])) {
return $domain =$_SERVER['HTTP_CLIENT_IP'];
}
// IP derrière un proxy
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
return $domain=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
// Sinon : IP normale
else {
return $domain=(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
}
}
function LookupIP($ip) {
$whoisservers = array(
//"whois.afrinic.net", // Africa - returns timeout error :-(
//"whois.lacnic.net", // Latin America and Caribbean - returns data for ALL locations worldwide :-)
//"whois.apnic.net", // Asia/Pacific only
//"whois.arin.net", // North America only
//"whois.ripe.net" // Europe, Middle East and Central Asia only
);
$results = array();
foreach($whoisservers as $whoisserver) {
$result = QueryWhoisServer($whoisserver, $ip);
if ($result && !in_array($result, $results)) {
$results[$whoisserver] = $result;
}
}
$res = "RESULTS FOUND: " . count($results);
foreach($results as $whoisserver=>$result) {
$res .= "\n\n-------------\nLookup results for " . $ip . " from " . $whoisserver . " server:\n\n" . $result;
}
return $res;
}
function ValidateIP($ip) {
$ipnums = explode(".", $ip);
if(count($ipnums) != 4) {
return false;
}
foreach($ipnums as $ipnum) {
if(!is_numeric($ipnum) || ($ipnum > 255)) {
return false;
}
}
return $ip;
}
function QueryWhoisServer($whoisserver , $domain ) {
$port = 43;
$timeout = 10;
$fp = #fsockopen($whoisserver, $port, $errno, $errstr, $timeout) or die("Socket Error " . $errno . " - " . $errstr);
//if($whoisserver == "whois.verisign-grs.com") $domain = "=".$domain; // whois.verisign-grs.com requires the equals sign ("=") or it returns any result containing the searched string.
fputs($fp, $domain . "\r\n");
$out = "";
while(!feof($fp)){
$out .= fgets($fp);
}
fclose($fp);
$res = "";
if((strpos(strtolower($out), "error") === FALSE) && (strpos(strtolower($out), "not allocated") === FALSE)) {
$rows = explode("\n", $out);
foreach($rows as $row) {
$row = trim($row);
if(($row != '') && ($row{0} != '#') && ($row{0} != '%') && ($row != preg_match("#^netname|^descr|^country|^person|^address|^phone#",$row ))) {
$res .= $row."\n";
}
}
}
return $res;
}
}
Too few arguments to function getData::QueryWhoisServer(), 0 passed in C:\xampp\htdocs\testVisitor\index.php
$getData->QueryWhoisServer(); is not providing any arguments.
In your function :
function QueryWhoisServer($whoisserver , $domain ) {
$port = 43;
$timeout = 10;
$fp = #fsockopen($whoisserver, $port, $errno, $errstr, $timeout)
fputs($fp, $domain . "\r\n");
$fp need $whoisserver,$portand$timeout
The $port and $timeout are defined in the function
But you need to specify $whoisserver and the $domain (domain is used in fputs) when you call this function,
That will be something like :
$getData->QueryWhoisServer($whoisserver, $domain);
Also in your function
LookupIP($domain);
The result use the fucntion QueryWhoisServer, so try to get the $result

Converting string to array address

I have dynamically generated array $array[], that could be multidimensional and I have a function that return string, which contains address in array (existing one). My question is: how to create or convert string $a = 'array[1]' to address $array[1]?
Example:
$array = [1,2,3,4];
$string = 'array[2]';
function magic($array, $string){
//some magic happens
return $result;
$result = magic($array, $string);
echo $result;
// and 3 is displayed;
Is there a function already to do this? Is it possible to do this?
This code is a modification of ResponseBag::get() from the wonderful HttpFoundation project:
function magic($array, $path, $default = null)
{
if (false === $pos = strpos($path, '[')) {
return $array;
}
$value = $array;
$currentKey = null;
for ($i = $pos, $c = strlen($path); $i < $c; $i++) {
$char = $path[$i];
if ('[' === $char) {
if (null !== $currentKey) {
throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i));
}
$currentKey = '';
} elseif (']' === $char) {
if (null === $currentKey) {
throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i));
}
if (!is_array($value) || !array_key_exists($currentKey, $value)) {
return $default;
}
$value = $value[$currentKey];
$currentKey = null;
} else {
if (null === $currentKey) {
throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i));
}
$currentKey .= $char;
}
}
if (null !== $currentKey) {
throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".'));
}
return $value;
}
echo magic([1,2,3,4], 'array[2]'); // 3
It can be modified to return a reference as well, just sprinkle it with some ampersands :)

php imap - get body and make plain text

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.

solve a bad Url to clean Url in php?

when I spide a website ,I got a lot of bad url like these.
http://example.com/../../.././././1.htm
http://example.com/test/../test/.././././1.htm
http://example.com/.//1.htm
http://example.com/../test/..//1.htm
all of these should be http://example.com/1.htm.
how to use PHP codes to do this ,thanks.
PS: I use http://snoopy.sourceforge.net/
I get a lot of repeated link in my database , the 'http://example.com/../test/..//1.htm' should be 'http://example.com/1.htm' .
You could do it like this, assuming all the urls you have provided are expected tobe http://example.com/1.htm:
$test = array('http://example.com/../../../././.\./1.htm',
'http://example.com/test/../test/../././.\./1.htm',
'http://example.com/.//1.htm',
'http://example.com/../test/..//1.htm');
foreach ($test as $url){
$u = parse_url($url);
$path = $u['scheme'].'://'.$u['host'].'/'.basename($u['path']);
echo $path.'<br />'.PHP_EOL;
}
/* result
http://example.com/1.htm<br />
http://example.com/1.htm<br />
http://example.com/1.htm<br />
http://example.com/1.htm<br />
*/
//or as a function #lpc2138
function getRealUrl($url){
$u = parse_url($url);
$path = $u['scheme'].'://'.$u['host'].'/'.basename($u['path']);
$path .= (!empty($u['query'])) ? '?'.$u['query'] : '';
return $path;
}
You seem to be looking for a algorithm to remove the dot segments:
function remove_dot_segments($abspath) {
$ib = $abspath;
$ob = '';
while ($ib !== '') {
if (substr($ib, 0, 3) === '../') {
$ib = substr($ib, 3);
} else if (substr($ib, 0, 2) === './') {
$ib = substr($ib, 2);
} else if (substr($ib, 0, 2) === '/.' && ($ib[2] === '/' || strlen($ib) === 2)) {
$ib = '/'.substr($ib, 3);
} else if (substr($ib, 0, 3) === '/..' && ($ib[3] === '/' || strlen($ib) === 3)) {
$ib = '/'.substr($ib, 4);
$ob = substr($ob, 0, strlen($ob)-strlen(strrchr($ob, '/')));
} else if ($ib === '.' || $ib === '..') {
$ib = '';
} else {
$pos = strpos($ib, '/', 1);
if ($pos === false) {
$ob .= $ib;
$ib = '';
} else {
$ob .= substr($ib, 0, $pos);
$ib = substr($ib, $pos);
}
}
}
return $ob;
}
This removes the . and .. segments. Any removal of any other segment like an empty one (//) or .\. is not as per standard as it changes the semantics of the path.
You could do some fancy regex but this works just fine.
fixUrl('http://example.com/../../../././.\./1.htm');
function fixUrl($str) {
$str = str_replace('../', '', $str);
$str = str_replace('./', '', $str);
$str = str_replace('\.', '', $str);
return $str;
}

How to get imap flags?

I used the imap4flag plugin for Dovecot sieve: http://wiki.dovecot.org/LDA/Sieve#Flagging_or_Highlighting_your_mail
The flag is correctly show in thunderbird but I search how get the flags for show them in roundcube.
Thank's in advance.
This is a missing feature, see the PHP bug #53043 : http://bugs.php.net/bug.php?id=53043
A example code using directly the IMAP protocol:
<?php
declare(strict_types=1);
class ImapSocket
{
private $socket;
public function __construct($options, $mailbox = '')
{
$this->socket = $this->connect($options['server'], $options['port'], $options['tls']);
$this->login($options['login'], $options['password']);
if ($mailbox !== null) {
$this->select_mailbox($mailbox);
}
}
private function connect(string $server, int $port, bool $tls)
{
if ($tls === true) {
$server = "tls://$server";
}
$fd = fsockopen($server, $port, $errno);
if (!$errno) {
return $fd;
}
else {
throw new \Exception('Unable to connect');
}
}
private function login(string $login, string $password): void
{
$result = $this->send("LOGIN $login $password");
$result = array_pop($result);
if (substr($result, 0, 5) !== '. OK ') {
throw new \Exception('Unable to login');
}
}
public function __destruct()
{
fclose($this->socket);
}
public function select_mailbox(string $mailbox): void
{
$result = $this->send("SELECT $mailbox");
$result = array_pop($result);
if (substr($result, 0, 5) !== '. OK ') {
throw new \Exception("Unable to select mailbox '$mailbox'");
}
}
public function get_flags(int $uid): array
{
$result = $this->send("FETCH $uid (FLAGS)");
preg_match_all("|\\* \\d+ FETCH \\(FLAGS \\((.*)\\)\\)|", $result[0], $matches);
if (isset($matches[1][0])) {
return explode(' ', $matches[1][0]);
}
else {
return [];
}
}
private function send(string $cmd, string $uid = '.')
{
$query = "$uid $cmd\r\n";
$count = fwrite($this->socket, $query);
if ($count === strlen($query)) {
return $this->gets();
}
else {
throw new \Exception("Unable to execute '$cmd' command");
}
}
private function gets()
{
$result = [];
while (substr($str = fgets($this->socket), 0, 1) == '*') {
$result[] = substr($str, 0, -2);
}
$result[] = substr($str, 0, -2);
return $result;
}
}
Usage:
<?php
$imap = new ImapSocket([
'server' => 'localhost',
'port' => 143,
'login' => 'login',
'password' => 'secret',
'tls' => false,
], 'INBOX');
var_dump($imap->get_flags(0));

Categories