Navarr's Tech Side The Technical Side of my Life

26Jun/110

Programs I Want to See Made Into (Browser) Web Applications

Filed under: General No Comments
10Apr/114

YouTube Audio Player

While I was procrastinating on my essay for GSW, I’ve made a couple slight changes to the YouTube Audio Player that should make it a little better.

Firstly, I’ve given you the ability to allow YouTube to set cookies.  I’m not sure why anyone would be interested in doing this for a Music player, but its there.  I guess the primary reason I set this is because youtube-nocookie wasn’t working properly the other day, as I soon found out from a comment on my blog.  So if it isn’t showing up, you should allow YouTube to collect cookies.

The second, and by far the more important change is embedding the link (in the event that neither the object nor the embed shows) in a <noembed> tag.  I’m not quite sure how I didn’t know about the existence of this tag, but I’ve gone ahead and programmed it in properly, which should get rid of the annoying duplication some users have been seeing on any players generated from this point forward.

And one last change I made while working on this blog post, I created an API!  So now you can generate them on the fly if you want to and get just the HTML for the player.  I’ll document the API below:

http://www.gtaero.net/ytmusic/?api=1

  • &q=
    • The URL to the YouTube Video or Playlist
  • &a=1
    • Only Add if you want the music to AutoPlay
  • &loop=1
    • Only Add if you want the music to Loop
  • &js=1
    • Only Add if you want to be able to use the JavaScript API with it
  • &s=on
    • Add if you want to enable the Progress Bar on the video.
    • &psize= This is the progress bar size, acceptable variables are below
      • s – Small, This will set the width of the video to 150px
      • m – Medium, This will set the width of the video to 187px
      • l – Large, This will set the width of the video to 224px
      • &tc =1
        • Only Add if you also want to show a timecode.  Only works with progress bar.  Changes the follow sizes to the corresponding pixels:
        • s – 225px
        • m – 262px
        • l – 299px
  • &invis=1
    • Add if you want to make the player invisible.  Note: People hate this.
  • &html5=1
    • Add if you want to use YouTube’s HTML5 player. You shouldn’t use this.  Its VERY buggy.
  • &cookie=1
    • Add if you’re okay with YouTube setting cookies on the user’s computer.

And that’s all!  Enjoy!

9Apr/111

Something Chrome Needs

There is a very common type of extension for Google Chrome, and that happens to be the “Notifier” type.

You have GMail Notifiers, Google Voice Notifiers, Google Reader, Google Docs, OWA, Facebook, Twitter, etc etc.  Wouldn’t it be nice if Google Chrome just had a single Notification Center with a fantastic User Interface for showing notifications from whatever services register themselves with it?

I think it would, and over the summer – if I have spare time – I think I’m going to program an extension that will can accept additions for showing notifications.  I’ll then ask around for help and/or program some basic services for it to use, and post it to the Chrome WebApp Store.

My next questions are:

  • Would you use this?  Is it a good idea?
  • Would you code for this?
  • Would you purchase this for $1?

At the moment, I’ve got plenty of cool programming projects, and I’m not making money with any of them.  GVOMS is almost entirely free (no companies have purchased a license to use), and anything else I’ve done so far has been free and open source.

So unless people are going to start donating to me – which I’m pretty sure you aren’t – I need to find some way to make money.  I’m a college student, after all.

And I don’t think $1 would be too much to ask for a unified notification center in Google Chrome, do you?

5Mar/110

Why I hate Terminal on Macs

Ugh.  Just ugh.  I had a lab in my Computer Science 202 class today.  The computer I sat down to was already booted into Mac OS X, and I didn’t want to restart it just to get into Windows, so I just logged in and opened up terminal since I’d be doing the whole thing over SSH anyways.  I should have basically the same experience, right?

Wrong.  So wrong its insane.

I had pleasantly forgotten that even when using SSH terminal doesn’t send nice commands like “Pg Up” and “Pg Dwn” to the server, nor does it send “End” for some reason.  I can’t remember, but I’m also pretty sure it refuses to send “Home” as well.

This is why I hate working on a Mac.

Filed under: Apple, Mac No Comments
31Dec/100

A Desired Feature for Cydia

I’m not really a gigantic apple fan, but thanks to my parents and the art of Hand-Me-Downs I managed to acquire an iPhone 3G.

I’ve been using this 3G for awhile, and of course one of the things I absolutely had to do with it was Jailbreak the device.  I don’t pirate or anything, but Jailbreaking it does bring fantastic changes to it that simply would not have been possible on the 3G otherwise.

For example, I use Z-Toggle and Bootlace: Z-Toggle for activating nice little features (Background Wallpaper, Battery Percentage) and Bootlace for giving me Android as an optional boot-method (iDroid is far from completion, though), and I just now finished installing and modifying the settings for Backgrounder, since 4.2 broke native multi-tasking on the old 3G device (I have no idea why), and I’ve already got accustomed to using it.

But there is one problem with Cydia I don’t believe has been addressed yet, and it would be nice if Cydia were to automatically store your custom sources and a list of the programs you’ve installed, so that when you re-install a new iOS (by starting from scratch so that you don’t continually lose space on your iPhone) and re-jailbreak your device, it sees the file and also helps convert your iPhone back to the jailbroken way it was.

This would be a very nice feature, and one I’m sure anyone would welcome.

Filed under: Cydia, iPhone No Comments
27Dec/105

A “Revolutionary” Way to Validate Email Input

I’m not talking about confirming email, where you have to make sure that the user owns an email address, but I am talking about a way to confirm that an email entered will probably work WITHOUT succumbing to regex, AND it’s relatively quick!

function validate_email($email)
{
	$email_parts = explode("@",$email);
	if(count($email_parts)) != 2) { return FALSE; } // You can only have one @ in an email address.
	$domain = $email_parts[1];
	if(!getmxrr($domain,$array)) { return FALSE; } // This domain doesn't have any MX Records.
	return TRUE; // Everything else is 'valid.'
}
Filed under: PHP 5 Comments
9Nov/100

Making More Natural Desktop Notifications in Chrome

Do you have a website or application that uses Google Chrome Desktop Notifications?  Well, let me just share with you this very simple snippit of code that will make their interaction a lot more natural.

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<style>
		html * { font-family: sans-serif; }
		h1 { padding: 0; margin: 0; font-size: 12pt; font-weight: bold; }
		body { font-size: 10pt; }
	</style>
	<script>
		function changeLinks() { for(var i = 0;i < document.getElementsByTagName("a").length;i++) { ele = document.getElementsByTagName("a")[i]; ele.target = "_blank"; } }
		function detectClick(e) { var rightclick; if (!e) { var e = window.event; } if (e.which) { rightclick = (e.which == 3); } else if (e.button) { rightclick = (e.button == 2); } if (rightclick) { self.close(); } }
	</script>
</head>
<body onload="document.timeout = setTimeout(self.close,5000);changeLinks();" onmouseover="clearTimeout(document.timeout);" onmouseout="document.timeout = setTimeout(self.close,5000);" onmouseup="detectClick();">
	<a style="display:block;cursor:normal;padding:0;margin:0;color:black;text-decoration:none;" onclick="self.close();" href="/link/" target="_blank">
		<h1>Title</h1>
		<span>Message</span>
	</a>
</body></html>

Thats really all there is to it. Lives on a 5 second time. If you hover over it, it stays longer, if you right click it it closes. If you click it it goes to /link/. Quite nifty, if I do say so myself.

Its slightly buggy regarding links in the message.. but meh.

4Nov/100

Give your Flip Cam an Icon on Windows

imageDid you delete all the files on your flip cam at least once?  Or do you not like that FlipShare icon that always shows up whenever you plug your FlipCam into your Windows computer?  Well, until the nice people over at Cisco decide to support Windows 7 Device Stage for their FlipCam line, you can at least come half way and make sure your camera has a nice little icon.

This is pretty easy, and as long as you’re not depending on the autorun.inf to open FlipShare every time you plug your Flip Camera in (and if you’re reading this blog, I’m 90% sure you aren’t), you can just copy the contents of the Flip Icon Zip File to the base directory of your Flip Cam, and it will start showing up in Auto Play (if enabled) and Windows Explorer with this very lovely, very high resolution icon created by Tim Van Damme.

For a preview of what this looks like in Windows Explorer:

image6

1Jul/107

How to create a socket server in PHP

class::SocketServer

EDIT: If you need to submit bugs or want to improve my work, its now available on github!

Ever tried searching for information on how to properly create a multi-client socket server in PHP?  You’ll get plenty of results with outdated and messy source code, some of which won’t even work.

This was the my state a couple days ago when I decided that I wanted to build an IRC server.  The why is not important… (For the fun of building an IRC Server).  So I googled around a hell of a lot bit until I finally found some code that worked on its own, and quickly built a semi-functional IRC server using it, and headed off to sleep at 5am.

The next day I was very, very happy with the results of my hard labor, but it wasn’t good enough, so I started re-writing it from scratch as an Object, and thus I created class::IRCServer.

Today, once I felt that I was finished screwing around with my newly built IRCd, I decided to modify the function enough to be used on its own as a socket server, to share with the world.

And thus, class::SocketServer was created.

< ?php
	/*!	@class		SocketServer
		@author		Navarr Barnier
		@abstract 	A Framework for creating a multi-client server using the PHP language.
	 */
	class SocketServer
	{
		/*!	@var		config
			@abstract	Array - an array of configuration information used by the server.
		 */
		protected $config;
 
		/*!	@var		hooks
			@abstract	Array - a dictionary of hooks and the callbacks attached to them.
		 */
		protected $hooks;
 
		/*!	@var		master_socket
			@abstract	resource - The master socket used by the server.
		 */
		protected $master_socket;
 
		/*!	@var		max_clients
			@abstract	unsigned int - The maximum number of clients allowed to connect.
		 */
		public $max_clients = 10;
 
		/*!	@var		max_read
			@abstract	unsigned int - The maximum number of bytes to read from a socket at a single time.
		 */
		public $max_read = 1024;
 
		/*!	@var		clients
			@abstract	Array - an array of connected clients.
		 */
		public $clients;
 
		/*!	@function	__construct
			@abstract	Creates the socket and starts listening to it.
			@param		string	- IP Address to bind to, NULL for default.
			@param		int	- Port to bind to
			@result		void
		 */
		public function __construct($bind_ip,$port)
		{
			set_time_limit(0);
			$this->hooks = array();
 
			$this->config["ip"] = $bind_ip;
			$this->config["port"] = $port;
 
			$this->master_socket = socket_create(AF_INET, SOCK_STREAM, 0);
			socket_bind($this->master_socket,$this->config["ip"],$this->config["port"]) or die("Issue Binding");
			socket_getsockname($this->master_socket,$bind_ip,$port);
			socket_listen($this->master_socket);
			SocketServer::debug("Listenting for connections on {$bind_ip}:{$port}");
		}
 
		/*!	@function	hook
			@abstract	Adds a function to be called whenever a certain action happens.  Can be extended in your implementation.
			@param		string	- Command
			@param		callback- Function to Call.
			@see		unhook
			@see		trigger_hooks
			@result		void
		 */
		public function hook($command,$function)
		{
			$command = strtoupper($command);
			if(!isset($this->hooks[$command])) { $this->hooks[$command] = array(); }
			$k = array_search($function,$this->hooks[$command]);
			if($k === FALSE)
			{
				$this->hooks[$command][] = $function;
			}
		}
 
		/*!	@function	unhook
			@abstract	Deletes a function from the call list for a certain action.  Can be extended in your implementation.
			@param		string	- Command
			@param		callback- Function to Delete from Call List
			@see		hook
			@see		trigger_hooks
			@result		void
		 */
		public function unhook($command = NULL,$function)
		{
			$command = strtoupper($command);
			if($command !== NULL)
			{
				$k = array_search($function,$this->hooks[$command]);
				if($k !== FALSE)
				{
					unset($this->hooks[$command][$k]);
				}
			} else {
				$k = array_search($this->user_funcs,$function);
				if($k !== FALSE)
				{
					unset($this->user_funcs[$k]);
				}
			}
		}
 
		/*!	@function	loop_once
			@abstract	Runs the class's actions once.
			@discussion	Should only be used if you want to run additional checks during server operation.  Otherwise, use infinite_loop()
			@param		void
			@see		infinite_loop
			@result 	bool	- True
		*/
		public function loop_once()
		{
			// Setup Clients Listen Socket For Reading
			$read[0] = $this->master_socket;
			for($i = 0; $i < $this->max_clients; $i++)
			{
				if(isset($this->clients[$i]))
				{
					$read[$i + 1] = $this->clients[$i]->socket;
				}
			}
 
			// Set up a blocking call to socket_select
			if(socket_select($read,$write = NULL, $except = NULL, $tv_sec = 5) < 1)
			{
			//	SocketServer::debug("Problem blocking socket_select?");
				return true;
			}
 
			// Handle new Connections
			if(in_array($this->master_socket, $read))
			{
				for($i = 0; $i < $this->max_clients; $i++)
				{
					if(empty($this->clients[$i]))
					{
						$temp_sock = $this->master_socket;
						$this->clients[$i] = new SocketServerClient($this->master_socket,$i);
						$this->trigger_hooks("CONNECT",$this->clients[$i],"");
						break;
					}
					elseif($i == ($this->max_clients-1))
					{
						SocketServer::debug("Too many clients...   ");
					}
				}
 
			}
 
			// Handle Input
			for($i = 0; $i < $this->max_clients; $i++) // for each client
			{
				if(isset($this->clients[$i]))
				{
					if(in_array($this->clients[$i]->socket, $read))
					{
						$input = socket_read($this->clients[$i]->socket, $this->max_read);
						if($input == null)
						{
							$this->disconnect($i);
						}
						else
						{
							SocketServer::debug("{$i}@{$this->clients[$i]->ip} --> {$input}");
							$this->trigger_hooks("INPUT",$this->clients[$i],$input);
						}
					}
				}
			}
			return true;
		}
 
		/*!	@function	disconnect
			@abstract	Disconnects a client from the server.
			@param		int	- Index of the client to disconnect.
			@param		string	- Message to send to the hooks
			@result		void
		*/
		public function disconnect($client_index,$message = "")
		{
			$i = $client_index;
			SocketServer::debug("Client {$i} from {$this->clients[$i]->ip} Disconnecting");
			$this->trigger_hooks("DISCONNECT",$this->clients[$i],$message);
			$this->clients[$i]->destroy();
			unset($this->clients[$i]);
		}
 
		/*!	@function	trigger_hooks
			@abstract	Triggers Hooks for a certain command.
			@param		string	- Command who's hooks you want to trigger.
			@param		object	- The client who activated this command.
			@param		string	- The input from the client, or a message to be sent to the hooks.
			@result		void
		*/
		public function trigger_hooks($command,&$client,$input)
		{
			if(isset($this->hooks[$command]))
			{
				foreach($this->hooks[$command] as $function)
				{
					SocketServer::debug("Triggering Hook '{$function}' for '{$command}'");
					$continue = call_user_func($function,$this,$client,$input);
					if($continue === FALSE) { break; }
				}
			}
		}
 
		/*!	@function	infinite_loop
			@abstract	Runs the server code until the server is shut down.
			@see		loop_once
			@param		void
			@result		void
		*/
		public function infinite_loop()
		{
			$test = true;
			do
			{
				$test = $this->loop_once();
			}
			while($test);
		}
 
		/*!	@function	debug
			@static
			@abstract	Outputs Text directly.
			@discussion	Yeah, should probably make a way to turn this off.
			@param		string	- Text to Output
			@result		void
		*/
		public static function debug($text)
		{
			echo("{$text}\r\n");
		}
 
		/*!	@function	socket_write_smart
			@static
			@abstract	Writes data to the socket, including the length of the data, and ends it with a CRLF unless specified.
			@discussion	It is perfectly valid for socket_write_smart to return zero which means no bytes have been written. Be sure to use the === operator to check for FALSE in case of an error.
			@param		resource- Socket Instance
			@param		string	- Data to write to the socket.
			@param		string	- Data to end the line with.  Specify a "" if you don't want a line end sent.
			@result		mixed	- Returns the number of bytes successfully written to the socket or FALSE on failure. The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.
		*/
		public static function socket_write_smart(&$sock,$string,$crlf = "\r\n")
		{
			SocketServer::debug("< -- {$string}");
			if($crlf) { $string = "{$string}{$crlf}"; }
			return socket_write($sock,$string,strlen($string));
		}
 
		/*!	@function	__get
			@abstract	Magic Method used for allowing the reading of protected variables.
			@discussion	You never need to use this method, simply calling $server->variable works because of this method's existence.
			@param		string	- Variable to retrieve
			@result		mixed	- Returns the reference to the variable called.
		*/
		function &__get($name)
		{
			return $this->{$name};
		}
	}
 
	/*!	@class		SocketServerClient
		@author		Navarr Barnier
		@abstract	A Client Instance for use with SocketServer
	 */
	class SocketServerClient
	{
		/*!	@var		socket
			@abstract	resource - The client's socket resource, for sending and receiving data with.
		 */
		protected $socket;
 
		/*!	@var		ip
			@abstract	string - The client's IP address, as seen by the server.
		 */
		protected $ip;
 
		/*!	@var		hostname
			@abstract	string - The client's hostname, as seen by the server.
			@discussion	This variable is only set after calling lookup_hostname, as hostname lookups can take up a decent amount of time.
			@see		lookup_hostname
		 */
		protected $hostname;
 
		/*!	@var		server_clients_index
			@abstract	int - The index of this client in the SocketServer's client array.
		 */
		protected $server_clients_index;
 
		/*!	@function	__construct
			@param		resource- The resource of the socket the client is connecting by, generally the master socket.
			@param		int	- The Index in the Server's client array.
			@result		void
		 */
		public function __construct(&$socket,$i)
		{
			$this->server_clients_index = $i;
			$this->socket = socket_accept($socket) or die("Failed to Accept");
			SocketServer::debug("New Client Connected");
			socket_getpeername($this->socket,$ip);
			$this->ip = $ip;
		}
 
		/*!	@function	lookup_hostname
			@abstract	Searches for the user's hostname and stores the result to hostname.
			@see		hostname
			@param		void
			@result		string	- The hostname on success or the IP address on failure.
		 */
		public function lookup_hostname()
		{
			$this->hostname = gethostbyaddr($this->ip);
			return $this->hostname;
		}
 
		/*!	@function	destroy
			@abstract	Closes the socket.  Thats pretty much it.
			@param		void
			@result		void
		 */
		public function destroy()
		{
			socket_close($this->socket);
		}
 
		function &__get($name)
		{
			return $this->{$name};
		}
 
		function __isset($name)
		{
			return isset($this->{$name});
		}
	}

class::SocketServer does all the functions necessary for a server.  It binds to the IP address and starts listening to the port.  Its easy to specify a maximum number of clients to allow, and the way its coded makes it easily modified.

Here is an example of a server (using this class) that listens for a user to send a string, and then echoes the reverse of that string back to the user.

< ?php
	// This is PHP5 Code, by the way.
 
	require_once("SocketServer.class.php"); // Include the Class File
	$server = new SocketServer(null,31337); // Create a Server binding to the default IP address (null) and listen to port 31337 for connections
	$server->max_clients = 10; // Allow no more than 10 people to connect at a time
	$server->hook("CONNECT","handle_connect"); // Run handle_connect everytime someone connects
	$server->hook("INPUT","handle_input"); // Run handle_input whenever text is sent to the server
	$server->infinite_loop(); // Run Server Code Until Process is terminated.
 
	/*
	 * All hooked functions are sent the parameters $server (The server class), $client (the connection), and $input (anything sent, if anything was sent)
	 * You should save the variables $server and $client using an ampersand (&) to make sure they are references to the objects and not duplications.
	 */
	function handle_connect(&$server,&$client,$input)
	{
		SocketServer::socket_write_smart($client->socket,"String? ",""); // Outputs 'String? ' without a Line Ending
	}
	function handle_input(&$server,&$client,$input)
	{
		$trim = trim($input); // Trim the input, Remove Line Endings and Extra Whitespace.
 
		if(strtolower($trim) == "quit") // User Wants to quit the server
		{
			SocketServer::socket_write_smart($client->socket,"Oh... Goodbye..."); // Give the user a sad goodbye message, meany!
			$server->disconnect($client->server_clients_index); // Disconnect this client.
			return; // Ends the function
		}
 
		$output = strrev($trim); // Reverse the String
 
		SocketServer::socket_write_smart($client->socket,$output); // Send the Client back the String
		SocketServer::socket_write_smart($client->socket,"String? ",""); // Request Another String
	}

In essence, this class allows you to handle sockets in PHP. Beautifully handle sockets in PHP, that is.

28Jun/101

Magical Typesetting in PHP

So, well working for Route 50 I came up with a fantastic idea for “typesetting” that well exceeded the norm.  Something we constantly have issues with is what type of string was sent to MySQL originally (some of us have different conventional ideas about where escaping HTML should be located.) as well as outputting that string in its correct format.

Me, with my fantastic idea, came up with a couple variables classes that I put in a file named class_typesetting.php.  The version on gist.github is slightly modified from the original version on the server.

It creates three classes, GenericVariable, String, and Number.  So far we haven’t used GenericVariable, but since the introduction of the classes I’ve taken it upon myself to introduce them to any new code I write.  When we create Core v5 (which will Objectify everything) strings taken from SQL will automatically be re-stored as String class variables.

First, lets examine some useful functionality.

<?php
$title = new String($_POST[“title”]); // <strong>Hello 'World'</strong>
?>
HTML Output: <?= $title->html ?> (&lt;strong&gt;Hello 'World'&lt;/strong&gt;)
Text Output: <?= $title->text ?> (Hello 'World')
SQL Output: <?= $title->sql ?> (<strong>Hello \'World\'</strong>)
HTML Attribute Output: <?= $title->html_attr ?>(&lt;strong&gt;Hello &#039;World&#039;&lt;/strong&gt;)

This allows for quick and easy access to the variables without having to worry about escaping them.

I recommend you hit the download link (class_typesetting.php) and play around with it.  Tell me about anything that’s not working correctly and if possible implement it in your future code.  (This means I’m putting this code in the “Public Domain”).