FightSkillz.com - Life, Code, & Idiocy

Posts Tagged ‘php’

Adobe Flex/Air Bug – Serving Content via PHP

Monday, February 1st, 2010

I've been using a php script as a gateway to fetching certain content from a server, mainly mp3 files. There are a bunch of reasons for doing this, the main ones would be to be able to easily log which files are being accessed, when, and by who - and if you plan on creating widgets for your users to stream the content they upload to your site and they happen to put it on a heavily visited part of the web you can temporarily disable or limit that user's widget's access to content giving your other user's priority and preventing your server from crashing or being overworked.

So in the Flex/AIR app I've got a URLRequest that's used to load a Sound object. Instead of specifying the index.php it had been accessing http://domain.com?var1=blah&var2=blah. Usually this will redirect to the index.php sending it the post variables and letting it do it's thing and fetch the mp3. It works on Adobe AIR for Mac, it works in a browser on Mac/Windows. But in a URLRequest from Windows it doesn't work, confirmed for XP and 7. It doesn't just redirect to the /index.php file and drop the POST/GET variables, it actually just doesn't redirect anywhere, and you get an IOError. You'd think the redirect would be handled entirely by the server and transparent to the client, but it appears that for whatever reason, Adobe AIR on Windows just returns an IO Error.

Either way it's easy to fix, you just have to specify the index file in your URLRequest like so: http://domain.com/index.php?var1=blah&var2=blah.

Running Commands as Root from PHP

Sunday, January 24th, 2010

Sometimes you need to automate some terminal commands within your web application. I personally prefer PHP over other server side languages, and in this case its ability to run such commands are fantastinominal. There are a bunch of built in functions for securing/escaping arguments and commands, and a bunch of methods for executing shell commands. The main differences between them are the way output is returned to php. For most cases you should be fine using escapeshellarg() and shell_exec() methods - assuming you're using variables posted to your server code as arguments. You should read up on the various program execution methods over at php.net, and research all the implications and security risks involved in using them.

This post doesn't focus on their use, but instead on how to give Apache(or whatever web server you're using) root access on your server. In fact what you need to do in order to simplify your scripts is allow the Apache process to run root commands without a password. That's RIGHT, without a password. This can be exceptionally dangerous so you may want to limit this root access specifically the no-password-necessary root access only to specific programs you need to run from your scripts. Otherwise a small programming error would let malicious people take full control of your web server with ease.

The main purpose of enabling no password root access here is so you can easily run programs with a single command and not worry about being challenged for a password or having to deal with that in your server code. It's potentially more dangerous to store your root password in a public facing script than giving it no-password-root-access to a single program. A fair amount of web software and tools will have versions of their commands that can be run on a single line for this purpose.

This is for Ubuntu, but should work on most other distros with little tweaking.

First add the following line to your php script:

echo shell_exec("whoami");

This will output the user that Apache, or whatever server is running your php file, is running as on the system. Typically Apache runs as www-data, but your system may be set up differently.

Now open a terminal and ssh into your web server. Run the following command:

sudo visudo

What this does is edit the /etc/sudoers file, however using the visudo command is necessary for changes to properly take effect. Go to the bottom and add the following line to enable the Apache user to sudo without a password:

www-data ALL=NOPASSWD: ALL

The first ALL refers to hosts, the second ALL refers to programs/commands. If you only want to grant Apache sudo access to a specific program replace the second ALL with the full path to the command file. So even though you will be able to call last from your script without worrying about the path, you need to know the actual path here:

www-data ALL=NOPASSWD: /usr/bin/last

Now you should have a list of shortcuts at the bottom of the terminal, you want to "WriteOut"(ctrl+o) the file which is the same as saving it, you'll be prompted to choose the path to save to, make sure that you're saving it as /etc/sudoers, otherwise it may try save your changes as a copy.

You can now try run last from your php script by adding the following to your php script:

echo shell_exec("sudo last");

Now that it works you may want to remove the echo lines from your script, or test it with a different command since showing the world who's actually running Apache or the output of last is not something you want.

Let Postfix send mail through your Gmail Account – Snow Leopard

Monday, October 12th, 2009

First of all GRRRRRR!!

Second, this has been one of those things I randomly get sucked into between projects where I'll spend 5 hours on Google trying to figure it out and getting tiny fragments of info but never actually solving the issue. This is the worst! What the hell am I talking about? Say you use MAMP or whatever as a local testing server. You write some PHP and you need to use the mail() function. You test your new email function to your personal gmail account. Ok so you try it and it doesn't work, or even worse it works a couple times and then never again.  So you go to Applications->Utilities and fire up the Console application. You're shocked to see that there's a message in there saying something about Gmail not accepting mail from your IP address because it's registered as a residential thingy and apparently a lot of spammers use their personal computers to send spam.

So you say no no there must be some mistake I'm a programmer, not a spammer, I'm just trying to test out my new app. But you quickly realize you're talking to a computer, pleading, and well it doesn't care. typical. After, you cry and try piece together a coherent step by step set of instructions to route all mail sent from your computer through your Gmail account - so it would be from you, and all go through. here's what you do.

note that $ is used to show a new terminal command, you don't actually type it in:

Open Terminal - found in Applications->Utilities and type in:

$ sudo nano /etc/postfix/relay_password

You'll now be editing a new file called relay_password in the nano Terminal editor, type in the following substituting your login info - it should work with google apps accounts as well:

smtp.gmail.com example@yourdomain.com:yourpassword

Press ctrl+o on your keyboard followed by Enter to save the file, then press ctrl+x to exit the editor.

Now type in:

$ sudo postmap /etc/postfix/relay_password

That should tell Postfix to use the relay file you just created. Gmail uses a secure connection so you need to head over to Verisign and download some root certificates. Go to the following url fill out your info and download the .zip file:

https://www.verisign.com/support/roots.html.

Now type in the following commands one after another. In the second command it wants the roots.zip you just downloaded, you can just drag the zip file onto the Terminal window and it will fill in it's location, don't do that for the 4th command though. Also note you may have some certificates already on your system, so after the second last command you may be prompted to replace existing certificates, type N so it doesn't replace the ones you have:

$ sudo mkdir /etc/postfix/certs
$ sudo cp roots.zip /etc/postfix/certs
$ cd /etc/postfix/certs/
$ sudo unzip -j roots.zip
$ sudo openssl x509 -inform der -in thawte\ Primary\ Root\ CA\ -\ G2_ECC.cer -out thawte\ Primary\ Root\ CA\ -\ G2_ECC.pem
$ sudo c_rehash /etc/postfix/certs

Now type in:

$ sudo nano /etc/postfix/main.cf

Go to the end of the document, you can delete the MAMP stuff, also note that if you have MAMP Pro and you edit postfix settings from there it'll fuck up what we're doing here. So remember this going into the future and don't do that.

Paste in the following at the end of the document - note: use the keyboard to get around the document, but use the mouse to right click and paste:

relayhost = smtp.gmail.com:587
# auth
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/relay_password
smtp_sasl_security_options = noanonymous

# tls
smtp_tls_security_level = may
smtp_tls_CApath = /etc/postfix/certs
smtp_tls_session_cache_database = btree:/etc/postfix/smtp_scache
smtp_tls_session_cache_timeout = 3600s
smtp_tls_loglevel = 1
tls_random_source = dev:/dev/urandom

Save it like we did before by pressing ctrl+o, then Enter, then ctrl+x.

Now type in:

$ sudo nano /etc/postfix/master.cf

You're now editing master.cf, this is a different file to main.cf we just pasted stuff into. There should be a table in here, find the line in the table that looks something like this:

#tlsmgr    fifo  -       -       n       -       1       tlsmgr

Make it look like this - note the comment is removed and fifo should be unix:

tlsmgr    unix  -       -       n       -       1       tlsmgr

Save it like the other times pressing ctrl+o, then Enter, then ctrl+x.

Ok, so at this point you can put the following into terminal and see that it works - put your email address in there twice:

printf "Subject: blah" | sendmail -f user@gmail.com user@gmail.com

Postfix is working now. good. You go back to your PHP application and test the mail() function again. If it works then you're done, but if not you panic. You start feeling really hungry. You know that Postfix is working but maybe PHP or Apache haven't gotten the message yet. ok. So you see in Console that sendmail is crashing, you open the crash report in Terminal and it tells you there's an incompatible version of libxml. It wants 10 and you have 9. You begin questioning if any of this is worth it and maybe you should just go sit in front of a tv and forget about doing anything meaningful with the rest of your life.

After almost installing XCode and registering as an apple developer so you can make and install the newest version of libxml, you wonder if maybe MAMP comes with libxml and find that yes it does. So instead of spending 2 hours upgrading the system libxml only to find it doesn't do anything you just upgrade to the latest version of MAMP (1.8 at the time of writing) and it works. What?? it works? really? yup. so what do you do now?

REJOICE! with lunch.

Some of this was scoured from random forums and blogs in the midst of complete frustration and combined into steps that actually work. A chunk however was taken from this post: http://dejan.ranisavljevic.com/2009/05/28/enable-postfix-with-relay-outbound-to-your-gmail-account-on-os-x-leopard/ so check them out.

Passing a Multi-dimensional Array Between Javascript And Php.

Thursday, August 21st, 2008
Passing data between client and server is pretty straight forward, we use HTML structured forms and AJAX calls to put data up, and echo/print methods to bring it down. The data types transmitted are usually strings and numbers. Unfortunately Javascript and Php don't have built in conventions for you to pass arrays or objects between one another. This article shows you how to pass an array from server to client, and then from client to server. Looking around Google there are a number of other developers who've found ways to do this, but the methods they use tend to limit the number of tiers in the array being passed from client to server, use up unwarranted resources for multiple form items and variables to hold each array item, and limit your overall control of the task. This method focuses on getting your data from an array to a string and back again using 1 hidden input, 1 variable, and allows you to have as many tiers to your array as you have characters to use as delimiters. Passing an array from Php to Javascript is quite simple, because our array starts in Php, and Php is parsed first by the server. The whole process can be done in one block of code. Loop through the array in Php echoing it into Javascript code, which when parsed by the clients browser will generate a Javascript array. Say we have a Php array:
 array("model" => "Prophecy Les Paul Ex", "neck" => "Mahogany"),
     "Fender" => array("model" => "Lite Ash Telecaster", "neck" => "Birdseye Maple" ),
     "Washburn" => array("model" => "Idol WI15", "neck" => "Rosewood")
     );
?>


On the page to be served add the following Php which will loop through the array generating the Javascript code to re-create the array on the client-side. You may also want to wrap the generated Javascript in a function if you don't want the array to be generated on page load, or want to be able to refresh/reset the array:
 
var Guitars = new Array();
 


That's it. 

Now if you want to pass the array back from Javascript to Php it's a bit more complex. We'll use the Javascript array Guitars that we just created. First we'll need an HTML form:
<form method="post" action="/example.php">
 
 
</form>
Note the use of both id and name. Name will be assigned to the posted variables we'll need to pick up on the server, as for referring to the input in Javascript you could use the getElementByName(); but I find it to be less reliable and harder to keep track of which elements have a name and which have an id. Using id throughout your application is more uniform. Anyway remember we still have the array Guitars from before, now we need to write the function called by the Submit button:
 
function fn_SubmitForm() {
     arr_Guitars = document.getElementById('arr_Guitars'); //get the element
     arr_Guitars.value = ""; //make sure the value is empty in case the user double clicked
     //loop through the array Guitars concatenating the values into a formatted string
     for(var i in Guitars) {
          arr_Guitars.value += Guitars[i]['model'] + ':' + Guitars[i]['neck'];
          /*
          //Nest this for(){} loop within itself for every tier of your array
          //for each nesting move the delimiters over, if you used a ; next, the
          //nested loop would look like the following:
          for(var ii in Guitars[i]['avail_colours']) {
          arr_Guitars.value += Guitars[i]['avail_colours'][ii]['colour'] + ';';
          }
 
          //to add more array items to this Guitar[i] replace the last delimiter of
          //the output of the last nested loop with that of the tier above it
          arr_Guitars.value = arr_Guitars.value.replace(/;$/,":");
          //or if you're finished with this Guitar[i] remove it
          arr_Guitars.value = arr_Guitars.value.repalce(/;$/,"");
          */
 
          arr_Guitars.value += ',';
          //the preceding line could be added to the end of the first line of the
          //loop if you're only passing a two tiered array
     }
     //remove the last , from the formatted string
     arr_Guitars.value = arr_Guitars.value.replace(/,$/,"");
 
     document.form_Decision.submit();  //submit the form
}
 
Note the formatted string uses the following structure model:neck,model:neck. Also for those new to regular expressions the expression used in the value.replace(); method in plain english means "the comma before the end of the string". Forward slashes mark the beginning and end of the expression, the comma represents a comma and the dollar sign represents the end of the string being analyzed.

Now on the server:
<?php
//get the formatted string
$Guitars = mysql_real_escape_string($_POST[&#039;arr_Guitars&#039;]);
//make sure the array being passed is not empty
if($Guitars != &#039;&#039;){
     //Php&#039;s explode function breaks apart the string into an array of strings based on the delimiter
     //Here we break apart the string into it&#039;s sub-strings <em>model:neck</em>
     $Guitars = explode(",", $Guitars);
 
     //for each exploded array item separate the model and neck values and elaborate the array
     foreach($Guitars as $key=>$row) {
          $row = explode(":",$row);
          $Guitars[$key] = array(
               "model" => $row[0],
               "neck" => $row[1]
               );
     }
}
?>
And that's it, you now have $Guitars again on the server. This method of passing arrays is extensible in that each level of the array can have unlimited values, and the array itself can have unlimited dimensions. For every dimension added to the array you need a new delimiter and you have to run a variation on the second foreach() statement above based on that delimiter.

xHtml, CSS, Javascript, Php, and MySql

Sunday, May 18th, 2008
Since this is my first post about computer programming I feel like I should start with the basics. There are many different combinations of servers, databases, languages and frameworks that can essentially accomplish the same thing, in sometimes different ways, usually with more or less features and benefits. Let's start with html. Html is the skeleton, it's responsible for the structure of a web page. Most programmers these days use a form of html called xhtml, which adds the clean orderly feel of xml form, it's more standards compliant and eliminates a lot of errors associated with cross-browser development. You then have css, which styles the html. css is responsible for the layout visually; presentation. These two languages are all you need to create a static page. Now when you get into sites that deliver changing content like blogs, message boards, or online stores, information needs to be dynamically pulled from a database. One of the most versatile and open source databases out there is mysql. In order to communicate with the database a language called php is used. Php is really what makes dynamic sites dynamic. An extremely versatile language used on both small scale; communicating with databases, conditional statements, variables, and functions inter-spliced into web sites, to full scale object oriented programming used in heavy online applications. Finally there's Javascript, a seriously under used and overlooked language that's been around for a long time but only gained popularity in the last few years as the XMLHttpRequest began receiving attention. Javascript is the layer that brings a web page to life, it lets you interact with the html and css of a page without having to reload the page. Ajax, is the name given to the use of the XMLHttpRequest in javascript and it's surrounding functions and effects. It allows a user to interact with the server, like getting information from a database—usually done by communicating with external server-side php files that serve as a go between the javascript and the database, adding a refreshing level of interaction to web sites and applications. A web site is really a set of instructions. All the languages and code don't actually do anything until someone opens their browser and points to a web page thus executing the code. First the web server(where the site is stored) interprets the php—if there is any, sending the resulting html, css, and javascript to your browser which is then responsible for reading through the code and generating the web site. There are many different browsers out there, most of which generate a web page slightly differently. Due to the lack of internet language standards over the years and many items which can be interpreted in different ways, different browsers tend to implement those features in different ways. The most infamous case of this inconsistency is Internet Explorer which instead of following the standards in many cases has gone as far as to develop proprietary tags and hacks just to accommodate their blatantly incorrect interpretation of the various languages. I won't get into the shady ethics of exploiting their leading browser market share (due to being packaged and integrated with windows) to create a situation where appealing to the masses(as a programmer) means having to completely redesign a website to work with their ridiculous browser engine, but business is business. Cross platform is another issue that needs attention as operating systems come with different fonts, use different file types and plugins. These issues can break layout and make an RIA dysfunctional or not work at all. A framework is simply a library of built in functions, classes, and structures that allow a programmer access to higher level functions with far less code as well as simplifying grammar and taking care of security and cross browser compatibility. I'll go into more detail in the future.