Saturday, December 10, 2011

Saving includes to a variable

I was reading a forum post and they wanted to save an include to a variable when making new forums on their website. I thought about it and here is what I came up with:
<?php
function get_include($path, $cat_id = null){
     ob_start(); // start buffer
     include $path;
     $content = ob_get_contents(); // assign buffer contents to variable
     ob_end_clean(); // end buffer and remove buffer contents
     return $content;
}
$render = array();
$render[] = "testing1";
$render[] = "testing2";
$category['fid'] = '134';
echo "<pre>";
$render[] = get_include('add_forum.php', $category['fid']);
$render[] = get_include('add_forum.php', $category['fid']);
print_r($render);
?>



and the forum_add.php looks like this:
<?php
echo "here is your id: $cat_id";
?>


The result looks like:
Array
(
    [0] => testing1
    [1] => testing2
    [2] => here is your id: 134
    [3] => here is your id: 134
)



Isn't this a nice way of both saving an include to a file and passing a variable to the include in a function.

Friday, November 25, 2011

Quick install LAMP server on Ubuntu

Here is the site I am going to summarize here: https://help.ubuntu.com/community/ApacheMySQLPHP
I am using Ubuntu 10.10 for this install. It should take 10 minutes or so to follow these steps.
The fastest way to install Appache2, PHP5.3, and MySQL is to use this command:
sudo tasksel install lamp-server
If you are using 11.04 then tasksel might not be installed. Then use this to install it:
sudo apt-get install tasksel
Tasksel will install the Lamp server but won't remove it, but we won't need to remove it.
At this point go to http://localhost and it should say "It works!"
Next use this command to make a new site:
sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/mysite gksudo gedit /etc/apache2/sites-available/mysite
Make a folder in your home folder called webhome or anything you want to put your website in instead of the default var/www because I like to be able to edit the website files from my home so I own them and don't have to use sudo to edit them as root. Edit the DocumentRoot line to point to your new web root: /home/user/webhome/
Change the Directory directive by fixing the path to point to your webhome folder. Instead of <Directory /var/www/> use <Directory /home/user/public_html/>
After saving the file in gedit use these commands to disable the default website and enable the new website.
sudo a2dissite default && sudo a2ensite mysite sudo /etc/init.d/apache2 restart
Next make a index.php file in the webhome folder that says:
<?php phpinfo(); ?> Now go to: http://localhost
You should see the php configuration showing all the php settings.
This was pretty easy. They have streamlined alot of these steps.

Tuesday, November 22, 2011

Idea for making midi or tracker sequencer in html

I would like to make a sequencer in html5. I think its possible and I have been researching how it can be done. The main problem will be making it work in the main browsers and not just 1 or 2. You could make tracker mod music play from firefox by installing vlc and check vlc firefox plug-in when you install it. That works and allows you to add files to the playlist using simple javascript. I made a demo which plays, stops, goes to next track and pauses the music. It works but then the next problem would be how to make the .it or .xm or .mid or .mod file on the fly using the server. Would that be done using a batch command run from php or could it be made using pure php. This would be faster than creating wave or mp3s on the fly and uploading them.
Here is a link to VLC's wiki talking about how to make the embeded object work in firefox and controlling it using js.
http://wiki.videolan.org/Documentation:WebPlugin#Playlist_object

Then I thought this was not really good either since its using old technology and when I refreshed the page it would crash the plugin too. I found a new way to run midi type files in firefox at least and maybe Chrome, Safari or Opera which use webkit.

I found this site:
http://weare.buildingsky.net/processing/audionode.js/examples/index.html
The top example works sort of:
http://weare.buildingsky.net/processing/audionode.js/examples/drum-machine.html
It uses javascript and html5's audio object to create audio from scratch like wave files.
https://wiki.mozilla.org/Audio_Data_API

You tell it what the sample rate is and then feed it all the data in an array. 44100 samples per second is the normal rate. Its the quality of CD's and it seems to work. There is a website I found which converts .midi files to wave channels on the fly in javascript on the client and plays them using firefox.
http://jsspeccy.zxdemo.org

It will take time to learn how to use this to make a cool sequencer program all on the web but it looks like it would be possible. I just need to know how to make sounds either wave files or how to make track files and then convert them to wave files to play in the browser. Its easy to make a simple sine wave but how do you introduce other sounds into the mix?

Sunday, November 6, 2011

Get amazon ASIN using javascript

I was wondering how this can be done and found a couple answers on: http://stackoverflow.com/questions/1764605/scrape-asin-from-amazon-url-using-javascript
url = window.location.href;
url.match("/([a-zA-Z0-9]{10})(?:[/?]|$)");

Monday, October 31, 2011

Hierarchy in databases for folders

I have been building a folder system that stores files and revisions to these files in the folders. I have now added deleting the folders or files by turning a column isDeleted = 1 or 0 when it is deleted so I can keep them in side until a certain time has gone by before moving them to an old table or delete them.
It was made for a comment system but I converted it to show the folder structure by building an unordered list for each root node and using lots of DIVs and spans with CSS to show the mini folders with plus and minus signs that will hide or unhide the inside list to show or hide a list of folders. This works for many levels. Then I made 2 columns on the right of the tree structure that shows 2 levels of the folders at any point. Then by clicking on any folder in the 2nd column it moves to the first column and shows the files and folders that are in it, in the second column or just a blank folder and file icon to allow you to add new folders and files. I also implemented a right click menu to add or remove files and folders. Then I made the folders and files draggable so we can move them to other folders either in the tree on the left or another folder in one of the 2 columns we navigate in. 
Now the problem I have to solve is how to keep them in order when I move a folder to another place. My folder tree walker fails to build the tree when it reads the table from top to bottom because I moved the folder above the point where the parent is so when it tries to find the parent for the child folder I moved it can't find it because the child it mentioned before the parent is listed in the database. I need to make a column that lists the tree in order from the root nodes out to the children. I have to do this because I don't want every person that views the page to have recursively find all the nodes since this won't scale well. I have to redo the order of the folders each time a new folder is added or a folder is moved. 
about a way to make adding a folder easy. It uses a lineage column that lists all the ids from the root to the present like 1-4-8 and when you add a child to 8 you will just add "-9" to the 9th folder in the system that's being placed inside the 8th folder. If I use this method then when I move a folder with many folders inside then I need to rewrite the lineage for each folder recursively using the parent of the folder it is being placed in as the base for the new location the folders are being moved to. 
Then I read this article: http://evolt.org/node/4047/
It mentions another way of fixing this by running a stored procedure when you insert a new folder where all folders after it it incremented by 1 id.
talks about other methods of working with this data. I am going to try pulling all the data out of the database using a single select and then build the tree in php and then update the sequence in the database afterward. I can do this each time a folder is moved.

Monday, October 24, 2011

Google Docs spreadsheet automatic email sending


This script sends an email using google docs spreadsheets.
Here is a script I made that sends an email to people if a cell doesn't say email sent. It uses cells that exist to put together the body and subject of the email. You can do alot more with this but its good enough to work.


function sendEmails2() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var startRow = 2;  // First row of data to process
  var numRows = 10000;   // Number of rows to process
  // Fetch the range of cells A2:N10000
  var dataRange = sheet.getRange(startRow, 1, numRows, 14)
  // Fetch values for each row in the Range.
  var data = dataRange.getValues();
  for (var i = 0; i < data.length; ++i) {
    var row = data[i];
    var emailAddress = row[6];  // First column
    var message = row[12];       // Second column
    var emailSent = row[13];     // Third column
    if (emailSent != EMAIL_SENT) {  // Prevents sending duplicates
      if(emailAddress.length == 0){
        //sheet.getRange(startRow + i, 15).setValue("stop");
        break;
      }
      var subject = "Sending emails from a Spreadsheet";
      MailApp.sendEmail(emailAddress, subject, message);
      sheet.getRange(startRow + i, 14).setValue(EMAIL_SENT);
      // Make sure the cell is updated right away in case the script is interrupted
      SpreadsheetApp.flush();
    }
  }
}

Friday, October 21, 2011

Excel Indirect function

I just used Excel today to make some reports and this is a simple form or the function I made:

=INDIRECT("'" & D4 & "'!" & C4)

If you put the values from D4 and C4 into their places it looks like this: =INDIRECT("'test'!a1").
What this does is print what ever is in A1 of the test sheet. What is nice is it looks at a cell in the spreadsheet to choose the sheet to look for values in. So you could have a dropdown box show a list of the sheet names that you get from a settings sheet that you update each time you add a sheet. Then you can make reports that will update for you every time you change what is in the dropdown menu. I also use vlookups to lookup exactly what ranges to use in the dynamic indirect function. That way you can put most of the function code in one place in the table that the vlookup looks at instead of putting all the index or match function text in every place that uses the indirect function. I was having the vlookup table calculate what row each section start of stops so we can do a count of cells within that section from the indirect function without all the overhead that the vlookup table does.

Tuesday, October 11, 2011

Shared online Tracker like Google Docs


I thought of a cool idea for a collaborating tracker.
How hard would it be to make a shared online tracker where every note you add to the tracker I see on my version of the online program as if we were both on the same computer.
Its like google docs for music trackers.
The tracks would have to be able to be encoded and decoded fast and compressed and sent accross the net or peices of the file to tell the other collaborators that are using it right now what changed. Like ajax in an online or off line tracker program.
If you like this idea then comment.

Thursday, October 6, 2011

New ways of hacking websites

What if someone could send you a link to their page and in that page it could make you post a form that you can't see. This form could send money from the bank account they are logged into to the attackers account. All they have to do is send them to the right page and with the right parameters sent along it will send the money to the attacker. There are a couple ways of fixing this. The bank could use a token that can only be used once along with other parameters int he form that have different values everytime so the attacker wouldn't know what the names of the hidden fields are without going to the banks website and getting their form. If they could use PHP curl request with the banks sessionid it would be relatively easy to get the form contents and then fill in the right values into it and send the form off to the bank website and they would think it was from them. They would also use curl to not only send the sessionid but also change the referer to say it came from the banks website page where the form is. That page could also be a unique url everytime as well. Then the curl request would need to know what page to download the form. They would go to the page where the user clicks to get the form and it would create the unique url for the form there so the attacker may get the form that way. How does the attacker get the sessionid? They use javascript to somehow run document.cookie on another tab than the one they are on now. If this works then they have the sessionid and can then refresh the page quickly after the js is done getting the sessionid and once it has refreshed the page will run php code to make the curl request to the page where the bank website is. This could be any website that has forms. This is just an example with a bank to show how important it is for websites to secure their sites using some of these techniques or others. Another thing the bank website can do to make it hard to run their form without being on their site is using dynamic named functions in php. Use the create_function function in PHP to make a custom custion that is written alittle bit differently each time in a way that ensures the user is logged in:
http://php.net/manual/en/function.create-function.php
But if the hacker has your sessionid I don't know how this will be good enough. Here are some interesting pages on the subject:
http://4diggers.blogspot.com/ 
Here is an article about cross domain ajax and how cross domain ajax could break any web application http://shiflett.org/blog/2006/aug/cross-domain-ajax-insecurity

Sunday, August 28, 2011

image test to local site


Reading a php page with only an image is a method a hacker could use to get your cookie info if they could get that image tag onto a secure site or blog. &amp;lt;br /&amp;gt; &amp;lt;img alt="no image" src="http://stokescomp.com/sample/test.php" style="display: none;" /&amp;gt;

Monday, August 22, 2011

Error when trying to use JSON and jquery libraries together

For the fix for this just use json2.js instead of json.js:
https://github.com/douglascrockford/JSON-js
The problem was that he was replacing the json function in the object.prototype and this breaks jQuery since this is not a very good idea. The new json2.js is much better. Below is the troubles I was having and how I solved it with the json.js but later I ran into other things that was broken in jQuery because of json.js. So just use json2.js instead.
I got this error when I had both json.js and jquery scripts in the same html file:
JSON.parse: unexpected character So I tried updating to the newest jquery 1.6.2 and I got this error: c.replace is not a function
I spent a couple hours trying to track it down.
I noticed that when I leave out the json.js file there are no errors when running any jquery code.
First I looked in json.js and found the lines that made it fail.
In json.js it has this code at the end to actually make the parseJSON function if it doesn't exist:

if(!Object.prototype.toJSONString){
Object.prototype.toJSONString=function(filter){return JSON.stringify(this,filter);};
Object.prototype.parseJSON=function(filter){return JSON.parse(this,filter);};
}}());


Now I tracked this down to the exact part of the jquery code that was causeing the problem.
There is a function called by(a,c) in the jquery file. The variable c had these values:
paddingLeft
paddingRight
opacity
function (filter) { "use strict"; return JSON.stringify(this, filter); }
When it got to the function here it fails since thats not a string but a function that was created using JSON's Object.prototype.toJSONString=function(filter)
I don't know why the function is in this list of css types. To fix it I replaced:
c=c.replace(bp,"-$1").toLowerCase();
with:
c=c.toString().replace(bp,"-$1").toLowerCase();
the toString changes the function to a string.
Then when I run the code it gets to the json function and tries to pass an object to json so I fixed it like this:
Object.prototype.parseJSON=function(filter){if((typeof filter) == 'object') return;return JSON.parse(this,filter);};
This checks if its an object instead of the expected string and returns nothing if thats the case.
I don't want to spend more time trying to figure out the root problem but this hack will make it work for now.

Neat asynchronous uploads

I am letting people upload multiple documents at a time to be added as revisions to existing documents. If the file name matches it shows them the revs that exist.
While they enter a description for the files the upload moves the files to a temp folder:
I move the files asynchronously using a hidden iFrame and a target on the form pointing to the name of the iFrame. The php thats echoed there includes js that will change a button from loading to Open for each file so they can open pdfs from the files temp location.
Without refreshing I upload the document and allow them to open it while its in a temp folder on the server. Then when they have finished adding a description for it then the file is moved to the real folder where all the other files are. The database has a hierarchical table that shows where in the virtual folders for these files are even though they are in the same folder in the physical server.

Sunday, August 14, 2011

XMP tags

I found out recently about a tag in html I didn't know about called XMP. They make it so all the code that you put in them is shown and the browser won't interprit them as html. Here is an example:

<p>testing a paragraph</p>

PHP Daemon runs out of file resources

http://gnuvince.wordpress.com/2008/10/28/php-wrong-for-long-running-processes-wrong-for-america/

<?php
$fd = fopen('/etc/passwd', 'r');
echo "$fdn";
fclose($fd);

$fd = fopen('/etc/fstab', 'r');
echo "$fdn";
fclose($fd);
?>


And this shows the usual:
$ php fds.php
Resource id #5
Resource id #6

Python doesn't have this problem though.

PHP is reusing the file descriptors but counting up its file resource. When it gets to 2^31-1 files and then goes into negative numbers and when it gets to 0 it crashes. How can the process use that many file handles in a few weeks time?

How do you reuse old file descriptors or resources after they are closed so you can run the php script forever?

Tuesday, August 2, 2011

Clearing multiple setTimeouts with js

http://garbageburrito.com/blog/entry/555/slideshow-clearing-all-javascript-timers
I was making timers and was having trouble clearing them since if you use the same variable to save each timer and you use clearTimeout(timer); it only clears the last timer and not all of them. You can't just call clearTimeout 3 times to clear them. So I found this col code to put setTimeouts into an array and clear them before you set more.

Make many timers and clear them any time.
<script>
timers = new Array();

function resetTimeouts() {
timers = new Array();
}
function clearTimeouts() {
for (var i= 0;i < timers.length; i++) {
clearTimeout(timers[i]);
}
//resetTimeouts();
timers = new Array();
}
//stop any timer
clearTimeouts();
timers.push(setTimeout("alert('timer here');", 2000))
</script>


Then if you make many timers and then you make more you want to clear all the old ones each time you make more so the old ones aren't triggered after new ones are made.

HDs prices have dropped

3TB Hard drives are now $130 on newegg.com
Thats the cheapest I have seen. This is 4.3 cents a GB and the cheapest I knew about before was 5cents a GB.

Wednesday, July 6, 2011

VBA code for copying range of cells in excel

I helped someone make a copy of some cells in an excel spreadsheet using VBA. Thy were adding a recipe to another worksheet.

'move to the AddRecipes tab
Sheets("AddRecipes").Select
'select the range of recipe ingredients and then copy the selection.
Range("C11:C30").Select
Selection.Copy
'select the dessert sheet
Sheets("DessertIngredients").Select
'select the range and then paste there using the dynamic variables in the for loop
Range(Cells(Row1 + 1, Column1), Cells(Row1 + 21, Column1)).Select
ActiveSheet.Paste

Friday, July 1, 2011

Making php control sessions

PHP can be insecure using session variables. One reason is because if you are on a shared host like Dreamhost or godaddy you have other people on your server and the default place to store session files with your session_id and session data is /tmp which anyone can read and use that information for anything they want. I just looked in the tmp folder on a shared host and there were 14000 session files from the last 2 days. That's not good at all. First thing you should do is move the place it is stored to a place in your home directory so only you can read them.
Fix this with the following change to your php.ini file. Make sure to make this new folder writable too.
change this:
session.save_path = "/tmp"
to this:
session.save_path = "/home/username/tmp"

Also change your default session name so anyone looking at your website be not recognize the session_id when they see it:
change this:
session.name = PHPSESSID
to something like this:
session.name = fh4hd4kjddj5fhk2jdkjfh


I made a demo of how to make this work completely with MySQL using this code:
http://www.josephcrawford.com/php-articles/going-deep-inside-php-sessions/
There were some problems with his code so I am putting a version here that works including a demo page for running it.

I made a session like this:
$_SESSION['name'] = 'mike';
and it serializes it and sticks it in the file like this:
s:16:"name|s:4:"mike";";
We will be putting this in the database instead of the file system.


first make a db.php file with this in it:
<?php
include "helper_mysql.php";
if($_SERVER['HTTP_HOST'] == 'localhost') $con_server = "localhost";
else {echo "not localhost";exit();}

$con_username = "username";
$con_password = "password";

$con = @mysql_connect($con_server,$con_username,$con_password);
if (!$con){
die('Could not connect to Database');
}


Make the table for mysql with this SQL:
CREATE TABLE sessions
(session_id INT PRIMARY KEY AUTO_INCREMENT
, ses_id VARCHAR(100)
, last_access INT
, ses_start INT
, ses_value VARCHAR(5000)
);


Next is the mysql_helper function I have used with a few changes to add this variable to keep track of the number of results as a global variable: $number_results
<?php
$number_results = 0;
function mysql_magic()
{
global $con, $con_server, $con_username, $con_password, $con_database, $number_results;
$number_results = 0;
$narg = func_num_args();
$args = func_get_args();

if (!$con)
{
$con = mysql_connect( $con_server, $con_username, $con_password );
@mysql_select_db( $con_database, $con );
}

$req_sql = array_shift($args);
$req_args = $args;

$req_query = mysql_bind($req_sql, $req_args);
$req_result = mysql_query($req_query);

if (!$req_result)
{
trigger_error(mysql_error());
return false;
}

if (startsWith($req_sql, 'delete') || startsWith($req_sql, 'update') || startsWith($req_sql, 'truncate'))
{
return mysql_affected_rows(); // -1 || N
}
else if (startsWith($req_sql, 'insert'))
{
return mysql_insert_id(); // ID || 0 || FALSE
}
else if (endsWith($req_sql, 'limit 1'))
{
$number_results = mysql_num_rows($req_result);
return mysql_fetch_assoc($req_result); // [] || FALSE
}
else if (startsWith($req_sql, 'select count(*)'))
{
$line = mysql_fetch_row($req_result);
return $line[0]; // N
}
else
{
$number_results = mysql_num_rows($req_result);
return mysql_fetch_all($req_result); // [][]
}
}

function mysql_bind($sql, $values=array())
{
foreach ($values as &$value) $value = mysql_real_escape_string($value);
$sql = vsprintf( str_replace('?', "'%s'", $sql), $values);
return $sql;
}

function mysql_fetch_all($result)
{
$resultArray = array();
while(($resultArray[] = mysql_fetch_assoc($result)) || array_pop($resultArray));
return $resultArray;
}

function startsWith($haystack,$needle,$case=false) {
if($case){return (strcmp(substr($haystack, 0, strlen($needle)),$needle)===0);}
return (strcasecmp(substr($haystack, 0, strlen($needle)),$needle)===0);
}

function endsWith($haystack,$needle,$case=false) {
if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);}
return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);
}


Next is the session class which will be used to run opening, closing, reading, writing, destroying, and garbage collecting the session.

<?php
class Session
{
private $ses_id;
private $table;
private $ses_life;
private $ses_start;

public function __construct($table = 'sessions')
{
$this->_table = $table;
}

public function open($path, $name)
{
echo "opening<br />";
$this->_ses_life = ini_get('session.gc_maxlifetime');
}

public function close()
{
echo "closing<br />";
$this->gc();
}

public function read($ses_id)
{
global $number_results;
if(isset($this->_ses_id)) $ses_id = $this->_ses_id;
echo "reading<br />";
$session_sql = "SELECT * FROM " . $this->_table. " WHERE ses_id = '$ses_id' LIMIT 1";
$session_row = mysql_magic($session_sql);
if (!$session_row) return '';
if ($number_results> 0)
{
$ses_data = unserialize($session_row["ses_value"]);
$this->_ses_start = $session_row['ses_start'];
return $ses_data;
} else {
if(!isset($this->_ses_id)) $this->_ses_id = $ses_id;
return '';
}
}

public function write($ses_id, $data)
{
global $number_results;
if(!isset($this->_ses_id)) $this->_ses_id = $ses_id;
echo "writing<br />";
if(!isset($this->_ses_start)) $this->_ses_start = time();
$session_sql = "SELECT * FROM " . $this->_table. " WHERE ses_id = '" . $this->_ses_id . "' LIMIT 1";
mysql_magic($session_sql);

if( $number_results == 0 )
{
$session_sql = "INSERT INTO ".$this->_table." (session_id, ses_id, last_access, ses_start, ses_value) VALUES (NULL, '".$this->_ses_id."', ".time().", ".$this->_ses_start.", '".serialize($data)."')";
} else {
$session_sql = "UPDATE ".$this->_table." SET last_access=".time().", ses_value='".serialize($data)."' WHERE ses_id='".$this->_ses_id."'";
}
$session_res = mysql_magic($session_sql);
if (!$session_res) return FALSE;
else return TRUE;
}

public function destroy($ses_id)
{
echo "deletinging<br />";
//delete the session from the database
if(!isset($this->_ses_id)) $this->_ses_id = $ses_id;
$session_sql = "DELETE FROM sessions WHERE ses_id = '" . $this->_ses_id . "'";
$session_res = mysql_magic($session_sql);
if (!$session_res) return FALSE;
else return TRUE;
}

public function gc()
{
echo "gcing<br />";
$ses_life = time() - $this->_ses_life;
$session_sql = "DELETE FROM " . $this->_table. " WHERE last_access <$ses_life";
$session_res = mysql_magic($session_sql);
if (!$session_res) return FALSE;
else return TRUE;
}

}


Now the following will use the code that we have shown you so far. It will do many different kinds of things with sessions so you can see how it works.
<?php
$database = "test";
include "db.php";
mysql_select_db($database, $con);
require_once('session.php');

define( 'UA_THRESHOLD', 25 );
define( 'PW_MAX_CHECKS', 3 );
require_once('session.php');

$s = new Session();

/**
* Change the save_handler to use
* the class functions
*/
session_set_save_handler (
array(&$s, 'open'),
array(&$s, 'close'),
array(&$s, 'read'),
array(&$s, 'write'),
array(&$s, 'destroy'),
array(&$s, 'gc')
);

session_start();
//uses the destore function to delete your session.

echo "session_id: ".session_id()."<br />";

//how do you change php's current session_id to the custom string like below.
//changing the session_id but it only changes it temporarily for this page and in the database.
//If you echo session_id() again after refreshing the page you will find that the session_id is put back to the randomized session_id.
//you should make the session_id a psudo random id like: sess_id_, random 26 character string, IP address, timestamp in seconds, unique_id
//it would look like this: sess_id_4e0e4d31ba4981223439051270011309560113165

$new_session_id = "sess_id_".str_replace(".","",uniqid("",1).$_SERVER['REMOTE_ADDR']).time()."165";
//this will show something like this:
//sess_id_4e0e4d31ba4981223439051270011309560113165
//the 165 at the end would be incremented by 1 each time a session is made so its harder to duplicate
//only do this when you are loging in or if you want to reset the session to be different every time you go to another page or refresht he current page. You will have to test this to see what works best for you. The more often people get new sessions the less likly a hacker is able to get the session and use it before it is invalidated. It depends on the importance of your user data.
session_id($new_session_id);

echo "here is the new session_id: ".session_id()."<br />";
echo "<br />session values: <pre>";
print_r($_SESSION);
echo "</pre>";

$_SESSION['message'] = "setting session vars in the database: yay!!!";
$_SESSION['number'] = 1.3432;
$_SESSION['user'] = 'stokescomp';
$_SESSION['unset_me'] = 'I will be unset';
$_SESSION['list_array'] = array(1,4,6,8,'help');

//this will call the write function and remove that value from the session
unset($_SESSION['unset_me']);

echo "<br />session values: <pre>";
print_r($_SESSION);
echo "</pre>";

//this removes the session from the database by calling the destory method so they will have to relogin
//session_destroy();


That's it and this will make working with sessions much more secure.

Making php control sessions

PHP can be insecure using session variables. One reason is because if you are on a shared host like Dreamhost or godaddy you have other people on your server and the default place to store session files with your session_id and session data is /tmp which anyone can read and use that information for anything they want. I just looked in the tmp folder on a shared host and there were 14000 session files from the last 2 days. That's not good at all. First thing you should do is move the place it is stored to a place in your home directory so only you can read them.
Fix this with the following change to your php.ini file. Make sure to make this new folder writable too.
change this:
session.save_path = "/tmp"
to this:
session.save_path = "/home/username/tmp"

Also change your default session name so anyone looking at your website be not recognize the session_id when they see it:
change this:
session.name = PHPSESSID
to something like this:
session.name = fh4hd4kjddj5fhk2jdkjfh



I made a demo of how to make this work completely with MySQL using this code:
http://www.josephcrawford.com/php-articles/going-deep-inside-php-sessions/
There were some problems with his code so I am putting a version here that works including a demo page for running it.

Thursday, June 30, 2011

Seesions in the database

I found a helpful article showing how to use a class.
http://www.josephcrawford.com/php-articles/going-deep-inside-php-sessions/

It has problems and I spent time fixing all the problems and will post the code when its ready.

Monday, June 20, 2011

How to make and use MySQL stored functions using PHP

How to make a useful function in mysql
I am going to show how to make MySQL functions that insert data into a people table in MySQL. I will also show how to make a function that returns a value of the average age of the people in the table.
Log into MySQL with the following line:
mysql -u Username -p
Then open the database you will use like this:
use test
First create a table called people and run this in MySQL:
CREATE table people(id int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT
,name VARCHAR(50)
,age INT
);

You can insert a user in mysql or in PHP. It will use the same SQL code either way.
You can add people with their ages to a list in 2 different ways. You can either write static PHP code and pass the name and age into the SQL code via varables and execute it or you can write a MySQL function and pass it the name and age values to insert into the table via parameters.
Here is how you would insert using the last blogs method using the mysql_magic function:

$age = 15;
$name = 'Mike';
$insert = mysql_magic("INSERT INTO people VALUES(NULL,?,?)", $name, $age);
echo "insert".$insert;


Now we will make a MySQL function that will do our inserts for us.
type this in the MySQL prompt:

DROP FUNCTION IF EXISTS insert_people;
DELIMITER $
CREATE FUNCTION insert_people(name VARCHAR(50), age INT)
RETURNS INT
BEGIN
INSERT INTO people VALUES(NULL, name, age);
RETURN 1;
END$
DELIMITER ;


Here is how you would execute the insert statement from a PHP script:

$name = "Bill";
$age = 20;
$insert = mysql_magic('SELECT insert_people(?,?) AS the_insert', $name, $age);
echo $insert[0]['the_insert']."
";

If the value echoed is a 1 then it worked.
Now lets make a function that will average the ages of the people:

DROP FUNCTION IF EXISTS average_age;
DELIMITER $
CREATE FUNCTION average_age()
RETURNS INT
BEGIN
DECLARE lv_avg_age INT;
SELECT AVG(age) INTO lv_avg_age FROM people;
RETURN lv_avg_age;
END$
DELIMITER ;


Now get the average from php:

$average = mysql_magic('SELECT average_age() AS the_average');
echo "The average age is: ".$average[0]['the_average'];

If there is something you would like to see here let me know and I will add it.

Monday, June 13, 2011

PHP helper function for making SQL queries easy

Go get this function called mysql_magic at:
http://www.php.net/manual/en/ref.mysql.php#100626
This function listed in PHP's manual looks very promising for making query's easy to use but just passing the query plus the parameters to a function that uses php's mysql_bind function plus the function returns a resultset if its a select and will also work for a delete or update statement which exits the function sooner than normal.
to use the function use these:
$nb_affected = mysql_magic('delete from users');
$nb = mysql_magic('select count(*) from users');
$one_row = mysql_magic('select * from users limit 1');
$all_rows = mysql_magic('select * from users where name = ?', 'John');
$id = mysql_magic('insert into users(name,rank) values(?,?)', 'Vincent', 3);
http://www.php.net/manual/en/ref.mysql.php#100626


To make the function work with the example below make this change to the function.
global $con, $con_server, $con_username, $con_password, $con_database;

if (!$con)
{
$con = mysql_connect( $con_server, $con_username, $con_password );
@mysql_select_db( $con_database, $con );
}
I will show you how to use it next. Make a table called data in mysql.

CREATE TABLE data (age INT,name VARCHAR(50));

Next insert a couple rows.
INSERT INTO data VALUES(20,'Bill');
INSERT INTO data VALUES(18,'Mark');

I put the function mysql_magic in a file called mysql_helper.php into the include path, but you can put it in the same folder as your webpage that will be doing mysql queries. This is all I did to make it work:
include "helper_mysql.php";
$con_server = "localhost";
$con_username = "username";
$con_password = "password";
$con = @mysql_connect($con_server,$con_username,$con_password);
if (!$con){
die('Could not connect to Database');
}
$con_database = "test";
mysql_select_db($con_database, $con);
$all_rows = mysql_magic('select * from data');
echo "<br /><pre>".print_r($all_rows,true)."</pre>";


Now you will see the result will show all the rows from the table:
Array
(
[0] => Array
(
[age] => 20
[name] => Bill
)

[1] => Array
(
[age] => 18
[name] => Mark
)
)

Then you can use the following to insert more data into the table.
$insert = mysql_magic("INSERT INTO data VALUES(15,'Ron')");

Now for a more useful example. Use ?'s to signify a parameter to bind variables to.
$age = 25;
$name = "Sally";
$insert = mysql_magic("INSERT INTO data VALUES(?,?)",$age, $name);
//after inserting use the following to see what the table looks like now.
echo "<br /><pre>".print_r($all_rows,true)."</pre>";

In the next post I will show how to make a stored procedure or function in MySQL and call it using the magic_mysql function when you want to insert data into the data table.

Tuesday, June 7, 2011

How to get the current time in a timezone of choice

type this in a php page to get the time where you live. The -6 means go to 6 hours before greenwhich time.
$tz = -6;
$date = gmdate('m/d/Y', time()+($tz*3600));
echo $date;

Running php from the commandline

if you want to run a short snibit of code from the command line use this syntax:
php -r "echo 'test';"

Thursday, May 5, 2011

a nice list of firebug extensions

http://getfirebug.com/wiki/index.php/Firebug_Extensions

I love firebug and here are all the extensions for it. One thats nice is Yslow that will tell you how you can make your site's performance better.

making your own selectors in jquery

It was really cool when I found out you can make your own jquery selectors.

http://james.padolsey.com/javascript/extending-jquerys-selector-capabilities/

for instance you can do this
$.extend($.expr[':'],{
inline: function(a) {
return $(a).css('display') === 'inline';
}
});

then use it like this
$(':inline'); // Selects ALL inline elements
$('a:inline'); // Selects ALL inline anchors

the article also teaches how to store data in elements and ways you can get at that data with regular expressions. This is good because sometimes I store data in made up parameters in the dom but this is not valid html but if you store key value pairs with javascript on certain elements you can store stuff in the webpage and get it using jquery selectors or select certain items with a dom flag set using the data method of jquery.

Monday, May 2, 2011

Javascript escaping in an onclick handler

I was having trouble escaping quotes that are in an onclick handler.
The problem is that the onclick event is surounded by double quotes so there can not be any double quotes inside. I have javascript code in there that has single quotes and I escape other single quotes like this \' but double quotes can't be escaped. I found that a good way of allowing double quotes inside is to contert them to javascript escape characters such as \042 or \x22 or \u0022 which are all interprited by javascript as double quotes. If you use the " then you find out that the browser converts them to their double quote equivalents before the javascript engine can see them and then it causes javascript errors because it finds a double quote inside the onclick events double quotes and not the html entities.
Here is a list of other possibilites.
http://stackoverflow.com/questions/97578/how-do-i-escape-a-string-inside-javascript-inside-an-onclick-handler

here is the php functions that will take care of both the above javascript escaping and html escaping as well

<?php
function esc_js($value){
//use this in onclick handlers where all quotes need to be seen as quotes by javascript
//here is the double quote equivilent \x22
//here is the single quote equivilent \x27
$value = str_replace("\"","\\x22",$value);
$value = str_replace("'","\\x27",$value);
return $value;
}

function esc_html($value){
//this encodes both single and double quotes so they appear in textbox values correctly
$value = htmlentities($value,ENT_QUOTES);
return $value;
}
?>

$val1="test's test";
$val2='test"s test';
$val3="test\"s test's";

<a href="" onclick="alert('<?php echo esc_js($val1);?>');return false">test 1</a><br>
<a href="" onclick="alert('<?php echo esc_js($val2);?>');return false">test 2</a><br>
<a href="" onclick="alert('<?php echo esc_js($val3);?>');return false">test 3</a><br>

Thursday, April 21, 2011

session tracking for users

I want to make it hard for a hacker to get my users information. I will use this method I found on the page I mentioned yesterday.
http://phpsec.org/projects/guide/4.html
This page also uses this great article about securing sessions:
http://shiflett.org/articles/the-truth-about-sessions

First I will check to see if the user identifier is stored in the session. If it is then they are logged in since I will only set this variable after they successfully enter their user name and password. When they login successfully I store the IP address and their browser agent and a secret string of text that can be the same for all users or I could use a combination of username and random characters. This second identifier will be passed in the URL so the attacker would need more than just the sessionid to impersonate them. Is this secure?
Then a hacker will have to steal the session_id and impersonate them and have the same IP address and browser agent string converted to a sha1 fingerprint and store it in the url. So this would be an example:
sha1("Mozilla/5.0 GeckoSECRET_PHRASE78.0.23.128")
this is: 3fb195ec6fe52981918b9065b8362a0efed8858f
then when you are logged in you would be at: http://example.com/admin.php?secret_fingerprint=3fb195ec6fe52981918b9065b8362a0efed8858f
This script can be included in any page. I call it validate_login.php
if(!isset($_SESSION)) session_start();
//starts the database connection
require_once("includes/db.php");
//stores the log function
require_once("includes/functions.php");
$phpself = $_SERVER['PHP_SELF'];
//the user_identifier will be a 13 character random string of text like DA3591BAC915 that is stored for each user to identify them with something besides the primary key
if(isset($_SESSION['USER_IDENTIFIER'])){
if ($_GET['secret_fingerprint'] != sha1($_SERVER['HTTP_USER_AGENT'] . "SECRET_PHRASE" . $_SERVER['REMOTE_ADDR'])){
/* Make them login again */
include('login.php');
exit();
}
} else if(isset($_POST['submitlogin'])){
$user = mysql_real_escape_string($_POST['user']);
$password = sha1(mysql_real_escape_string($_POST['password']));

//authenticate user
$sql = "SELECT user_identifier FROM user WHERE user = '$user' AND password = '$password'";

$result = @mysql_query($sql);
if(!$result) {echo "There was an error";log(mysql_error($con)." sql: $sql ");exit();}
if(mysql_num_rows($result) == 0){echo "You need to user the right user or password";include('login.php'); exit();}
$row = @mysql_fetch_array($result);
$_SESSION['USER_IDENTIFIER'] = $row[0];

//only pass this in the url so it has to exist in a GET parameter for the user to be allowed to stay logged in
$secret_fingerprint = sha1($_SERVER['HTTP_USER_AGENT'] . "SECRET_PHRASE" . $_SERVER['REMOTE_ADDR']);

//send them to the page that requested to login
header('Location: ' . $_SERVER['PHP_SELF'] . '?secret_fingerprint='.$secret_fingerprint);
exit();
} else {
//they aren't logged in yet : show the login form here
include('login.php');
exit();
}

Here is an example page that requires the use of above authentication plus has a logout link and a link to another page. When we go to another page we have to include the secret finger print that has their IP address and browser hashed with an sha1 hash or they will not be authenticated and will have to log in again.
This page is admin.php
<?php
include('validate_login.php');
?>
<h1>You are logged in now</h1>
<a href="logout.php?logout=1&to=<?php echo $phpself;?>">Log off</a><br />
Go to another secure page on the <a href="anotherpage?secret_fingerprint=<?php $_GET['secret_fingerprint'];?>">site</a>.


This also has a logout link that logs the user out. Here is a good logout script:
logout.php
<?php
if(!isset($_SESSION)) session_start();
if(isset($_GET['logout'])){
session_destroy();
unset($_SESSION);
$to = $_GET['to'];

//send them to the page they were being sent to
header('Location: http://'.$_SERVER['SERVER_NAME'].':/'.$to);
exit();
}


Here is the login script login.php:
<form action="<?php echo $phpself;?>" method="post">
<p><label>Email<br /><input type="text" value="<?php if(isset($_POST['user'])) echo $_POST['user'];?>" name="user"></label></p>
<p><label>Password<br /><input type="password" name="password"></label></p>
<p><label><input type="checkbox" name="rememberme"> Remember Me</label></p>
<input type="submit" value="Log In" name="submitlogin"></p>
</form>
<a href="#">Lost your password?</a>


If you need a registration script just leave a comment.

Wednesday, April 20, 2011

Jquery selectors are cool

http://www.codylindley.com/jqueryselectors/
These are very useful for web programming with javascript Jquery.
You can use these kinds of Jquery selectors to loop through all the elements that match many different kinds of selectors such as class, id, or just first or last or nth or parent or child.
So you can actually do things not just to children but to parents of an element too.

I have used this kind of selector to get the id or other information from the first td in each row of a table. And to change the background color of the rows as you pass through them too.

PHP session variables securit

PHP stores information in sessions to keep track of what user someone has logged in as. The session variables has a session_id that can be taken through sniffing or man in the middle attacks. After they take your session_id they can apply it to their own computer and then they will be you until you log out and your session is destroyed. I would like to test these theries out to see how to make it impossible for this to work. I can track the user in one browser and not let them use that session_id in another browser. tracking IP addresses don't work because AOL changes your IP address every time you go to a new page.

Here are some links I am studying right now.
http://blogs.sitepoint.com/notes-on-php-session-security/
http://phpsec.org/projects/guide/4.html
http://blogs.sitepoint.com/php-security-blunders/

I think eventually I will want to go to a more secure method and not store anything other than a sessionid that is stored in the database that stores the other information that would normally be stored in a session variable like username, full name, if they are an employee and what page they are on or other information.
Read this page for information on how to use sessions in a database:
http://www.oracle.com/technetwork/articles/mclaughlin-phpid1-091467.html

Tuesday, April 12, 2011

A fun little MySQL puzzle

I was looking for a way to convert a column in the database that has things like this: M1.1 and M1.2 all the way up to M1.15 into something like this:
M1.01 and M1.02 all the way up to M1.09 and M1.1 (for 10) and M1.15 for any above 10.

I used mysql like this
SELECT item as `the item to fix`,
SUBSTRING_INDEX(item,'.',1) as `the part to the left of the period`,
SUBSTRING_INDEX(item,'.',-1) as `the part to the right of the period`,
if(SUBSTRING_INDEX(item,'.',-1) < 10,
CONCAT(SUBSTRING_INDEX(item,'.',1),'.','0',SUBSTRING_INDEX(item,'.',-1))
,
if(SUBSTRING_INDEX(item,'.',-1) = 10,
CONCAT(SUBSTRING_INDEX(item,'.',1),'.',1)
,
item
)
) as `the fixed value`
FROM `data` where item like '%.%'


SUBSTRING_INDEX gets the text to the left of the first occurrence of the '.' if you use a 1 for the 3rd parameter and it gets the text to the right of the last occurrence of the '.' if you set the 3rd parameter to a -1.
Cool little puzzle that took 10 minutes to solve.

Getting web request with GET request in Excel

I found a cool easy way to do a GET request to any website and use any parameters needed.
One method to get code from a webpage and use it is here:
http://scriptorium.serve-it.nl/view.php?sid=40
and another I use is here:
Function testHttpGet()
Dim oHttp As Object
Set oHttp = CreateObject("Microsoft.XMLHTTP")
MyUrl = "http://10.0.21.130/test.php?name=mikeqq"
oHttp.Open "GET", MyUrl, False
oHttp.send
'MsgBox oHttp.Status
If oHttpPost.Status < 300 Then
SomeVar = oHttpPost.responseText
MsgBox SomeVar
End If
End Function

Just put this code in a module in Excel and then call it from in the spreadsheet somewhere. So now I can have excel give and get commands from a PHP script and could even act like a cron job by executing every once in a while!

Mysql Master - Slave replication server

I put together an Ubuntu 10.10 server with MySQL on it. I did it in VmWare Player and made it so what ever inserts I put in the master computer database gets put into the slave instantly. I'm going to try doing lots of inserts to see how long till it catches up. I can use PHP to programatically decide what SQL queries go to which database.
A great article I found this in is here
http://www.oracle.com/technetwork/articles/dsl/white-php-part2-355138.html

Friday, April 8, 2011

Dynamic caching of webpages

I read an interesting article on Oracles site on how to scale PHP pages for high traffic to scale web applicatons
I can see how this would be powerful. I have made php pages before that are very complex and if there were thousands of people coming every minute it would kill the sever unless it only had to load a certain page once every hour or so. Then if there are any updates they will only be updated and seen by everyone visiting once an hour instead of the instant they appear.

instead of having to run php all the time you just run it once an hour and write the content to a textfile with the name of the file being the url of the file plus any variables or get parameters that make the page unique or look different. All requests for the next hour will just read a text file with the webpage in it.
I will try an example in php and put it here.

<?php
$timeout = 60; // One Hour is 3600
$file = 'C:/Users/mike/Desktop/webhome/cachingtest/tempcache/'.sha1($_SERVER['REQUEST_URI']);
if (file_exists($file) && (filemtime($file) + $timeout) > time()){
//only show the cached copy of the page
readfile($file);
exit();
} else {
// Setup saving and let the page execute:
ob_start();
register_shutdown_function(function (){
Global $file;
$content = ob_get_flush();
file_put_contents($file, $content);
});
}
?>
<h2>Testing saving the current page from cache and only loading a fresh copy after a certain time limit has passed.</h2>

Tuesday, March 15, 2011

javascript attributes

I was trying to find a way to make an image grow big and then small each time you click on it. I used these functions

function open_enlarge(plan){
$('#'+plan).addClass('largemap');
$('#'+plan).removeClass('smallmap');
document.getElementById(plan).setAttribute('onclick', 'close_enlarge("'+plan+'");');
$('#addjob_floorplan').attr('onclick', 'close_enlarge("addjob_floorplan")');
}

function close_enlarge(plan){
$('#'+plan).removeClass('largemap');
$('#'+plan).addClass('smallmap');
document.getElementById(plan).setAttribute('onclick', 'open_enlarge("'+plan+'");');
$('#addjob_floorplan').attr('onclick', 'open_enlarge("addjob_floorplan")');
}

Then it didn't work in internet explorer so I decided to go with a simpler way with jQuery with only 1 function call toggling 2 classes back and forth instead of having to change the onclick event and having to make it different for Internet explorer 7:

function open_enlarge(plan){
$('#'+plan).toggleClass('largemap','smallmap')
}

Test case Idea for php, javascript and mysql

I want to make some kind of test case for my websites

It automatically runs a script to recreate the test database each time abd then run the same javascript commands that a user would run normally.

The script would pretend to be a user and then analyze the finished data and expect the same result every time and if its different then it will report an error with details after the test. It will log errors during the test as well. It could be logged on a file or emailed or in a database you can look at from in the admin of the website and have the test done everyday or manually started.
My sites usually have alot that goes on and if there was something to run that tests everything or at least the hardest problems to catch then it would be worth the effort
especially when the changes I make can break something only the customers would see.

Sunday, February 6, 2011

script in CMD to copy only files that don't already exist

The following script will be written to copy.bat or something like that. When it runs it will copy the files that don't exist yet and skip them if the file does exist. This way it won't accidentally overwrite the file after you make changes to it.
set file=copy_mike.pdf
call:copy
set file=copy_jim.pdf
call:copy
set file=copy_bob.pdf
call:copy

echo done
pause
goto :EOF

:copy
if not exist %file% (
call:process
)
goto :EOF

:process
copy blank.pdf %file%