Error in PHP Generator - php

What is the best way to inform who use my generator function if something errors occurs, instead of writing weird return or raising exception like this piece of code
function csv_file_generator($csvFilename, $delimiter = ";", $enclousure = '"') {
if(($csvHandler = fopen($csvFilename, 'rb')) === false) {
return;
}
while (($row = fgetcsv($csvHandler, 0, $delimiter, $enclousure)) !== false) {
yield $row;
}
if (feof($csvHandler) === false) {
return;
}
if (fclose($csvHandler) === false) {
return;
}
return; /* Exit Generator */
}

<?php
class CsvFileGenerator {
protected $fp;
protected $delimiter;
protected $enclousure;
public function __construct($filename, $delimiter = ";", $enclousure = '"'){
$this->delimiter=$delimiter;
$this->enclousure=$enclousure;
if(!file_exists($filename)){
throw new Exception("file [$filename] dont exists");
}
if(!is_readable($filename)){
throw new Exception("file [$filename] is not readable");
}
$this->fp = fopen($filename, 'rb');
if($this->fp === false){
throw new Exception("cant open [$filename]");
}
}
public function getGenerator(){
while (($row = fgetcsv($this->fp, 0, $this->delimiter, $this->enclousure)) !== false) {
yield $row;
}
}
public function __destruct() {
if($this->fp){
fclose($this->fp);
}
}
}
foreach( (new CsvFileGenerator('mycsvfile.csv'))->getGenerator() as $line){
#do some
}
One way to rome. :-)

How about callbacks?
function gen($i, $on_close = null, $on_error = null) {
while ($i--) {
yield $i;
if ($i === 5 && is_callable($on_close)) {
$on_close();
}
}
}
$closed = false;
$gen = gen(10, function () use (&$closed) {
$closed = true;
});
foreach ($gen as $x) {
if ($closed) {
break;
}
echo $x, PHP_EOL;
}
I'll admit its not pretty. Another options could be to return instances of special classes to let your main code know something is wrong.

Related

can i use || and && together?

im trying to open a log file and see if a text does not exist, if it doesnt exist then continue, but at the same time i want to check its the log file has not been sent per mail already.
public function start() {
$pattern = $this->config["twp_pattern"] ?? '*.log';
$pathLog = (isset($this->config["twp_path"])) ? trim($this->config["twp_path"], '/') : 'var/log';
$lastRun = (isset($this->config['twp_last_run'])) ? str_replace('T', ' ', $this->config['twp_last_run']) : false;
$path = getcwd() . '/' . $pathLog . '/' . $pattern;
$this->now = new \DateTime();
foreach (glob($path) as $log) {
$open = fopen($log, 'r') or die ('File opening failed');
$content = fread($open,filesize($log));
var_dump($content);
fclose($log);
if (!$lastRun || filectime($log) < strtotime($lastRun) && $this->checkIfAlreadyExists($content) === false) {
continue;
}
$logs[] = $log;
}
if (!empty($logs)) {
$success =$this->sendMail($logs);
}
if($success === false){
return false;
}
$this->setLastRun();
return true;
}
public function checkIfAlreadyExists($content){
if (!preg_match_all('/already exists/', $content)) {
echo "is not there";
return false;
}else{
echo "is there";
return true;
}
}
my problem is even tho email has been sent, it will send it again when i run
function start()
if i remove the && $this->checkIfAlreadyExists($content) === false, it will not longer send logs per mail that has already been sent. can anyone spot my mistake ? Thanks
Fixed by changing my if statement
if ((!$lastRun || filectime($log) < strtotime($lastRun)) || ($this->checkIfAlreadyExists($content))) {
continue;
}
Thanks for your time and the help ! <3

Upload Image PHP rename file

I am very much a beginner when it comes to PHP, however, I seemed to have my image uploader working the way I want to with the following code (sourced online). The only issue is I need to rename the files when the user uploads them to something unique like the user/date. I cannot seem to get it working when I alter this code.
I have spent some time searching here and the internet in general but I have struggled to find something that fits.
Please could someone offer me a fix or direct me in the right direction.
Thank You Stack Overflow,
class Uploader {
private $files = array();
private $extensions = array();
private $errors = array();
private $store_directory = "./attachment";
private $resize_image_library_instance = null;
public function __construct($files) {
if (is_array($files) === false) {
$files[] = $files;
}
$this->files = $files;
}
public function set_upload_to($store_directory) {
$this->store_directory = $store_directory;
}
public function set_valid_extensions($extensions, $case_sensitive = false) {
$this->extensions = $extensions;
$this->case_sensitive = $case_sensitive;
}
public function set_resize_image_library($resize_image_library_instance) {
$this->resize_image_library_instance = $resize_image_library_instance;
}
public function is_valid_extension() {
$total = count($this->files);
for($i=0; $i<$total; $i++) {
if (empty($this->files['name'][$i]) === false) {
$file_extension = $this->get_extension($this->files['name'][$i]);
if (in_array($file_extension, $this->extensions) === false) {
$this->errors['type'] = "extension";
$this->errors['file_name'] = $this->files['name'][$i];
$this->errors['file_extension'] = $file_extension;
return false;
}
}
}
return true;
}
public function run() {
$total = count($this->files);
for($i=0; $i<$total; $i++) {
if (empty($this->files['name'][$i]) === false) {
if (move_uploaded_file($this->files['tmp_name'][$i], $this->store_directory.'/'.$this->files['name'][$i]) == false) {
$this->errors['type'] = "run";
$this->errors['file_name'] = $this->files['name'][$i];
}
}
}
return empty($this->errors);
}
public function resize($scale_size = 200) {
$total = count($this->files);
for($i=0; $i<$total; $i++) {
$image = realpath($this->store_directory.'/'.$this->files['name'][$i]);
if (file_exists($image) === true && is_file($image) === true) {
$this->resize_image_library_instance->init($image);
$this->resize_image_library_instance->scale($scale_size);
if ($this->resize_image_library_instance->save($image) === false) {
$this->errors['type'] = "resize";
$this->errors['file_name'] = $image;
}
}
}
return empty($this->errors);
}
public function get_errors() {
return $this->errors;
}
//
private function get_extension($filename) {
$info = pathinfo($filename);
return $info['extension'];
}
private function get_filename($file) {
$info = pathinfo($file);
return $info['filename'];
}
}
To generate an unique name for the uploaded file and save it to server you can use the time(), mt_rand() and then the uploaded file's name together. Like this..
public static function generateUniqueFileName($fileName)
{
return time() . mt_rand(100, 100000) . $fileName;
}
And if you want to pre-pend the username as well then you can pass it to the method and concat it in the beginning.

Is there a way to tell if a user uploaded file is a server script?

I'm writing some server side scripts for my web host that will do a whole bunch of auto updating for client side applications. As long as the user has properly identified themselves as the owner with the app name and password they should be able to upload to a repository on the server created automatically; however, I don't want to allow any scripts to be uploaded such that it could run on the server. I intend to allow people to create their own repositories without having to ask me so is there anyway to block this potential vulnerability?
This is the setup code for the repositories, named APPSEtUP.php :
<?php
$app = str_replace("_", " ", TDecode($_POST['app']));
$pass = str_replace("_", " ", TDecode($_POST['pass']));
$command = str_replace("_", " ", TDecode($_POST['command']));
$worked = false;
if ($command == "SETUP_API") { $worked = SETUP_API($app, $pass); }
if ($command == "MAKE_DIR") { $worked = Make_Directory($app, $pass, TDecode($_POST['DIR']), TDecode($_POST['up'])); }
if ($worked) { echo "SUCCESS!"; }
return;
function Make_Directory($api, $pw, $dir, $up) {
$path = $_SERVER['REQUEST_URI'];
if ($path == "/scripts/APPSETUP.php") { echo "API FAILURE: 008\r\n"; return false; }
if (!startsWith($path, "/scripts/Apps/")) { echo "API FAILURE: 009\r\n"; return false; }
if (!Get_API_PW("./security.LOCK", $pass)) { echo "API FAILURE: 010\r\n"; return false; }
if ($path != "/scripts/Apps/".$api."/APPSETUP.php") { echo "API FAILURE: 011\r\n"; return false; }
while (startsWith($dir, ".") || startsWith($dir, "/")) { $dir = substr($dir, -(strlen($dir)-1)); }
while (endsWith($dir, "/")) { $dir = substr($dir, 0, strlen($dir)-1); }
if (!(file_exists("./".$dir."/") || mkdir("./".$dir."/", "0777", true))) { echo "API FAILURE: 012\r\n"; return false; }
if ($up == "true" && !(file_exists("./".$dir."/UploadFile.php") || copy("./UploadFile.php", "./".$dir."/UploadFile.php"))) {
echo "API FAILURE: 013\r\n"; return false;
} return true;
}
function startsWith($haystack, $needle) {
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
function endsWith($haystack, $needle) {
$length = strlen($needle);
return $length === 0 || (substr($haystack, -$length) === $needle);
}
function SETUP_API($api, $pw) {
$temp1 = "./Templates/USERLOG.php";
$temp2 = "./Templates/UploadFile.php";
$temp3 = "./APPSETUP.php";
$dest1 = "./Apps/";
$dest2 = "./Apps/".$api."/";
$dest3 = "./Apps/".$api."/USERLOG.php";
$dest4 = "./Apps/".$api."/security.LOCK";
$dest5 = "./Apps/".$api."/UploadFIle.php";
$dest6 = "./Apps/".$api."/APPSETUP.php";
if (!(file_exists($dest1) || mkdir($dest1, 0777, true))) { echo "API FAILURE: 001\r\n"; return false; }
if (!(file_exists($dest2) || mkdir($dest2, 0777, true))) { echo "API FAILURE: 002\r\n"; return false; }
if (!file_exists($dest4)) { if (!App_Reset($dest2, $dest4, $pw)) { echo "API FAILURE: 003\r\n"; return false; } }
if (!Get_API_PW($dest4, $pw)) { echo "API FAILURE: 004\r\n"; return false; }
if (!copy($temp1, $dest3)) { echo "API FAILURE: 005\r\n"; return false; }
if (!copy($temp2, $dest5)) { echo "API FAILURE: 006\r\n"; return false; }
if (!copy($temp3, $dest6)) { echo "API FAILURE: 007\r\n"; return false; }
return true;
}
function App_Reset($api, $sec, $pw) {
try {
Delete_Bad_App($api);
$pWriter = fopen($sec, "w");
fwrite($pWriter, TEncode($pw));
fclose($pWriter);
return true;
} catch (exception $e) { return false; }
}
function Delete_Bad_App($api) {
$di = new RecursiveDirectoryIterator($api, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $ri as $file ) {
$file->isDir() ? rmdir($file) : unlink($file);
} return;
}
function Get_API_PW($sec, $guess) {
try {
$pReader = fopen($sec, "r");
$pw = TDecode(fread($pReader, filesize($sec)));
fclose($pReader);
return $pw == $guess;
} catch (exception $e) { return false; }
}
function TriceInt($c) {
$b = unpack("C*", $c)[1] % 255;
$foo = (string)$b;
while (strlen($foo) < 3) { $foo = "0".$foo; }
return $foo;
}
function TEncode($str) {
if (TEncoded($str)) { return $str; }
return implode(array_map("TriceInt", str_split($str, 1)));
}
function TDecode($str) {
if (!TEncoded($str)) { return $str; }
return implode(array_map("chr", array_map('intval', str_split($str, 3))));
}
function TEncoded($str) {
return (ctype_digit($str) && strlen($str) % 3 == 0);
}
?>
and here is the script that is for uploading files.
<?php
$uploads_dir = './';
if ($_FILES["file"]["error"] == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
?>
Do note that the upload script is named UploadFile.php and is located in a templates folder as referenced in the setup script.
So following the suggestions in the comments of the question I tried disabling script execution with .htaccess but because I'm using a Windows Server hosted by godaddy I was using the wrong kind of file to do so. I found this link which explained how to do the same thing in web.config which does apply to Windows servers.
http://issues.umbraco.org/issue/U4-8472
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<clear />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

Why base64_encode() return null

I have a 22M docx file and want to encode it using base64_encode() function in php. But It always returns NULL value after running this function. Is there any limit file size or condition for this function. My code:
$handle = fopen($fullpathfile, "rb");
$imagestr = base64_encode(fread($handle, filesize($fullpathfile)));
fclose($handle);
Try this code
$fh = fopen($fullpathfile, 'rb');
$cache = '';
$eof = false;
while (1) {
if (!$eof) {
if (!feof($fh)) {
$row = fgets($fh, 4096);
} else {
$row = '';
$eof = true;
}
}
if ($cache !== '')
$row = $cache.$row;
elseif ($eof)
break;
$b64 = base64_encode($row);
$put = '';
if (strlen($b64) < 76) {
if ($eof) {
$put = $b64."\n";
$cache = '';
} else {
$cache = $row;
}
} elseif (strlen($b64) > 76) {
do {
$put .= substr($b64, 0, 76)."\n";
$b64 = substr($b64, 76);
} while (strlen($b64) > 76);
$cache = base64_decode($b64);
} else {
if (!$eof && $b64{75} == '=') {
$cache = $row;
} else {
$put = $b64."\n";
$cache = '';
}
}
if ($put !== '') {
echo $put;
}
}
fclose($fh);

PHP function not returning string [duplicate]

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I have constructed a function that takes a filename, and increments a counter in the filename and returns it, however, everything is correct, except the return does not return the filename.
Any help, please?
My code:
$filename = join("", array_reverse($date));
$filename .= ".xml";
$dir = "../gigs";
$file = $dir."/".$filename;
function getNewFileName($filename, $dir) {
if (is_file("$dir/$filename")) {
if (strpos($filename, "_") === false) {
$filename = str_replace(".xml","_1.xml",$filename);
getNewFileName($filename, $dir);
}
else {
$pos = strpos($filename, "_");
$counter = (int)substr($filename, $pos+1,1);
$counter++;
$filename = substr($filename,0, $pos)."_".$counter.".xml";
getNewFileName($filename, $dir);
}
} else {
// echoing HERE shows that the string is manipulated correctly
return (string)$filename; // but returning here is not working
}
}
echo getNewFileName($filename, $dir); // <- this last line prints nothing out
Thanks in advance.
The line:
getNewFileName($filename, $dir);
needs a return:
return getNewFileName($filename, $dir);
This is what your function should look like:
function getNewFileName($filename, $dir) {
if (is_file("$dir/$filename")) {
if (strpos($filename, "_") === false) {
$filename = str_replace(".xml","_1.xml",$filename);
return getNewFileName($filename, $dir);
}
else {
$pos = strpos($filename, "_");
$counter = (int)substr($filename, $pos+1,1);
$counter++;
$filename = substr($filename,0, $pos)."_".$counter.".xml";
return getNewFileName($filename, $dir);
}
}
return (string)$filename;
}
echo getNewFileName($filename, $dir); // <- this last line prints nothing out
Firstly, please try and format your code so the indents are readable. Second, you're just not returning from recursive calls to getNewFileName():
function getNewFileName($filename, $dir) {
if (is_file("$dir/$filename")) {
if (strpos($filename, "_") === false) {
$filename = str_replace(".xml","_1.xml",$filename);
return getNewFileName($filename, $dir); // here
} else {
$pos = strpos($filename, "_");
$counter = (int)substr($filename, $pos+1,1);
$counter++;
$filename = substr($filename,0, $pos)."_".$counter.".xml";
return getNewFileName($filename, $dir); // and here
}
} else {
return (string)$filename;
}
}
assuming that's your intent.
function getNewFileName($filename, $dir) {
if (is_file("$dir/$filename")) {
if (strpos($filename, "_") === false) {
$filename = str_replace(".xml","_1.xml",$filename);
return (string)$filename;
} else {
$pos = strpos($filename, "_");
$counter = (int)substr($filename, $pos+1,1);
$counter++;
$filename = substr($filename,0, $pos)."_".$counter.".xml";
return (string)$filename;
}
} else {
return (string)$filename;
}
}
Your function had a loop to infinity.

Categories