Best php questions in May 2012

Why does in_array() wrongly return true with these (large numeric) strings?

37 votes

I am not getting what is wrong with this code. It's returning "Found", which it should not.

$lead = "418176000000069007";
$diff = array("418176000000069003","418176000000057001");

if (in_array($lead,$diff))
    echo "Found";
else
    echo "Not found";

I think it is because of the limitations of the number storage. The values exceed PHP_INT_MAX.

Try without using the quotes, and try to echo the values of the variables. It will result in something like

$lead ---> 418176000000070000  
$diff ---> Array ( [0] => 418176000000070000 [1] => 418176000000060000 )

so in this case the in_array result is true!

<?php
     $lead = "418176000000069007";
     $diff = array("418176000000069003","418176000000057001");

     if(in_array($lead,$diff,true)) //use type too
       echo "Found";
     else
       echo "Not found";
?>

Try this. It will work.

Why does PHP use opcode caches while Java compiles to bytecode files?

26 votes

From my point of view, both PHP and Java have a similar structure. At first you write some high-level code, which then must be translated in a simpler code format to be executed by a VM. One difference is, that PHP works directly from the source code files, while Java stores the bytecode in .class files, from where the VM can load them.

Nowadays the requirements for speedy PHP execution grow, which leads people to believe that it would be better to directly work with the opcodes and not go through the compiling step each time a user hits a file.

The solution seem to be a load of so called Accelerators, which basically store the compiled results in cache and then use the cached opcodes instead of compiling again.

Another approach, done by Facebook, is to completely compile the PHP code to a different language.

So my question is, why is nobody in the PHP world doing what Java does? Are there some dynamic elements that really need to be recompiled each time or something like that? Otherwise it would be really smarter to compile everything when the code goes into production and then just work with that.

The most important difference is that the JVM has an explicit specification that covers the bytecode completely. That makes bytecode files portable and useful for more than just execution by a specific JVM implementation.

PHP doesn't even have a language specification. PHP opcodes are an implementation detail of a specific PHP engine, so you can't really do anything interesting with them and there's little point in making them more visible.

How are input keys exploitable by malicious users?

18 votes

In the CodeIgniter PHP framework, there is a function that automatically runs on each request that, among other things, filters the GET/POST/COOKIE array keys, and kills the application if it encounters characters it deems unsafe.

To prevent malicious users from trying to exploit keys we make sure that keys are only named with alpha-numeric text and a few other items.

Something like:

// foreach GET/POST/COOKIE keys as $str...
if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
{
    exit('Disallowed Key Characters.');
}

For example, this will trigger if you accidentally post something like <input name="TE$T"> or have a query string like ?name|first=1.

I can see this being a good way to enforce common sense key names, or catch mistakes while developing an application, but I don't understand: How can a malicious user possibly "exploit keys" in $_POST data for instance? Especially since (I would assume) input values are just as exploitable, what is this actually preventing?

Your question, in itself, brings up a good point: it's unclear what exactly you're being protected against. But there are some popular items it could be addressing:

  • magic quotes
  • things that could eventually lead to SQL injection
  • strings that could be executed by way of shell commands
  • things that could conflict with your URL
  • things that could conflict with HTML
  • things that resemble a directory traversal attack
  • cross site scripting (XSS) attacks

But other than those, I really can't think of why you'd always why you'd want to generally protect via preg_match("/^[a-z0-9:_\/-]+$/i", $str).

I've got the feeling that they're overprotecting simply because CodeIgniter is so widely used that they need to protect against things they themselves haven't thought of yet for the sake of their users who may be even less-aware of such attacks than CodeIgniter's developers.

Secure string compare function

15 votes

I just came across this code in the HTTP Auth library of the Zend Framework. It seems to be using a special string compare function to make it more secure. However, I don't quite understand the comments. Could anybody explain why this function is more secure than doing $a == $b?

/**
 * Securely compare two strings for equality while avoided C level memcmp()
 * optimisations capable of leaking timing information useful to an attacker
 * attempting to iteratively guess the unknown string (e.g. password) being
 * compared against.
 *
 * @param string $a
 * @param string $b
 * @return bool
 */
protected function _secureStringCompare($a, $b)
{
    if (strlen($a) !== strlen($b)) {
        return false;
    }
    $result = 0;
    for ($i = 0; $i < strlen($a); $i++) {
        $result |= ord($a[$i]) ^ ord($b[$i]);
    }
    return $result == 0;
}

It looks like they're trying to prevent timing attacks.

In cryptography, a timing attack is a side channel attack in which the attacker attempts to compromise a cryptosystem by analyzing the time taken to execute cryptographic algorithms. Every logical operation in a computer takes time to execute, and the time can differ based on the input; with precise measurements of the time for each operation, an attacker can work backwards to the input.

Basically, if it takes a different amount of time to compare a correct password and an incorrect password, then you can use the timing to figure out how many characters of the password you've guessed correctly.

Consider an extremely flawed string comparison (this is basically the normal string equality function, with an obvious wait added):

function compare(a, b) {
    if(len(a) !== len(b)) { 
        return false;
    }
    for(i = 0; i < len(a); ++i) {
        if(a[i] !== b[i]) {
            return false;
        }
        wait(10); // wait 10 ms
    }
    return true;
}

Say you give a password and it (consistently) takes some amount of time for one password, and about 10 ms longer for another. What does this tell you? It means the second password has one more character correct than the first one.

This lets you do movie hacking -- where you guess a password one character at a time (which is much easier than guessing every single possible password).

In the real world, there's other factors involved, so you have to try a password many, many times to handle the randomness of the real world, but you can still try every one character password until one is obviously taking longer, then start on two character password, and so on.

This function still has a minor problem here:

if(strlen($a) !== strlen($b)) { 
    return false;
}

It lets you use timing attacks to figure out the correct length of the password, which lets you not bother guessing any shorter or longer passwords. In general, you want to hash your passwords first (which will create equal-length strings), so I'm guessing they didn't consider it to be a problem.

Why does preg_replace with /(.*)/ repeat part of string?

14 votes

Why does the following code:

<?php echo preg_replace("/(.*)/", "$1.def", "abc");

Output abc.def.def instead of abc.def?

I'm interested in understanding why the repetition occurs.

Using /(.+)/ or /^(.*)$/ works as expected, but I'm not looking for a solution, just asking a question (although these patterns may be related to the answer).

Tinker with a live version here.

Because .* matches the empty substring at the end of the string. It means there are two matches to the string abc:

  1. The whole string abcabc.def
  2. The empty string → .def

which gives abc.def.def.


Edit: Detail of why it happens is explained in Java regex anomaly?.

Baffled: PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0?

13 votes

I have found that one common reason for the error is an exception being thrown from within an exception handler. I'm quite sure this doesn't happen in the application I'm trying to debug... But I've put all the initialization processing lines at the top of index.php in a try/catch.*

It can apparently also happen because some things cannot be serialized to be stored in a session. At most this application stores arrays into the session (quite a bit), but I'm confident that it doesn't store anything too out of the ordinary in it.

Someone commented that it happened to them because their primary key needed to be CHAR(32) instead of INT(11). The PK's in this app are all INTs.

Other suggestions are that it could be a problem with PHP 5.3.3 fixed in 5.3.6, full disk, and a need to typecast a SimpleXML value. We do happen to be running PHP 5.3.3, but upgrading would have to be a last resort in this case. It hasn't always been doing this.

UPDATE/NOTE: I actually can't reproduce the error myself, only see it happening in the logs, see below paragraph for where I believe the error is happening...

* From the error logs, it seems likely that at least one place it is happening is index.php. I am deducing this only because it is indicated in some entries by a referring URL. The try/catch code is currently only around the "top" initialization portion of the script, below that is mostly the HTML output. There is some PHP code in the output (pretty straightforward stuff though), so I may need to test that. Here is the catch part, which is not producing any output in the logs:

} catch (Exception $e) {
    error_log(get_class($e)." thrown. Message: ".$e->getMessage(). "  in " . $e->getFile() . " on line ".$e->getLine());
    error_log('Exception trace stack: ' . print_r($e->getTrace(),1));
}

Would really appreciate any tips on this!

EDIT: PHP is running as an Apache module (Server API: Apache 2.0 Handler). I don't think there are any PHP accelerators in use, but it could just be that I don't know how to tell. None of the ones listed on Wikipedia are in phpinfo().

As far as I can tell the MPM is prefork. This is the first I'd ever looked into the MPM:

# ./httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

The problem

In short you have a exception thrown somewhere, you have no idea where and up until now you could not reproduce the error: It only happens for some people, but not for you. You know that it happens for other people, because you see that in the error logs.

Reproduce the problem

Since you have already eliminated the common reasons you will need to reproduce the error. If you know which parameter will cause the error it should be easy to locate the error.

  • Most likely it is enough if you know all the POST/GET parameters.
  • If you can't reproduce with just these, you need to know additional request headers. Such as user agent, accept-encoding,...
  • If you still can't reproduce, then it becomes very difficult: The error may depend on a state (a session), the current time, the source ip address or the like.

The custom log method

Let's start simple: To get alle parameters you can write in the very beginning of the effected php file something like:

file_put_contents("/path/to/some/custom_error_log", date()."\n".print_r(get_defined_vars(), true), FILE_APPEND | LOCK_EX);

Don't forget that the custom_error_log file must be writable to your php application. Then, when the error occurs in the error log, find the corresponding lines in your custom_error_log file. Hopefully there are not to many requests per second so that you can still identify the request. Maybe some additional parameters in the error log like source ip can help you identify the request (if your error log shows that). From that data, reconstruct a request with the same POST/GET parameters.

The tcpdump method

The next option that is very simple as well, but requires you to have root-access on your target machine is to install tcpflow. Then create a folder, cd into that folder and simply execute (as root) tcpflow "port 80". The option (port 80) is a pcap filter expression. To see all you can do with that, see man pcap-filter. There is a lot what these filter expressions can do.

Now tcpflow will record all tcp connections on port 80, reconstruct the full data exchange by combining the packages belonging to one connection and dump this data to a file, creating two new files per connection, one for incoming data and one for outgoing data. Now find the files for a connection that caused an error, again based on the timestamp in your error log and by the last modified timestamp of the files. Then you get the full http request headers. You can now reconstruct the HTTP request completely, including setting the same accept-encoding, user-agent, etc. You can even pipe the request directly into netcat, replaying the exact request. Beware though that some arguments like a sessionid might be in your way. If php discovers that a session is expired you may just get a redirect to a login or something else that is unexpected. You may need to exchange things like the session id.

Mocking more things

If none of this helps and you can't reproduce the error on your machine, then you can try to mock everything that is hard to mock. For example the source ip adress. This might make some stunts necessary, but it is possible: You can connect to your server using ssh with the "-w" option, creating a tunnel interface. Then assign the offending ip adress to your own machine and set routes (route add host ) rules to use the tunnel for the specific ip. If you can cable the two computers directly together then you can even do it without the tunnel.

Don't foget to mock the session which should be esiest. You can read all session variables using the method with print_r(get_defined_vars()). Then you need to create a session with exactly the same variables.

Ask the user

Another option would be actually ask the user what he was doing. Maybe you can follow the same steps as he and can reproduce.

If none of this helps

If none of that helps... well... Then it gets seriously difficult. The IP-thing is already highly unlikely. It could be a GEO-IP library that causes the error on IPs from a specific region, but these are all rather unlikely things. If none of the above helped you to reproduce the problem, then you probably just did not find the correct request in all the data generated by the custom_log_file-call / tcpflow. Try to increase your chances by getting a more accurate timestamp. You can use microtime() in php as a replacement for date(). Check your webserver, if you can get something more accurate than seconds in your error log. Write your own implementation of "tail", that gives you a more accurate timestamp,... Reduce the load on the system, so that you don't have to choose from that much data (try another time of day, load of users to different servers,...)

circle the problem once you can reproduce

Now once you can reproduce it should be a walk in the park to find the actual cause. You can find the parameter that causes the error by trial and error or by comparing it to other requests that caused an error, too, looking for similarities. And then you can see what this parameter does, which libraries access it, etc. You can disable every component one by one that uses the parameter until you can't reproduce anymore. Then you got your component and can dive into the problem deeper.

Tell us what you found. I am curious ;-).

How does PHP handle variables?

12 votes

I'm a PHP developer since many years but I don't know just one detail of how PHP handles variables and their types behind the scenes. I mean: in PHP - in theory - I could use the same variable to store an integer, and then a string, and then a boolean, and then an array... etc...

Personally, I loathe this way of "poorly-casted" programming, but I'm wondering how can PHP store and manage the variables and their types as I asked. I imagine the interpreter creates and handles C variables in behind, but I can't figure out how.

Thank you.

Behind the scenes, PHP variables are stored in a "zval" structure, which consists of a union between all of the types of data which the variable could store (e.g, a long, a double, a string pointer/length, an object pointer...), and a couple of other fields outside the union which indicate which type it is and keep track of a reference count.

There's some further discussion of this at:

http://devzone.zend.com/317/extension-writing-part-ii-parameters-arrays-and-zvals/

improving a friends list query : counting the mutual friends

11 votes

i have two tables in my database one is to keep users info (users_table ) and the other one keeps track of the friends

users_table:

id    username      avatar  
1         max       max.jpg  
2         jack      jack.jpg  

friends_table :

id    u1_id      u2_id  
1         1          2  
2         1          3  

in every user profile i show his/her friends list

here is my query

select u.id,
    u.username,
    u.avatar
from friends_table f
join users_table u on f.u1_id = u.id || f.u2_id = u.id
where u.id <> $profile_id
    and (f.u1_id = $profile_id || f.u2_id = $profile_id)

this query selects friends of the profile owner ($profile_id)

and join them with the user table to get each friend username and avatar

now i want to count the mutual friends between each friend and the profile owner is it possible to this in one query or should i do some long and probably slow query like this for each founded friend( it's just a example and it might have some syntax error ):

       foreach ( $friends_list_query_resul as $qr ){
       $friend_id = $qr['id'];

       $mutual_count = mysql_query
    ( "select count(*) from friends_table where 
    ($u1_id = $friend_id || $u2_id = $friend_id )
               && 


    ( $u1_id IN ( SELECT `u1_id`,`u2_id` from friends_table where
     ($u1_id = $profile_id || $u2_id = $profile_id ) )

||

      $u2_id IN ( SELECT `u1_id`,`u2_id` from friends_table where
     ($u1_id = $profile_id || $u2_id = $profile_id ) )


       ")
        }

i've decided to add two rows for each friend relation to the table .

id    u1_id      u2_id  
1         10         20  
2         20         10

it makes the process easier and faster .

Why is it a bad idea to tell your server to parse HTML as PHP?

11 votes

You know you can make a server parse HTML pages as PHP (execute PHP code in a HTML doc) using .htaccess?

Well, some people say it's bad to do so. Why?

Some people also say it opens a security vulnerability in your application. How?

The source code is still removed before the document reaches the browser, so it can't be the case of unauthorized access to source code, right?

Let me start with a little story: back when I was a security contact at a Linux distribution vendor, the PHP security team begged Linux vendors to stop calling interpreter crashes security bugs, even when the PHP interpreter was running inside the web server (say, mod_php on Apache). (At the time, roughly one interpreter crash was being found per week.)

It took a little bit of conversation for them to actually convince us that whoever supplied the running PHP code is completely trusted and any attempt to control what the scripts could do from the interpreter was misguided -- and if someone figured out how to crash the interpreter to walk around the restrictions it tried to impose (such as the entire silly safe mode pile of crap), it was not a security flaw, because the safe execution of scripts was not the goal of the PHP interpreter -- it never was and never would be.

I'm actually pretty happy with the end result of the discussions -- it clearly defined PHP's security goals: You should only ever allow execution of PHP code that you 100% completely trust. If you do not trust it, you do not run it. It's that simple.

Whatever operating system resources are available to the interpreter are all available and fair game, regardless of whether the script exploits a bug in the interpreter or just does something unexpected.

So, please do not allow random code to be executed in the context of your webserver unless that is what you really want.

Please use the principle of least privilege to guide what resources are available to every program.

Consider using a mandatory access control tool such as AppArmor, SELinux, TOMOYO, or SMACK to further confine what your programs can and can't do. I've worked on the AppArmor project since 2001 or so and am fairly confident that with a day's effort most system administrators can enhance their sites security in a meaningful way with AppArmor. Please evaluate several options, as the different tools are designed around different security models -- one or another may be a better fit.

But whatever you do, please don't run your server in a fashion that needlessly opens it up to attack via extra vectors.

Is a PHP Session acceptable with the new UK cookie law?

10 votes

I am just looking for some advice on the new UK Cookie Law and how it affects PHP sessions. I understand that you do not need the users to opt in when a cookie is "strictly necessary" and the example given is adding an item to a shopping cart.

I am using similar functionality that remembers what you have stored in a contact form, which I feel is strictly necessary use of a session and therefore no opt in is required.

However the confusion for me arises because I have a session_start(); at the top of each page, which means the cookie is set straight away. Some users will not then go to use the contact form, so this means that the cookie is not strictly necessary for them.

I could remove session_start(); from the top of each page, but this functionality is used throughout a number of websites and it would be preferable if we could leave it in.

Could anyone shed any more light on this?

The simple answer is that you're probably going to be okay, the extent to which this law will even be enforced is massively up for debate anyway.

We will enforce the law proportionately. We’ll look at the risks if and when customers complain to us. If a websites’ cookie and privacy is a risk to many people, we may then take action.

There is a balance to be struck though, as not all cookies are equal, and our enforcement approach will bear this in mind.

For example, someone may complain about a cookie placed without their consent, but if it was just used to remember essential details rather than to gather information to be used for marketing purposes, then it may not be appropriate to act.

(Source: The ICO's Dave Evans on EU cookie law compliance)

Regex to ignore accents? PHP

8 votes

Is there anyway to make a Regex that ignores accents?

For example:

preg_replace("/$word/i", "<b>$word</b>", $str);

The "i" in the regex is to ignore case sensitive, but is there anyway to match, for example
java with Jávã?

I did try to make a copy of the $str, change the content to a no accent string and find the index of all the occurrences. But the index of the 2 strings seems to be different, even though it's just with no accents.

(I did a research, but all I could found is how to remove accents from a string)

I don't think, there is such a way. That would be locale-dependent and you probably want a "/u" switch first to enable UTF-8 in pattern strings.

I would probably do something like this.

function prepare($pattern)
{
   $replacements = Array("a" => "[áàäâ]",
                         "e" => "[éèëê]" ...);
   return str_replace(array_keys($replacements), $replacements, $pattern);  
}

pcre_replace("/(" . prepare($word) . ")/ui", "<b>\\1</b>", $str);

In your case, index was different, because unless you used mb_string you were probably dealing with UTF-8 which uses more than one byte per character.

Slow MySQL Remote Connection

8 votes

Currently our site is running on 1 server (Ubuntu 10.04 - Rackspace is our host), and in order to be able to handle traffic spikes, we are currently using the highest option that Rackspace offers (30 GB RAM and an 8-core CPU).

CPU is our bottleneck, so I would like to put MySQL on its own server. I have tried doing this, but unfortunately it's adding 9 seconds to the page load time. PHP / MySQL is connecting from 1 server to the other through Rackspace's ServiceNet (local ip address). Before using the ServiceNet ip address, the page load was ridiculously slow (over 40 seconds).

I have added "skip-name-resolve" to my.cnf, and this did not seem to improve performance at all.

I am just wondering what options I have to reduce the remote MySQL connection time. It seems like there has to be something I'm missing because an extra 9 seconds is way too much.

Cloned server running MySQL from the other server: http://173.45.255.52/index.php?action=browse_members

Live server running MySQL locally: http://bros4bros.com/index.php?action=browse_members


UPDATE:

I did a simple query, and my page load time was very fast (270 ms), so I did a much larger query (SELECT * FROM cities WHERE 1... this table has almost 3,000,000 records), and the response time is still not much different from the live site: http://173.45.255.52/simple_query.php

I'm kind of stumped. How can it be adding 9 seconds to the site load time just by running MySQL remotely?

A waterfall shows it's just waiting for 9 seconds.

waiting

The live site's waterfall is below:

live waterfall


UPDATE 2:

Using mysql_pconnect instead of mysql_connect makes no difference. There is still an extra 8 - 9 seconds of waiting. Pinging one server to the other is less than 1 ms. I'm tearing my hair out now.

Temporarily disabling the firewall has no effect.

Using "mysqli_connect" instead of "mysql_connect" successfully connects but queries return no results... SCRATCHES HEAD


UPDATE 3:

Successfully updated the code to use "mysqli_connect" instead of "mysql_connect", and there was no performance benefit. I had to change my "mysql_query" statements to "mysqli_query", etc.


UPDATE 4:

Yeah, that sounds like it has to be the problem (in response to Jens' comment below). We're displaying 60 members on the page, so if we're doing two small queries per member displayed, that's 120 queries. I guess they're just adding up. Time to hit the code to find a more elegant solution to minimize queries... Interestingly enough I destroyed the second server, cloned the first server again, and now I'm only seeing an extra 2.5 seconds. If I develop a more elegant solution to minimize queries, I've got to be able to get that to negligible.

Reduce the number of MySQL queries!

I am in the process of converting a lot of small queries into fewer larger queries, and it is working. The site is now very fast when running MySQL from the other server.

How can I pass an array of PDO parameters yet still specify their types?

7 votes
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";

I want to still use the array input like this:

$stmt->execute($array);

Otherwise I cannot reuse the same method for executing my queries.

At the same time, the :limit1 and :limit2 doesn't work unless it is put in like this:

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);

I tried to do both but it doesn't execute with the bindParams:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);

What is the way around it?

I thought I could extend PDOStatement and add a new method "bindLimit" or something but I can't figure out what internal method PDO uses to bind parameters to a variable.

If you turn off the default setting of PDO::ATTR_EMULATE_PREPARES, then it will work. I just found out that that setting is on by default for mysql, which means you never actually use prepared statements, php internally creates dynamic sql for you, quoting the values for you and replacing the placeholders.

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare($sql);
$stmt->execute(array(5)); //works!

The prepares are emulated by default because of performance reasons.

See as well PDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?

Regex: Help in allowing only some letters, banning special characters ($% etc.), except others (' -). Multi word string

6 votes

I need a Regex for PHP to do the following:

I want to allow [a-zα-ωá-źа-яա-ֆა-ჰא-ת] and chinese, japanese (more utf-8) letters; I want to ban [^٩٨٧٦٥٤٣٢١٠۰۱۲۳۴۵۶۷۸۹] (arabic numbers);

This is what i've done:

function isValidFirstName($first_name) {
    return preg_match("/^(?=[a-zα-ωá-źа-яա-ֆა-ჰא-ת]+([a-zα-ωá-źа-яա-ֆა-ჰא-ת' -]+)?\z)[a-zα-ωá-źа-яա-ֆა-ჰא-ת' -]+$/i", $first_name);
}

It looks like it works, but if I type letters of more than 1 language, it doesn't validate.

Examples: Авпа Вапапва á-ź John - doesn't validate. John Gger - validates, á-ź á-ź - validates.

I would like to this all of these.

Or if there's a way, to echo a message if user entered more lingual string.

I can't reproduce the failure cases here (Авпа Вапапва á-ź John validates just fine), but you can simplify the regex a lot - you don't need that lookahead assertion:

preg_match('/^[a-zα-ωá-źа-яա-ֆა-ჰא-ת][a-zα-ωá-źа-яա-ֆა-ჰא-ת\' -]*$/i', $first_name)

As far as I can tell from the character ranges you've given, you don't need to exclude the digits because anything outside these character classes will already cause the regex to fail.

Another consideration: If your goal is to allow any letter from any language/script (plus some punctuation and space) you can (if you're using Unicode strings) further simplify this to:

preg_match('/^\pL[\pL\' -]*$/iu', $first_name)

But generally, I wouldn't try to validate a name by regular expressions (or any other means): Falsehoods programmers believe about names.

javascript incorrectly determines daylight savings time line -- an example out of 2006

6 votes

I have read many StackOverflow questions on the javascript new Date() object when it comes to daylight savings time lines -- as in when they are crossed. However, I haven't seen an answer about this particular problem or a way to work around it while still relying on 'unix time'.

I have personally chosen to work around this issue by passing the javascript date as a date to my PHP code rather than the unix time. Yet, the nagging question still remains! I have confirmed this behavior on IE8, Chrome, and FF so I'm assuming it will behave the same for you. (Update: OSX users might not be able to generate this behavior)

My Research; the closest questions to my issue:

  • This user was working on the particular hours right around the DST change.
  • This user was worried about the presentation of the time depending on the user's time zone. The accepted answer on that page mentioned that getTimezoneOffset is "flaky" which led me to not delve into that.
  • See my answer below on other questions that have some great insights

I have generated a test scenario around November 1st, 2006. This may or may not work the same for you depending on the time zone you are in. If I understand the javascript aspect correctly, you will need to synchronize your PC's clock to

Eastern Time (US & Canada) and check the 'Automatically adjust clock for Daylight Saving Time'.

I am basing this experiment off of the "Indianapolis" time zone in PHP. My javascript result, when I find the unix time for November 1st, 2006 is one hour off of what the PHP generates (3600 seconds). According to this page (Thanks Jon!) javascript is wrong.

The two languages results' come back into agreement on 11/06/2006!

This and other research causes me to believe that Javascript got its history wrong and picked the wrong Sunday to 'Fall back' out of DST -- thereby causing the discrepancy I am seeing.

I have tried to simplify this as much as possible but there are still quite a few gears in motion.

1) Here is the PHP code and output that shows the CORRECT number of milliseconds until the date 11/01/2006.

date_default_timezone_set("America/Indiana/Indianapolis");
echo "Unixtime for November 1, 2006 is: ".strtotime("11/01/2006")."\n";
echo "Unixtime for November 6, 2006 is: ".strtotime("11/06/2006");

The result is:

Unixtime for November 1, 2006 is: 1162357200 (where the disagreement lies)
Unixtime for November 6, 2006 is: 1162789200

Both of them are based off of GMT-0500.

2) In Javascript, (see my jsfiddle**), I call new Date and then getTime() upon it like so (and remove the milliseconds):

new Date("2006/11/01").getTime()/1000
new Date("2006/11/06").getTime()/1000

This generates the values

1162353600 <-- PHP outputs: 1162357200
1162789200 <-- the same as PHP for '2006/11/06'; congruence is restored

which is a difference (for 2006/11/01) from the output via PHP of 3600 seconds -- or one hour. This value (one hour earlier) when processed in my PHP application generated the prior day (2006/10/31) which was unacceptable since it broke my navigation forward. (see more explanation of my particular scenario)

Outputting in Javascript: Date("2006/11/01") without calling getTime() clears up some of the mystery because javascript reveals the offset it was using GMT-0400.

My jsfiddle** experiment (also listed above) shows these results.

**(you may need to change your computer's timezone to see the identical behavior).

Possibly coming into play is that according to Wikipedia 2006 was the first year that Indiana began using DST. A curious puzzle either way.

Since I have already worked out my solution (by avoiding relying on unix time in my javascript) I thought I should post this for posterity and hopefully someone might know how to correct the value javascript is showing.

The question is this: How does one bring the two 'unix time' results between PHP and javascript into alignment? I would be grateful to learn how around the DST 'line' or in general. (I'm currently assuming the DST line is the problem).

Update: an iMac running Chrome generated the results that PHP is generating. What??? Wild. Any javascript-side fix to this behavior looks like it would be a great undertaking (or at least ugly). Perhaps this is not a javascript problem since it generates the correct answer depending on the OS (or other factors?).

Notably, on this iMac I did not force the timezone and I'm not sure this Apple computer would allow it. The settings for "Set date and time automatically" was checked (true) and disabled. The time zone was set to Eastern Daylight Time. The box to 'Set timezone automatically' was unchecked (false) and disabled.

I added the Windows tag to highlight that it doesn't seem to be a problem in OSX.

Update: According to the site linked above, I verified that all the following dates crossed into a new GMT offset on the appropriate dates (updated fiddle) -- unlike how the 2006 response was one week off. I.e., on November 4th, 2007, it was GMT-4 and November 5th, 2007, it returned GMT-5.

  • 2007 Sunday, March 11 at 2:00 AM Sunday, November 4 at 2:00 AM
  • 2008 Sunday, March 9 at 2:00 AM Sunday, November 2 at 2:00 AM
  • 2009 Sunday, March 8 at 2:00 AM Sunday, November 1 at 2:00 AM
  • 2010 Sunday, March 14 at 2:00 AM Sunday, November 7 at 2:00 AM
  • 2011 Sunday, March 13 at 2:00 AM Sunday, November 6 at 2:00 AM

Lastly, if you know the proper channels to submit this error in 2006 to whatever timezone source Javascript is relying on, please do so and let me know about it.

Firstly, time in Indiana is very complicated.

But in this case, I believe Javascript is wrong. The output of your Javascript on my machine (having set the time zone) is "Wed Nov 01 2006 00:00:00 GMT-0400 (Eastern Daylight Time)" on Chrome and "Wed Nov 1 00:00:00 EDT 2006" on Internet Explorer - but daylight saving time ended in Indianapolis in 2006 on October 29th.

.NET's TimeZoneInfo class gives the same result:

// Ignore the daft ID; it really means Eastern time
var zone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var local = new DateTime(2006, 11, 1);
Console.WriteLine(zone.GetUtcOffset(local));

Output:

-5:00:00

(So it knows it's not in daylight saving time then.)

Likewise in Noda Time (my own date and time library, which uses the tzdb database):

var zone = DateTimeZone.ForId("America/Indiana/Indianapolis");
var instant = new Instant(1162357200 * NodaConstants.TicksPerSecond);
var zoned = new ZonedDateTime(instant, zone);
Console.WriteLine(zoned);

Result:

Local: 01/11/2006 00:00:00 Offset: -05 Zone: America/Indiana/Indianapolis

Shift values down the chain in a table

6 votes

Provided that I have the following result set from a mysql database table:

+----+------+-------+
| ID | type | value |
+----+------+-------+
|  8 |    A |  1435 |
|  9 |    B |  7348 | 
| 10 |    A |  1347 | 
| 11 |    A |  3478 | 
| 12 |    A |  4589 | 
| 13 |    B |  6789 |
+----+------+-------+

I would like to delete row ID 8 and push the values in the field 'value' down, in such a way that every row has the value of previous entry, but affecting only those where the field 'type' is the same as the row being deleted ('A' in this case).

That is to say, deleting row id 8 should eventually yield the following:

+----+------+-------+
| ID | type | value |
+----+------+-------+
|  - |    - |    -  | *
|  9 |    B |  7348 |   |
| 10 |    A |  1435 | * |
| 11 |    A |  1347 | * |
| 12 |    A |  3478 | * |
| 13 |    B |  6789 |   V
+----+------+-------+

ID 10 has inherited the value from ID 8, then ID 11 inherits from ID 10, and so on. Notice however how rows having type 'B' are unaffected.

So the question: Is there any way to perform this "shift" of values without having to query and update each row one by one? In an ideal world I would do one query to do shift and then another to delete the row, but I'm not quite sure if this is possible at all.

(Also I would rather not use Triggers, since I intend encapsulate all the application logic within the application itself)

SET @remove_id = 8;

SELECT ID, type, value FROM (
  SELECT   ID,
           type,
           CAST(IF(type <> @type OR ISNULL(@val), value, @val) AS UNSIGNED)
             AS value,
           @type := IF(ID   = @remove_id, type, @type),
           @val  := IF(type = @type, value, @val)
  FROM     my_table JOIN (SELECT @type := NULL, @val := NULL) AS z
  ORDER BY ID ASC
) AS t
WHERE ID <> @remove_id

See it on sqlfiddle.


UPDATE

I hadn't realised you actually wanted to update the underlying table. For that, you can use some slight hackery to effectively do the same thing in an UPDATE statement (one can't assign to user variables directly, so instead assign to a column the concatenation of its new value and a null string formed from taking the first 0 characters of the newly assigned user variable):

SET @remove_id = 8, @type = NULL, @val = NULL;

UPDATE my_table SET
  value = IF(
    type <> @type OR ISNULL(@val),
    value,
    CONCAT(@val, LEFT(@val := value, 0))
  ),
  type = CONCAT(type, LEFT(
    @type := IF(
      ID <> @remove_id,
      @type,
      CONCAT(type, LEFT(@val := value, 0))
    )
  , 0))
ORDER BY ID ASC;

DELETE FROM my_table WHERE ID = @remove_id;

See it on sqlfiddle.

PHP vs ASP.NET static variables

5 votes

Static variables in ASP.NET caught me off guard today. Then i became freaked out, because this means either i have a fundamental misunderstanding of static variables in the world of the web or ASP.NET does not act like i thought it would.

So in ASP.NET

public class MyClass {
    public static bool myVar = true;    
}

If ASPUserA sets MyClass.myVar = false every other user on the system would experience these changes. So, ASPUserB would have myVar = false. My Source: http://www.foliotek.com/devblog/avoid-static-variables-in-asp-net/

class MyClassPHP {
    public static $myVar = false;
}

If PHPUserA sets MyClass::$myVar = true does this mean that every user on the system experiences these changes???

Thank you.


Upon further research i did this;

class MyClassPHP {
    public static $myVar = 0;
}

Then i had users who went to a page do this

MyClassPHP::$myVar++;
echo MyClassPHP::$myVar;

It always was 1. No matter how many times i refreshed or simultaneous connections... WOHHH that was a great conclusion, or else i am screwed!!


ASP.NET update

Upon further research and testing things i found this.

public partial class MyPage : System.Web.UI.Page
{
    public static int myInt = 0;

    protected void Page_PreInit(object sender, EventArgs e)
        myInt++;
    }

}

Then my page can display myInt.

Between the browsers (Firefox and chrome) the myInt was progressively higher as i refreshed the page. So this does not matter if your class is static. It only matters if you have static variables. They are application wide.

When running in IIS:

A static variable is not "page" specific. It is "AppDomain" specific. The only relation to the "page" would be the path (so to speak) of the variable (MyProject.MyPage.MyVariable for example). Because all users of your application are running in the same AppDomain (i.e. same IIS application folder), then they will all use the same static variable. So... eventually your users are going to see each each other's information since they are all sharing that one single static variable.

PHP however tracks statics PER USER INSTANCE, so I guess you could call them "safer from the singleton dangerzone".

how to delete database row in example below?

4 votes

I have a cancel button where the user can cancel on a file upload and it will display a cancel message. Now what I want also to happen is that when the user clicks on the Cancel button, it will look up for the file name which has been cancelled in the database and delete the database row. Problem is that it is not deleting the database row at all. How can I get this to happen. At the moment I am using the jpuery.ajax method which you can see in code below.

Below is form code:

var $fileImage = $("<form action='imageupload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='return imageClickHandler(this);' class='imageuploadform' >" + 

 "Image File: <input name='fileImage' type='file' class='fileImage' /></label><br/><br/><label class='imagelbl'>" + 

 "<input type='submit' name='submitImageBtn' class='sbtnimage' value='Upload' /></label>" + 

 "</p><p class='imagef1_cancel' align='center'><label>" + 

 "<input type='button' name='imageCancel' class='imageCancel' cancel_image_file_name='" + imagefilename + "' value='Cancel' /></label></form>"); 

Below is the cancel button function:

    $('.imagef1_cancel').eq(window.lastUploadImageIndex).find(".imageCancel").on("click", function(event) {

        var cancel_image_file_name = $(this).attr('cancel_image_file_name');

    jQuery.ajax("cancelimage.php?imagefilename=" + cancel_image_file_name)

    return stopImageUpload(2, cancel_image_file_name);

});

Finally below is the cancelimage.php script where the jquery.ajax navigates to, to supposedly be able to delete the the database row containing the file name:

 <?php

...

    //I have connected to database

    $cancel_image_file_name = $_GET["imagefilename"];

            $imagecancelsql = "DELETE FROM Image 
            WHERE ImageFile = 'ImageFiles/". mysql_real_escape_string($cancel_image_file_name)."'";

        mysql_query($imagecancelsql);

        mysql_close();


    ?>

UPDATE:

Below is what it currently shows when I echo the delete query:

Notice: Undefined index: imagefilename in /web/stud/xxx/.../cancelimage.php on line 19 DELETE FROM Image WHERE ImageFile = 'ImageFiles/'

Below is the code of the delete function where when the Delete Button is pressed, it will navigate to the deleteimage.php script and delete the database row:

function stopImageUpload(success, imagefilename){

         $('.listImage').eq(window.lastUploadImageIndex).append('<div>' + htmlEncode(imagefilename) + '<button type="button" class="deletefileimage" image_file_name="' + imagefilename + '">Remove</button><br/><hr/></div>'); 

$('.listImage').eq(window.lastUploadImageIndex).find(".deletefileimage").on("click", function(event) {
    var image_file_name = $(this).attr('image_file_name');

    jQuery.ajax("deleteimage.php?imagefilename=" + image_file_name)

    $(this).parent().remove();
});

      return true;   
}

Below is deleteimage.php script:

<?php

//connected to DB

  $image_file_name = $_GET["imagefilename"];

        $imagedeletesql = "DELETE FROM Image 
        WHERE ImageFile = 'ImageFiles/". mysql_real_escape_string($image_file_name)."'";

    mysql_query($imagedeletesql);

    mysql_close();


?>

Below is an UPDATE of what the cancel button function now looks like:

function startImageUpload(imageuploadform, imagefilename){
            $('.imagef1_cancel').eq(window.lastUploadImageIndex).find(".imageCancel").on("click", function(event) {

var cancel_image_file_name_ = $(this).attr('css');
var cancel_image_file_name = '';
var style_array = cancel_image_file_name_.split(" ");
for(i=0;i<style_array.length;i++){
    if(style_array[i].substr(0,2) == "__"){
     cancel_image_file_name = style_array[i].slice(2,style_array[i].length-2);
}

}

    jQuery.ajax("cancelimage.php?imagefilename=" + cancel_image_file_name)

    return stopImageUpload(2, cancel_image_file_name);

});       
      return true;
}

I changed the button input tag to this for cancel button:

<input type='button' name='imageCancel' class='imageCancel __"+ imagefilename + "' value='Cancel' />

Try these changes:

on form:

<input type='button' name='imageCancel' class='imageCancel __"+ imagefilename + "' value='Cancel' /></label></form>

on cancel button function:

var cancel_image_file_name_ = $(this).attr('class');
var cancel_image_file_name = '';
var style_array = cancel_image_file_name_.split(" ");
for(i=0;i<style_array.length;i++){
    if(style_array[i].substr(0,2) == "__"){
     cancel_image_file_name = style_array[i].slice(2,style_array[i].length);
}

}

Secure storage of database credentials

4 votes

Had a major problem recently where my web hosting company messed up and all my php files were displayed in plain text. This was a major issue for me for obvious reasons. Mainly because mysql database details were exposed.

I am now trying to change the way in which my php files get the login information for the database so that this will never happen again even if the hosting company fail me.

my current set up looks like this :

     include 'info.php';

    class Login {

var $host;
var $username;
var $password;
var $db;
var $url;

Inside the info.php is the username, password and so on for the database. I want to make it so that the info.php file can never be viewed and only my .php files are able to access info.php in order to get the login infomation.

How can i set this up? This is a bit of a tricky one for me to explain so please dont be harsh and -1 me for a bad description.. just ask and i will clear up any gaps in my description.

Simply place info.php outside your webroot. This way, you can include it, but should your web hosting f*#$ up, no one else can view that file, even as plain text.

You would then include it like this:

include('../info.php');

This way, even if someone finds out that you have a file called info.php that stores all your passwords, they cannot point their browser to that file.

The above would be the ideal and most watertight solution. However, if that is not possible due to permissions, the other option would be to place all sensitive files in a directory and block direct access to that directory using a .htaccess file.

In the directory you want to block off access to, place an .htaccess file with the following contents:

deny from all