Category: Programming

Converting DateTime.Ticks into a Unix timestamp in PHP

November 30, 2010 at 11:46 PM

I needed a way to convert the number of ticks from the DateTime.Ticks property in .NET into a Unix timestamp in PHP. So I wrote up this solution that makes this possible. The solution works by taking the number of ticks that I want to convert into a Unix timestamp and subtracting it with the number of ticks of the Unix epoch.

To figure out the number of ticks of the Unix epoch, I used C# (it is possible to do this in a different .NET language) using these two lines of code to find the number of ticks of the Unix epoch in a simple Console Application:

DateTime unix = new DateTime(1970, 1, 1, 0, 0, 0);
System.Console.WriteLine(unix.Ticks);

This ends up printing out:
621355968000000000

I then took this number, which is in one hundred nanoseconds, and created a PHP function which subtracts the number of ticks to be converted by the number of ticks of the Unix epoch and then divides it by 10000000 to convert the now Unix timestamp from one hundred nanoseconds to seconds as Unix timestamps in PHP are handled in seconds.

function ticks_to_time($ticks) {
	return floor(($ticks - 621355968000000000) / 10000000);
}

This is an example of this function in use:

// 11/24/2010 9:20:45 PM UTC in DateTime.Ticks
$time = ticks_to_time(634262304450000000);
echo "$time\n";
echo date("F j Y g:i:s A T", $time) . "\n";

Which should output:
1290633645
November 24 2010 1:20:45 PM PST

So there we have it, a function that makes it easy to convert the number of ticks from the DateTime.Ticks property in .NET into a Unix timestamp in PHP.

How to Revert Your SVN Repository on Assembla

July 24, 2010 at 11:36 PM

There is no simple way to revert your repository to a previous revision on Assembla. However, a reversion is possible by following these steps.

First, export the SVN repository in your space. This can be done under the Import/Export section of your repository. It’ll take a minute for the dump to be created. Once that has completed, download the repository dump.

Then, extract the contents of the ZIP file to a temporary directory, then run the following commands in the temporary directory:

svnadmin create REPO_NAME
svnadmin load REPO_NAME < rXX.dump
svnadmin dump -r 1:YY REPO_NAME --incremental > rYY.dump
gzip rYY.dump

Replace XX with the current revision of your repository, YY with the revision you wish to revert to, and REPO_NAME with any name, such as your repository’s name. This name will not be carried over later.

Afterwards, delete the repository tool on Assembla by going to Admin -> Tools, then clicking Delete next to it which is located on the right. Now re-add the Source/SVN repository tool.

Finally, import the dump to the newly created repository by going to the Import/Export section and uploading the gzipped SVN dump. The process will take from a few to several minutes depending on how large your repository is.

Your repository should now be reverted back to the revision you specified.

There is no simple way to revert your repository to a previous revision on Assembla. However, a reversion can be done following these steps.

First, export the SVN repository in your space. This can be done under the Import/Export section of your repository. It’ll take a minute for the dump to be created. Once that’s finished download the dump.

Then, extract the contents of the ZIP file to a temporary directory, then run the following commands in the temporary directory:

svnadmin create REPO_NAME
svnadmin load REPO_NAME < rXX.dump
svnadmin dump -r 1:YY REPO_NAME --incremental > rYY.dump
gzip rYY.dump

Replace XX with the current revision of your repository, YY with the revision you wish to revert to, and REPO_NAME with whatever you like. The temporary repository name will not be carried over.

Afterward, delete the repository on Assembla by going to Admin -> Tools, then Delete it on the right. Now re-add the Source/SVN repository.

Finally, import the dump to the newly created repository by going to the Import/Export section and uploading the gzipped SVN dump. The process will take a few to several minutes depending on how big your repository is.

You’re repository should now be reverted.

Outputting A to ZZZ in PHP

June 23, 2010 at 8:21 PM

Here is a way to output from A to ZZZ in PHP. There are probably better ways to do this but it works. I wasn’t able to find an example written in PHP that would do this so I wrote my own. I’m not sure if there is any use that this code will provide as it is mainly just a proof of concept.

<?php
$letters = range('a', 'z');

for ($a = 0; $a < 78; $a++)
{
	if ($a >= 26)
	{
		if ($a >= 52)
		{
			// AAA to ZZZ
			$orig_letter = $letters[$a - 52];
			for ($b = 0; $b < 26; $b++)
			{
				$orig_letter2 = $orig_letter . $letters[$b];

				for ($c = 0; $c < 26; $c++)
				{
					$letter = $orig_letter2 . $letters[$c];
					echo "$letter\n";
				}
			}
		}
		else
		{
			// AA to ZZ
			$orig_letter = $letters[$a - 26];
			for ($b = 0; $b < 26; $b++)
			{
				$letter = $orig_letter . $letters[$b];
				echo "$letter\n";
			}
		}
	}
	else
	{
		// A to Z
		$letter = $letters[$a];
		echo "$letter\n";
	}
}

Login By Username On MySpace By Emulating iPhone Login

October 31, 2009 at 8:16 PM

One day I was logging onto MySpace using the iPhone app, I was curious to try using my username (it’s your vanity URL, if not set it’s your Friend ID), and it worked. Now I’m not sure why MySpace freaks out over being able to login by the username because Facebook intentionally allowed logging in by username earlier this month.

Since this login works on the iPhone/iPod Touch, there has to be a way to bring it to the computer in order to use this method. Since my router is pretty much a Linux server running DHCP on it, I could easily run a packet sniffer in the middle to find out how the iPhone/iPod Touch was communicating to MySpace. The packet sniffer I used was shell based and is called Justniffer.

After figuring out the packet sniffer I figured out that the iPhone app uses SOAP+XML to exchange data. Once you type in the username and password, it sends the password in clear text to MySpace in order to create a hash and salt of the password. I am not sure why they really need to do this since you already sent the password over clear text, they could just save themselves a HTTP request by doing it in the actually login process.

Update 11/5: MySpace has fixed this issue and logging in by username no longer works. The following error now occurs, “The email supplied is not registered to a valid user.”

The first step of the authentication request makes the following HTTP request:

POST /SecurityService.asmx HTTP/1.1
Host: mobileservices.myspace.com
User-Agent: MySpace/1.6 CFNetwork/459 Darwin/10.0.0d3
Content-Length: 595
Content-Type: text/xml; charset=utf-8
Authorization: OAuth realm="http://mobileservices.myspace.com/",oauth_consumer_key="1000002",oauth_token="",oauth_signature_method="HMAC-SHA1",oauth_signature="MC37B2CcYBDeJPlT%2BT1jsjCZPSM%3D",oauth_timestamp="1256437313",oauth_nonce="9EC617B6-DEB7-427A-9463-B6AE3CFD8F4A",oauth_version="1.0"
Soapaction: urn:MySpace.IntegrationServices/GetSaltAndHash
Accept: */*
Accept-Language: en-us
Cookie: SessionDDF1=2962622b49c74a011793142740791e622b72e026b3477387; SessionDDF2=22b8f3a96cb338ae3990d279b29cefa01e58e2c5118f4486
Connection: keep-alive

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<MySpace xmlns="urn:MySpace.IntegrationServices">
<Version>iPhone: 1.6</Version>
<DeviceID>b6aaa9591ef5811e499ee1bf04758b3533eaccd7</DeviceID>
</MySpace>
</soap12:Header>
<soap12:Body>
<GetSaltAndHash xmlns="urn:MySpace.IntegrationServices">
<request>
<TokenType>Mobile</TokenType>
<Clear>p@ssw0rd</Clear>
</request>
</GetSaltAndHash>
</soap12:Body>
</soap12:Envelope>

In this example the password simply is p@ssw0rd. Notice how there is no spot for the username in this request, all it does is create a salt and hash based on that password. I have no idea why this is necessary but knowing MySpace they obviously think it is.

This request will outcome the following HTTP response:

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 547
Content-Type: application/soap+xml; charset=utf-8
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
X-Server: 7b262264f255ce9e4eea78ee5ed43e765b933575b6ad33d5
Set-Cookie: SessionDDF1=8c39718f6f8758c74900ce98793335c96e886d8666f52130; domain=.myspace.com; path=/
Date: Sun, 01 Nov 2009 02:52:01 GMT
Connection: keep-alive

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetSaltAndHashResponsexmlns="urn:MySpace.IntegrationServices">
<Results>
<Status>Success</Status>
<StatusCode>Success</StatusCode>
<SecurityComponents>
<Salt>Q8NysHYF/cKqV/+RES0NdA==</Salt>
<Hash>N+HrTQhAJencbKruQ2e8/qDKhELcJDq824aoSYzl5MA=</Hash>
</SecurityComponents>
</Results>
</GetSaltAndHashResponse>
</soap:Body>
</soap:Envelope>

Now since they have received the salt and hash, we can proceed onto step two of the authentication. This actually verifies the login information with the salt and hash along with the username or email it has received. This step makes the following HTTP request:

POST /SecurityService.asmx HTTP/1.1
Host: mobileservices.myspace.com
User-Agent: MySpace/1.6 CFNetwork/459 Darwin/10.0.0d3
Content-Length: 858
Content-Type: text/xml; charset=utf-8
Authorization: OAuth realm="http://mobileservices.myspace.com/",oauth_consumer_key="1000002",oauth_token="",oauth_signature_method="HMAC-SHA1",oauth_signature="L3vOxtNAADDGBRv2i16UvMoP97g%3D",oauth_timestamp="1256437314",oauth_nonce="E493D130-9496-4A17-A861-5862C657DF57",oauth_version="1.0"
Soapaction: urn:MySpace.IntegrationServices/Authenticate
Accept: */*
Accept-Language: en-us
Cookie: SessionDDF1=2962622b49c74a011793142740791e622b72e026b3477387; SessionDDF2=22b8f3a96cb338ae3990d279b29cefa01e58e2c5118f4486
Connection: keep-alive

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<MySpace xmlns="urn:MySpace.IntegrationServices">
<Version>iPhone: 1.6</Version>
<DeviceID>b6aaa9591ef5811e499ee1bf04758b3533eaccd7</DeviceID>
</MySpace>
</soap12:Header>
<soap12:Body>
<Authenticate xmlns="urn:MySpace.IntegrationServices">
<request>
<RequestData>
<Hash>N+HrTQhAJencbKruQ2e8/qDKhELcJDq824aoSYzl5MA=</Hash>
<CaptchaInfo>
<CaptchaLevel>Medium</CaptchaLevel>
<CaptchaGuid></CaptchaGuid>
<CaptchaImageSize>Sz120</CaptchaImageSize>
<CaptchaText></CaptchaText>
</CaptchaInfo>
<Salt>Q8NysHYF/cKqV/+RES0NdA==</Salt>
<Credential>somerandomusername</Credential>
</RequestData>
</request>
</Authenticate>
</soap12:Body>
</soap12:Envelope>

In this request we have used the hash and salt, along with the username which is called Credential here. In this example it is somerandomusername. Now since this is all sent the following HTTP response occurs:

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 566
Content-Type: application/soap+xml; charset=utf-8
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
X-Server: 12e0f2a61ef7e974de69e6f93fc8612bb56e8a9e86e1792c
Set-Cookie: SessionDDF1=ee28a6c308e5ab151a34f39f979df9e80737ca2a9eeb80d7; domain=.myspace.com; path=/
Date: Sun, 01 Nov 2009 02:59:28 GMT
Connection: keep-alive

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<AuthenticateResponse xmlns="urn:MySpace.IntegrationServices">
<AuthenticateResult>
<StatusMessage>Invalid username or password.</StatusMessage>
<Status>Error</Status>
<ErrorInfo>
<Name>InvalidCredentials</Name>
<Description>Invalid username or password.</Description>
</ErrorInfo>
</AuthenticateResult>
</AuthenticateResponse>
</soap:Body>
</soap:Envelope>

Since the the password to somerandomusername is invalid, we are presented with “Invalid username or password.” I honestly do not understand why there needs to be a creation of the salt and hash before the actual authentication request is made.

Now since I know how the requests are made, I’ve wrote a program to emulate these requests. The program was created with Eclipse using Java 1.6.

The program can be downloaded here.
The source code is included and the program may be modified and redistributed freely.
DISCLAIMER: I am not liable for ANY damages caused by this program.

Here are screenshots of the program in use:

Usage
Arguments for the program.

LoginFail
Example of a failed login.

LoginLockedOut
Example of a failed login on a locked out account. Notice in the response it says “There was an error in processing this request.”

LoginSuccess
Example of a successful login.

Ruby on Rails Sucks? I Don’t Think So

August 15, 2009 at 4:55 PM

I have been playing around with Ruby on Rails for a while. You know how to program and know the commands for it, you’ll think it’s cool. Ruby on Rails is a MVC framework for the language Ruby. MVC stands for Model-View-Controller. The model is the database logic, the controller is the application logic, and the view is the presentation logic. Using this style, it keeps things organized.

People will think Ruby on Rails suck because they don’t know how to catch on to it. I admit, I was originally one of them, until I read Agile Web Development with Rails, Third Edition (Amazon). This book showed me how powerful this framework was and how much it was capable of doing. Doing validations is a breeze, embedding variables and Ruby code is a breeze in the views, routes are easy to configure (no .htaccess), database migrations to keep things in order, ActiveRecord to ease querying, updating, and inserting (no more SQL queries), and there’s so many other cool things with it. There is even loads of plugins on the Internet and on Github that do kickass things.

Does Ruby on Rails use a lot of RAM? From what I have notice from playing around with it I haven’t notice it take so much RAM. Besides, if I needed more RAM later and I was generating the money from the site, I’d just upgrade the server, piece of cake.

I plan on developing new sites using Ruby on Rails. PHP is just getting old (the new namespace delimiter is \, and that’s an escape character!)