Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

Tuesday, March 6, 2012

Notepad++ Replace using Regex

One of the best features of Notepad++ is the search and replace. You can either use normal search, extended (so you can search for newlines (\n) and tabs (\t)), or regular expressions.

Regex is great for massaging data into the form you want to input into another program.

One case I often have is long lists of output from a PHP script using var_dump() which I want to paste into an Excel spreadsheet. But I need to remove the preceding "string '" and the trailing "' (length=<length of string>)" for the data to make sense.

To remove the starting "string '", just use a normal search (since the string is the same on all lines). To remove the ending we need to use regex since the <length of string> value can vary, using the regular expression search \' \(length=.* should do the trick.

Tuesday, June 28, 2011

Logging in to HTTPS websites using PHP cURL

To log in to a HTTPS website using PHP cURL you need to do the following:

enable cURL by uncommenting the line extension=php_curl.dll in your php.ini file.

Set up cURL to either accept all certificates or add the needed certificate authority to cURLs CA list (check out http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/)

Then you need to load the page to get the session cookie:
// Create temp file to store cookies
$ckfile = tempnam ("/tmp", "CURLCOOKIE");

// URL to login page
$url = "https://www.securesiteexample.com";

// Get Login page and its cookies and save cookies in the temp file
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); // Stores cookies in the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);


Now you have the cookie, you can POST login values (check the source of the login page to check if you need any other fields too)
$fields = array(
'username' => 'yourusername',
'password' => 'yourpassword',
);
$fields_string = '';
foreach($fields as $key=>$value) {
$fields_string .= $key . '=' . $value . '&';
}
rtrim($fields_string, '&');

// Post login form and follow redirects
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); //Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Tells cURL to follow redirects
$output = curl_exec($ch);


Now you should be able to access any pages within the password-restricted area by just including the cookies for each call:

$url = "https://www.securesiteexample.com/loggedinpage.html";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Accepts all CAs
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); //Uses cookies from the temp file
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);


Found from http://coderscult.com/php/php-curl/2008/05/20/php-curl-cookies-example/, http://davidwalsh.name/execute-http-post-php-curl, http://stackoverflow.com/questions/3519939/make-curl-follow-redirects, and http://www.php.net/manual/en/function.curl-setopt.php.
Also see http://php.net/manual/en/book.curl.php.

Tuesday, October 26, 2010

Check if a Zend_Db_Table_Rowset is empty

When retrieving data from the database using Zend Framework (using find or fetchAll functions) you will be presented with a Zend_Db_Table_Rowset. To check if it is empty it would seem logical to use the empty function like when checking an array. This will not work.

To check if a Zend Rowset (Zend_Db_Table_Rowset) is empty you need to use the count function. e.g.:
if(count($result) > 0) {
//Do something
}

Or using the Rowsets own count function (which does not iterate through all the elements apparently):
if($result->count() > 0) {
//Do something
}


See http://www.mail-archive.com/fw-general@lists.zend.com/msg25411.html for a discussion on the topic.

Friday, July 16, 2010

Alternative to Eclipse IDE

So, getting tired of eclipse's infinite number of program/system halting tasks?

Maybe you should try Netbeans, it's not just for Java development. There are also plugins for PHP, Ruby, C/C++, and Groovy (whatever that is).

Check it out at:
http://netbeans.org/

Wednesday, May 5, 2010

Postscript delegate failed for ImageMagick PHP library

For ImageMagick in PHP through the library Imagick the following error may occur for versions ImageMagick-6.3.5 to ImageMagick-6.4.2:
Postscript delegate failed `': No such file or directory

This is a bug and the error appears when one is trying to use the readimageblob function to read a PDF file.

The fix has been posted and the bug is no longer present. See http://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=11989. So to fix it get the latest release from http://www.imagemagick.org/.

Some installations (like server environments), haven't got the latest version and cannot install it. For these, it is possible to work around this bug, by using a temp file.

So instead of:
$im = new Imagick();
$im->readimageblob($data);


Use:
$im = new Imagick();
$temp = tmpfile();
fwrite($temp, $data);
fseek($temp, 0);
$im->readimagefile($temp);
fclose($temp);


(This would typically be followed by for example:
$im->setImageFormat("png");
$data = $im->getimageblob();
)

Sources: http://markmail.org/message/6mg3lxi26gd5fluv#query:readimageblob%20Postscript%20delegate%20failed+page:1+mid:6mg3lxi26gd5fluv+state:results

If this doesn't fix it for you, also check out: http://stackoverflow.com/questions/588918/imagemagick-imagick-convert-pdf-to-jpg-using-native-php-api

Tuesday, April 6, 2010

Imagemagick reading pdfs under Apache and Windows

Getting "Apache HTTP Server has stopped working" when trying to read a pdf file using the PHP imagick class when running Apache?:

If
<?php
$im = new imagick('file.pdf[0]');
?>

breaks your server. Try installing the latest Ghostscript windows binaries: http://pages.cs.wisc.edu/~ghost/

You should also have gotten an error if you tried to convert the pdf in commandline:
Unrecoverable error: undefinedresource in setcolorspace
Operand stack:
--nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- DefaultGray ColorSpace
START 0 2568152 1228867 1461800 167944 true 1134 5 <9>
END PROCS 6 2568152 1240166 1461800 169328 true 1133 5 <9>
gs_std_e.ps 13 2588248 1246221 1461800 170712 true 1133 5 <12>
gs_il1_e.ps 20 2588248 1248404 1461800 170712 true 1133 5 <15>
END FONTDIR/ENCS 25 2588248 1248582 1461800 170712 true 1133 5 <21>
END DEVS 31 2591744 1255606 1461800 170712 true 1133 5 <21>
END STATD 37 2591744 1262786 1461800 172336 true 1133 5 <45>
END GS_FONTS 44 2631936 1293632 1461800 172336 true 1134 5 <51>
END BASIC COLOR 50 2631936 1300193 1461800 172336 true 1132 5 <54>
END LEVEL 1 COLOR 55 2631936 1301921 1461800 172336 true 1132 5 <57>
END IMAGE 61 2652032 1308551 1461800 172336 true 1132 5 <60>
gs_btokn.ps 67 2652032 1311993 1461800 172336 true 991 4 <63>
gs_dps1.ps 73 2652032 1313338 1461800 172336 true 991 4 <63>
gs_dps2.ps 78 2652032 1315345 1461800 172336 true 991 4 <63>
gs_type1.ps 84 2652032 1316871 1461800 172336 true 991 4 <63>
gs_lev2.ps 93 2672128 1334882 1508160 219096 true 991 4 <63>
BEGIN RESOURCES 96 2672128 1337010 1508160 219096 true 991 5 <64>
END CATEGORY 100 2672128 1338270 1508160 219256 true 991 6 <64>
While reading gs_patrn.ps:
%%[ Error: typecheck; OffendingCommand: get ]%%
START 297633 2756688 1417603 1508160 221464 true 995 6 <67>
END PROCS 297638 2756688 1428886 1508160 222848 true 993 6 <67>
gs_std_e.ps 297645 2776784 1434941 1508160 224232 true 993 6 <70>
gs_il1_e.ps 297649 2776784 1437124 1508160 224232 true 993 6 <73>
END FONTDIR/ENCS 297653 2776784 1437302 1508160 224232 true 993 6 <79>
END DEVS 297657 2780280 1444326 1508160 224232 true 993 6 <79>
END STATD 297662 2800376 1454858 1508160 225856 true 993 6 <103>
END GS_FONTS 297667 2820472 1482354 1508160 225856 true 993 6 <109>
END BASIC COLOR 297672 2820472 1488915 1508160 225856 true 991 6 <112>
END LEVEL 1 COLOR 297677 2840568 1493995 1508160 225856 true 991 6 <115>
END IMAGE 297683 2840568 1497297 1508160 225856 true 991 6 <118>
gs_btokn.ps 297689 2840568 1500739 1508160 225856 true 991 6 <121>
gs_dps1.ps 297694 2840568 1502084 1508160 225856 true 991 6 <121>
gs_dps2.ps 297700 2840568 1504091 1508160 225856 true 991 6 <121>
gs_type1.ps 297705 2840568 1505617 1508160 225856 true 991 6 <121>

Friday, March 26, 2010

Custom message for Zend CSRF token

Ever see the following message when using Zends CSRF token?:

The token 'cea65eff4f464dsl57729a21fbd56aea' does not match the given token 'd2479b415baafe5791ase68f85122828a'

Wouldn't it be more useful to have an intelligible message? To set custom messages for the Zend_Form_Element_Hash do the following:

$this->addElement('hash', 'csrf_token', array(
'salt' => get_class($this) . '',
'timeout' => ,
'errorMessages' => array('Identical' => 'Form has timed out (probably), or you are attempting a cross-site request forgery. Please submit form again.'),
));


'Identical' is the validator that Zend_Form_Element_Hash uses. So adding the errorMessages line when creating the hash should do the trick.

There is probably a setErrorMessages() method also, but I haven't tried this.

Thursday, February 11, 2010

Zend PHPUnit check elements set by controller

When testing output from controllers in Zend using the Zend PHPUnit one might want to check the elements set by the controller, if they have the right values or exist at all.

Anything below top level form ($this->view->form = $form; in controller) one needs to use the getElement() function like one would in the controller. getSubForm() is also valid if there are subforms:

public function testRegisterViewObjectContainsProperties() {
$controller = new RegistrationController(
$this->request,
$this->response,
$this->request->getParams()
);
$controller->registerAction();

$this->assertTrue(isset($controller->view->form));

$this->assertTrue(isset($controller->view));
$this->assertTrue(isset($controller->view->form));
$username = $controller->view->form->getSubForm('userpass')->getElement('username');


http://www.contentwithstyle.co.uk/content/unit-testing-controllers-with-zend-framework seems to be useful.

Zend PHPUnit posting to controller

Sending data to the controller to check what you get back can be tricky. Especially if you have subforms or file uploads.

Here is how if you have subforms (in this case a select and a multiselect in separate subforms):
public function testPostMissingFilledFields() {
$this ->request ->setMethod('POST')
->setPost(array(
//Selected element with value '2'
'firstLayerSubform1' =>
array('secondLayerSubform1' =>
array('thirdLayerSubform1' =>
array('select' => array('2')))),
//Selected elements with values 1159 and 1161
'firstLayerSubform2' =>
array('secondLayerSubform2' =>
array('thirdLayerSubform2' =>
array('multiselect' => array('1159', '1161')))),
));


Useful functions to see what you submit look like are:
In Test file:
var_dump($this->request->getParams());
In controller:
var_dump($this->_request->getParams());

If you find a way to check for uploaded files please tell me. :)

PHPUnit with Zend View

When you want to check if important objects in Zend Views show up using PHPUnit testing can be used. In my case I have a registration form which repopulated the fields if one was missing or if anything was incorrectly filled in.

There seem to be multiple ways to select elements in the DOM:
- assertQuery - CSS selector
- assertXpath - Xpath selector
- strpos (!) - search through the html as a string

I first tried CSS selector:
$this->assertQuery('input[id="username"][value="test1"]'); //username
$this->assertQuery('input#username[value="test1"]'); //username
$this->assertQuery("input[value='test@asdf.com']"); //emailaddress


All should work, but there are different problems. The two first selections don't work, event though they work in firebug. The last line doesnt work either because of the period '.' which gives a "DOMXPath::query(): Invalid predicate" error.
Seems Zend PHPUnit converts from CSS to Xpath selectors and doesnt manage to do it right.

Therefore using Xpath directly is better. (Download the FireXpath extension to Firebug for Firefox and play around to learn it (also http://www.w3schools.com/XPath/default.asp is good)). So here's Xpath:
$this->assertXpath("//input[@id='username'][@value='test1']"); //username
$this->assertXpath("//input[@id='emailaddress'][@value='test@asdf.com']"); //emailaddress

Works out of the box.

Alternatively you can search through the html code linearly:
$this->assertTrue(strpos($this->_response->getBody(), 'test@asdf.com') !== false); //emailaddress
However, if anything changes in the html code, the test might fail.

Solution sources: http://framework.zend.com/manual/en/zend.test.phpunit.html, http://www.tig12.net/downloads/apidocs/zf/, others I cant remember.

Friday, February 5, 2010

Atomic transactions in Zend

If you have many database changes where all need to succeed or none at all do the following:

//Get a hold of the database adapter:
$model = new Model_DbTable_();
$adapter = $model->getAdapter();
$adapter->beginTransaction();
try {
//Do inserts, updates, deletes etc.
//Commit the changes and do rollback if it fails:
$adapter->commit();
}
catch (Exception $e) {
$user->getAdapter()->rollback();
//Print errors
$echo $e->getMessage();
}


or similarly:

$db->beginTransaction();
try {
$db->insert('server', array('key' => 'foo', 'value' => 'bar'));
$db->insert('server', array('key' => 'bar', 'value' => 'baz'));
$db->insert('server', array('key' => 'baz', 'value' => 'foo'));

$db->commit();
}
catch (Exception $e) {
$db->rollback();
$e->getMessage();
}


Solution found: http://devzone.zend.com/article/1367

'not found in haystack' error in Zend

If you get a '%value%' was not found in the haystack' error when using select boxes in Zend, add the following to the form element:

$element->setRegisterInArrayValidator(false);

or directly when creating form:

$form->addElement('multiselect', 'elementname', array('RegisterInArrayValidator' => false));

Solution found at: http://stackoverflow.com/questions/991001/zendvalidatebetween-strange-error-message

Wednesday, December 9, 2009

Dynamically add POST form in PHP and javascript

Sometimes you want to send data as POST to a page based on a button clicked. A possibility is to generate this form on the fly using javascript:


<html>
<body>
<script type="text/javascript">
//Create form to send values as post to the update status page.
var form = document.createElement("form");

form.setAttribute("method", "post");
form.setAttribute("action", "computationpage.php");

var hiddenField = document.createElement("input");
hiddenField.setAttribute("name", "inputValue1");
hiddenField.setAttribute("value", 999);
form.appendChild(hiddenField);

var hiddenField = document.createElement("input");
hiddenField.setAttribute("name", "inputValue2");
hiddenField.setAttribute("value", "this is a string");
form.appendChild(hiddenField);

//Create hidden div to contain the form.
var div = document.createElement("div");
div.setAttribute("style", "visibility:hidden");
div.appendChild(form);
document.body.appendChild(div);

form.submit()
</script>
</body>
</html>


This code would when call, create a form, add it to a hidden div at the bottom of the page and submit the form.

EDIT: added HTML, BODY, and SCRIPT tags. This is all that should be needed for this script to work standalone (its not valid XHTML 1.0 Strict though :)).

Friday, November 20, 2009

Character sets UTF-8 and ISO-8859-1 in HTML and PHP

Character sets can bring much agony to programming for the web. Here are some useful functions and ideas about handling charsets.

There are two main charsets: UTF-8(Unicode) and ISO-8859-1. UTF-8 lets one handle more characters than ISO-8859-1 (such as arabic and chinese characters).

HTML files that should handle unicode characters must have this set in the header:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>

Here one could also use 'iso-8859-1' instead.

If you need to convert between ISO-8859-1 and UTF-8 in PHP the functions utf8_encode and utf8_decode are useful. utf8_encode will convert from ISO-8859-1 to UTF-8 and utf8_decode from UTF-8 to ISO-8859-1.
The use of the functions is:
$utf8string = utf8_encode( $iso-8859-1string );
$iso-8859-1string = utf8_decode( $utf8string );


In addition to UTF-8 there are two other Unicode standards UTF-16 and UTF-32. The difference is how many bytes are used to store a character and thus how many different characters can be stored. UTF-32 is in little use, and so is UTF-16, but UTF-16 is used in more places.

To convert between these Unicode charsets use iconv. It is used like this:
$utf16string = iconv("utf-8", "utf-16", $utf8str);
or
$utf8string = iconv("utf-16", "utf-8", $utf16str);

incov can also be used to convert from other character sets such as ISO-8859-1 like this:
$utf16string = iconv("iso-8859-1", "utf-16", $iso-8859-1string);

Solutions found at: http://www.php.net/manual/en/function.utf8-decode.php, http://php.net/manual/en/function.utf8-encode.php, http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_21916597.html, and http://www.php.net/manual/en/function.iconv.php.

Monday, November 2, 2009

Time functions in PHP

Getting time in the right format can be a challenge. The default format is unix timestamp (a number giving the number of seconds since January 1 1970 00:00:00 UTC). However one often want to extract the date in a certain format for display purposes or for use in databases.

There are some functions that are useful for doing this. They are date(),strtotime(), mktime().

mktime will return the unix timestamp from the arguments passed into it, e.g. one can give it minutes, hours, days,months, years:
mktime(0,0,0,3,20,2004) which is "20/03/2004 00:00:00" will be 1079737200.

date will return a string formatted according to the given format. Several arguments can be given, including "Y" for 2009 while "y" gives 09 etc. Examples:
$today = date("F j, Y, g:i a"); // March 10, 2001, 5:16 pm
$today = date("m.d.y"); // 03.10.01
$today = date("j, n, Y"); // 10, 3, 2001
$today = date("Ymd"); // 20010310

Or
date("d, m, Y", mktime(0,0,0,3,20,2004)) // 20, 03, 2004
date("d, m, Y", strtotime("now")) // 03, 11, 2009 )

Or
currentWeek = date("W", strtotime("now")) //45 for 03.11.2009

strtotime will take a string and try to convert it into a unix timestamp. An example is "now" which will give the time right now in unix timestamp. Other examples are strtotime("10 September 2000") and strtotime("+1 day").


Sources: http://php.net/manual/en/function.date.php, http://php.net/manual/en/function.strtotime.php, http://php.net/manual/en/function.mktime.php