I have a webpage where I let users to upload files to the account folder. Exactly PDF and JPG files only. I want to count the number of pages inside each PDF uploaded to show it to the users.
To do this, I was using PDFINFO linux library, part of XPDF proyect.
This is the man page of the binary file: http://linuxcommand.org/man_pages/pdfinfo1.html
You can download the .zip with the binaries there: http://www.foolabs.com/xpdf/download.html
My code (this worked perfectly, but yesterday it failed):
function getNumPagesInPDF($document){
if(!file_exists($document))return null;
$cmd = "pdfinfo";
// Open the document
exec($cmd." '".$document."'", $output);
// Browse the data
$pagecount = 0;
foreach($output as $op){
// Extrac number of pages
if(preg_match("/Pages:\s*(\d+)/i", $op, $matches) === 1){
$pagecount = intval($matches[1]);
break;
}
}
return $pagecount;
}
I can run the command in SSH, and it works in the server. Now, this code doesn't work in PHP, but nothing changed the code.
AH! a little addition: I checked exec works in my PHP using:
function exec_enabled() {
$disabled = explode(',', ini_get('disable_functions'));
return !in_array('exec', $disabled);
}
if (exec_enabled()){
echo "exec funciona";
}
Another addition: PHP didn't shows any error related with that and I have the error logging enabled to a log file (including warnings). My host recently activated mod_security.
TASK1: Try $document variable: the path is ok, relative to the place where the php code file is placed. The path exists and the file too.
TASK2: Check if $output variable has anything: NO, $output array is empty! Why? cannot understand.
TASK3: Check the $cmd." '".$document."'" : it's ok, and copied the "result" to ssh works. I'm lost.
As per the comment discussion, we've seen that running a binary using a bare filename does not always work. This is as true on the console as it is inside a system command like exec().
When you run pdfinfo in either environment, the system will search through the environment variable PATH to discover which directories to find it in. This variable is nearly always different between your user account and the Apache environment, which is why it is important to always specify the fully-qualified filename when running a binary programmatically.
As far as I know, exec() does not regard the folder containing the current PHP script as the current working directory. Even if it did, the current directory . would need to be in the Apache user's PATH in order for this to be found. Thus, I am not sure why this used to work for you, but it emphasises the importance of the above lesson: always use the full path.
You should also read the path from a settings file, rather than hardwiring it in code. This will help you as you move from local, test, staging and live environments of your app, which may store this binary in different locations.
Related
I'm having a strange problem using ftp_get() on one of the two identical instances. One is on localhost and another on an actual server. I'm using the following to download a file via FTP. Both of the instances download from the same FTP servers with the same credentials and same paths.
$result = ftp_get($connection, $downloadPath, $serverPath, FTP_BINARY);
if ($result) {
$successfulWrites[] = $downloadPath; // file name only without path
} else {
// on second attempt to download file with same name, ftp_get() returns false
// this is where I throw an exception in my code
}
On my localhost, I can download the same file over and over, and it doesn't matter what the file name on the FTP server is or where it's located.
On second instance, which is identical to the localhost's (i.e. pulled from the same git repo) in terms of code, I can download a file once, but the same file cannot be downloaded again, and ftp_get() returns false. If I change the name of the file on the FTP server, I can download it, but after that it won't work again. i.e. ftp_get() will return false.
I don't have access to the FTP server log. If it's available, I'm going to try to get it today from the host. But can anyone think of a reason this might be happening? ftp_get() just returns true or false without any explanation, so I'm pretty stuck with this.
I'm using PHP 5.4, and I have no idea what the spec is of the FTP (regular FTP) server.
As discussed, it sounded like ftp_get was successfully obtaining the file and writing it locally. I wonder whether due to a permissions problem, when it tries to write the file locally again, it fails. Thus, the FTP channel itself is fine, and the problem is just local.
I'm somewhat surprised at this though, as I would imagine PHP would have raised a warning. Is your error_reporting set to allow this whilst you are debugging?
I'm making a utility that provides a GUI to easy edit certain values in a csv file on a remote server. My boss wants the utility in php running on the private webserver. I'm new to php, but I was able to get the GUI file modifier working locally without issues. The final piece now is rather than the local test file I need to grab a copy of the requested file off of the remote server, edit it, and then replace the old file with the edited one. My issue is uploading and downloading the file.
When I searched for a solution I found the following:
(note in each of these I am just trying to move a test file)
$source = "http://<IP REMOTE SERVER>/index.html";
$dest = $_SERVER['DOCUMENT_ROOT']."index.html";
copy($source, $dest);
This solution ran into a permissions error.
$source ="http://<IP REMOTE SERVER>/index.html";
$destination = $_SERVER['DOCUMENT_ROOT']."newfile.html";
$data = file_get_contents($source);
$handle = fopen($destination, "w");
fwrite($handle, $data);
fclose($handle);
This also had a permissions error
$connection = ssh2_connect('<IP REMOTE SERVER>', 22);
ssh2_auth_password($connection, 'cahenk', '<PASSWORD>');
ssh2_scp_recv($connection, '/tmp/CHenk/CHenk.csv', 'Desktop/CHenk.csv');
This solution has the error Fatal error: Call to undefined function ssh2_connect() which I have learned is because the function is not a part of the default php installation.
In closing, is there any easy way to read/write files to the remote server through php either by changing permissions, having the php extension installed, or a different way entirely that will work. Basically I'm trying to find the solution that requires the least settings changes to the server because I am not the administrator and would have to go through a round about process of getting any changes done. If something does need to be changed instructions on doing so or a link to instructions would be greatly appreciated.
Did you set the enable-url-fopen-wrapper in your php.ini?(only if your php version is older)
Please look # php remote files storing in example 2
I have some code that copies a file to a temporary location where it is later included in a zip file.
I already have the source files stored in a local cache directory, and have also stored the SHA1 hash of the original files. The files in question are .png images, ranging from a few kb to around 500kb.
My problem is that at high server loads, the copy intermittently fails. Upon examining my logs, I see that even though a healthy file exists in the source location, the destination contains a file with zero bytes.
So, to try and figure out what was going on and to increase reliability, I implemented a SHA1 check of the destination file, so that if it fails, I can retry the copy using the shell.
99.9% of the time, the files copy with no issue. Occasionally, the first copy fails but then the second attempt succeeds. In a few number of cases (around 1 in 2,500; and always at high server load), both copies will fail. In nearly all these cases SHA1 of the destination file is da39a3ee5e6b4b0d3255bfef95601890afd80709 which is consistent with an empty file.
In all occasions, the script continues, and the created zip includes an empty image file. There is nothing in the Nginx, PHP or PHP-FPM error logs that indicates any problem. The script will copy the same file successfully when retried.
My stack is Debian Squeeze with the .deb PHP 5.4/PHP 5.4 FPM packages and Nginx 1.2.6 on an Amazon EBS backed AMI. The file system is XFS and I am not using APC or other caching. The problem is consistent and replicable at server loads >500 hits per second.
I cannot find any documentation of known issues that would explain this behaviour. Can anyone provide any insight into what may be causing this issue, or provide suggestions on how I can more reliably copy an image file to a temporary location for zipping?
For reference, here is an extract of the code used to copy / recopy the files.
$copy = copy ($cacheFile, $outputFile);
if ($copy && file_exists($outputFile) && sha1_file($outputFile) !== $storedHash) {
// Custom function to log debug messages
dbug(array($cacheFile, sha1_file($cacheFile),
$storedHash, $outputFile,
file_exists($outputFile), filesize($outputFile)),
'Corrupt Image File Copy from Cache 1 (native)');
// Try with exec
exec ("cp " . $cacheFile . " " . $outputFile);
if (file_exists($outputFile) && sha1_file($outputFile) !== $storedHash)
dbug(array($cacheFile, sha1_file($cacheFile),
$storedHash, $outputFile,
file_exists($outputFile), filesize($outputFile)),
'Corrupt Image File Copy from Cache 2 (shell exec)');
}
Objective: Use PHP to call a vbs that converts an xls/xlsx file to a csv.
Question: How can I pass a source file path and a destination file path to a vbs that converts xls/xlsx to csv and run that vbs in a PHP web application?
Details: I have a working vbs that takes a source file path and a destination file path and converts the xls/xlsx at source file path into a csv. I can execute it from the Windows cmd line and it does exactly what I want it to do. I can also put the execution command into a bat file and run the bat file to achieve the same results. However, when I use exec()/shell_exec()/system() in PHP to execute the same command no csv is created. (If I try to run the bat from PHP using system() the contents of the bat file show up on the page, in fact, echo Conversion complete! prints "echo Conversion complete! Conversion complete.") I haven't seen any errors yet.
Note: I know about PHPExcel, I'd prefer not to use it.
excelToCsv.vbs
On Error Resume Next
if WScript.Arguments.Count < 2 Then WScript.Echo "Please specify the source and the destination files. Usage: ExcelToCsv <xls/xlsx source file> <csv destination file>"
Wscript.Quit
End If
csv_format = 6
Set objFSO = CreateObject("Scripting.FileSystemObject")
src_file = objFSO.GetAbsolutePathName(Wscript.Arguments.Item(0))
dest_file = objFSO.GetAbsolutePathName(WScript.Arguments.Item(1))
Dim oExcel
Set oExcel = CreateObject("Excel.Application")
Dim oBook
Set oBook = oExcel.Workbooks.Open(src_file)
oBook.SaveAs dest_file, csv_format
oBook.Close False
oExcel.Quit
batConverter.bat
excelToCsv.vbs conversionTestSourceMS2003.xls batTest.csv
echo Conversion Complete!
index.phtml
<?php
system("cmd /c batConvert.bat")
?>
Note: All of the above files (along with conversionTestSourceMS2003.xls) are in the same directory. I have not implemented any way to pass the parameters (since I can't get it to work even if it's all hard coded...)
Set Up: PHP5, Zend Framework, WAMP, Windows 7 (localhost).
For the sake of simplicity, I merged everything into a single ASP page. This will allow me to hopefully see a similar problem in IIS, and since it is in a single ASP script, I will be able to see the error more directly. My test machine is running on Windows Vista SP2 on IIS7 with Excel 2007 SP3.
excelToCsv.asp
<%
Option Explicit
Dim csv_format, src_file, dest_file, strPath, objFSO
csv_format = 6
src_file = "conversionTestSourceMS2003.xls"
dest_file = "testbat.csv"
strPath = "[HARDCODED PATH HERE]\"
src_file = strPath & src_file
dest_file = strPath & dest_file
Dim objExcel, objBook
Set objExcel = CreateObject("Excel.Application")
Set objBook = objExcel.Workbooks.Open(src_file)
objBook.SaveAs dest_file, csv_format
objBook.Close False
Response.Write "Conversion Complete!"
objExcel.Quit
%>
When running this code, I got a generic ASP error. So, I enabled detailed error messages in ASP and I get this following error...
Microsoft Office Excel error '800a03ec'
Microsoft Office Excel cannot access the file '[HARDCODED PATH
HERE]\conversionTestSourceMS2003.xls'. There are several possible
reasons: • The file name or path does not exist. • The file is being
used by another program. • The workbook you are trying to save has the
same name as a currently open workbook.
/temp/ExcelToCsv.asp, line 18
Now, this is not Apache, but I do believe the problem is related to yours. This error implies there is a security/permission problem where Excel cannot do what it needs to do to access or read the file. In fact, I encountered similar errors when I was executing the VBScript (and passing the error up the chain) from PHP (in IIS).
I believe it can be resolved by changing the Windows User being used to create the process. This can be configured in Services.msc by editing the Apache service and changing the Log On tab to an actual Windows user instead of a Service Account. I have not tested it yet, though, since setting up Apache is not something I can do right now.
Anyone ever have this problem?
local.xml has been modified. core_config_data table has been modified for unsecure and secure url as well as cookie domain. Cache dirs have been wiped clean, session values have been cleared, log tables have been truncated.
it is under version control with subversion.
have also run find to locate where it could possibly be getting the production DB IP.
find ~/path/to/application -type f -print0 | xargs -0 grep -l "IP Of incorrect DB"
yet still throwing an error on DB
SQLSTATE[HY000] [2003] Can't connect to MySQL server on 'IP of incorrect DB' (4)
Extremely baffled and can not for the life of me locate where it would possibly be getting the production DB's IP
local.xml points to development address.
You might want to check that the magento/var/ directory, as well as all subdirectories, are writable by the web server. If those directories are not writable Magento uses /tmp/ which can cause strange effects and even conflict with other Magento sites.
Make sure you're editing the config file you think you're editing. Take a look at the following code
#File: app/code/core/Mage/Core/Model/Config.php
public function loadBase()
{
$etcDir = $this->getOptions()->getEtcDir();
$files = glob($etcDir.DS.'*.xml');
$this->loadFile(current($files));
while ($file = next($files)) {
$merge = clone $this->_prototype;
$merge->loadFile($file);
$this->extend($merge);
}
if (in_array($etcDir.DS.'local.xml', $files)) {
$this->_isLocalConfigLoaded = true;
}
return $this;
}
This is the code that merges in your local.xml file to the configuration tree. Add some debugging code
public function loadBase()
{
var_dump('Called ' . __METHOD__); //ensure we're being called
$etcDir = $this->getOptions()->getEtcDir();
$files = glob($etcDir.DS.'*.xml');
$this->loadFile(current($files));
while ($file = next($files)) {
var_dump($file); //dump the file path being loaded to the browser
$merge = clone $this->_prototype;
$merge->loadFile($file);
$this->extend($merge);
}
if (in_array($etcDir.DS.'local.xml', $files)) {
$this->_isLocalConfigLoaded = true;
}
exit; //bail out early
return $this;
}
Load your site in a browser, and observe the paths being output via var_dump. Make sure that the file(s) being loaded are the ones you think are being loaded. Keep in mind that it looks like every XML file from the etc folder is loaded and merged in.
If the paths are what you expect, next add some debugging code to output the contents of the XML file(s) being loaded.
public function loadBase()
{
var_dump('Called ' . __METHOD__ . ''); //ensure we're being called
$etcDir = $this->getOptions()->getEtcDir();
$files = glob($etcDir.DS.'*.xml');
$this->loadFile(current($files));
while ($file = next($files)) {
header('Content-Type: text/plain'); //so the browser renders it as plain text
echo file_get_contents($file); //dump the contents of the file being loaded to the browser
$merge = clone $this->_prototype;
$merge->loadFile($file);
$this->extend($merge);
}
if (in_array($etcDir.DS.'local.xml', $files)) {
$this->_isLocalConfigLoaded = true;
}
exit; //bail out early
return $this;
}
If the database information is correct in these files, then your system has been customized and/or hacked in some way that there's code calling out to another database server.
If that's the case you'll need to install something like xDebug to get some decent error reporting. This will let you find the exact code that's throwing the error, at which point you can trace it back to where it's getting it's connection information.
Good luck.
Just came across this when I had a similar issue. Followed Alan Storm's suggestion of dumping the config file names and found the problem. I had done a fresh install before copying the db and config files in from another instance, and had renamed the existing local.xml to localorig.xml. This was being loaded after local.xml and setting the db configuration fields back to the wrong values.
Moral: if you're backing up any of the config files in the same folder, change the extension.
Thanks Alan.
Try installing Alan Storm's Configviewer and check the generated XML to confirm the connection details point to the local.xml specifications. It's possible that one of the modules is using a non-default resource or some other oddity.
Can you post some of the stack trace in your question (obfuscated if you need) to show which module is calling that erroneous DB?
I had a similar problem just now. I double checked the local.xml file and that was definitely correct, however. Magento was still using an old user to access the database.
The problem was instantly resolved with: rm -rf var/cache/* - immediately this was done, the site came up.
It appears that Magento is caching the contents of local.xml in the cache area. Not so helpful.
Obviously, also recommend double checking the local.xml file but in this case it was 100% correct.
Just to try to help. Can you check your apache configuration? Something like "apache2 -S" to see which virtualhosts are used (and note especially the first default one).
You could test that all your virtualhosts (if you work with virtualhosts) are using the right documentRoot. Don't you have an other copy of the sources on your dev server?
I mean are you sure you get the right magento instance running on the url you're using on your browser? In the same way are you sure of the cache directories used on your installation - do you see any change in theses directories since the wipe out?