Commits

Anonymous committed e7faa58

Initial import pingfire up to firefox 3.5

  • Participants

Comments (0)

Files changed (14)

+syntax: glob
+*.elc
+*.pyc
+*~
+*.orig
+*.log
+*.swp
+*.tmp
+*.DS_Store
+.DS_Store
+testdb.sqlite
+django
+local_settings.py
+*.pid
+*.db
+*.hdf.h5
+*.h5 
+
+syntax: regexp
+(.*/)?\#[^/]*\#$
+.*/.svn/*
+\.svn/
+
+content pingfire chrome/content/
+
+overlay chrome://browser/content/browser.xul chrome://pingfire/content/toolbar.xul
+
+locale pingfire en-US chrome/locale/en-US/
+
+skin pingfire classic/1.0 chrome/skin/
+
+style chrome://global/content/customizeToolbar.xul chrome://pingfire/skin/pingfire.css
+

chrome/content/post.xul

+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	id="pingfire-post-dialog" 
+	title="Post to Ping"
+	buttons="accept,cancel"
+	ondialogaccept="return post();"
+	ondialogcancel=""
+	onload="return loadPostDialog();"> 
+
+	<script type="application/x-javascript" src="chrome://pingfire/content/toolbar.js" />
+
+	
+	<hbox align="left">
+	
+		<label 
+			id="pf_pingmy_lbl" 
+			 width="100px;"
+			value="Ping My: "/>
+	
+		<menulist id="pf_pingmy_cbo">
+    		<menupopup id="pf_pingmy_pop">
+    			<menuitem label="Default" 	value="default"/>
+    			<menuitem label="Blog" 		value="blog"/>
+    			<menuitem label="Microblog"	value="microblog"/>
+    			<menuitem label="Status" 	value="status"/>
+    			<menuseparator/>
+    		</menupopup>
+  		</menulist>
+
+	
+	</hbox>
+	
+	<hbox align="center">
+    	<label id="pf_subject_lbl" width="100px;" value="Title: "/>
+    	<textbox 
+    		id="pf_subject_fld" 
+            maxlength="100" 
+    		width="300px;"
+    		oninput="charCount();"/>
+    	
+  	</hbox>
+	
+	<hbox align="center">
+    	<label id="pf_message_lbl" width="100px;" value="Message: "/>
+    	<textbox 
+    		id="pf_message_fld" 
+            maxlength="140" 
+    		multiline="true"
+    		width="300px;"
+    		oninput="charCount();"/>
+    	
+  	</hbox>
+  	
+  	<hbox align="right">
+  		<label 
+  			id="pf_message_length_fld" 
+  			align="right" 
+  			value="0 of 140 characters."/>
+  	</hbox>
+  	
+  	<hbox align="middle">
+  		<description style="font-weight:900;">
+  			Note: A "Title" is required when posting to a blog.
+  		</description>
+  	</hbox>
+
+
+
+</dialog>

chrome/content/preferences.xul

+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+	id="pingfire-preferences-dialog" 
+	title="Ping Fire Preferences"
+	buttons="accept,cancel"
+	ondialogaccept="return savePreferences();"
+	ondialogcancel=""
+	onload="return loadPreferences();"
+	minwidth="350"
+	minheight="300"
+	width="350"
+	height="300">
+
+<script type="application/x-javascript" src="chrome://pingfire/content/toolbar.js" />
+
+<hbox align="center">
+    <label id="pf_username_lbl" value="Username: "/>
+    <textbox id="pf_username_fld" maxlength="100"/>
+  </hbox>
+  <hbox align="center">
+    <label id="pf_password_lbl" value="Application Key: "/>
+    <textbox type="password" id="pf_password_fld" maxlength="200"/>
+  </hbox>
+  
+ 
+
+		<groupbox>
+			<caption label="Url shortener settings"/>
+			<grid>
+				<columns>
+					<column flex="4"/>
+					<column flex="1"/>
+				</columns>
+				<rows>
+					<row>
+						<label control="cur_url_short_lbl" value="Shortened current url on click"/>
+						<checkbox id="cur_url_short_fld" />
+					</row> 
+					<row>
+                        <menulist id="url_shortner">
+                          <menupopup>
+                            <menuitem label="tinyurl" value="tinyurl"/>
+                            <menuitem label="bit.ly " value="bitly"/>
+                          </menupopup>
+                        </menulist>
+                   
+                     </row>
+                        <row>
+     						<label control="bitly_api_lbl" value="bit.ly application key:"/>
+     						</row> 
+     						<row>
+     						<textbox id="bitly_api_fld" maxlength="100"/>
+     					</row>
+     					<row>
+     						<label control="bitly_login_lbl" value="bit.ly login:"/>
+     						</row> 
+     					 <row>
+     						<textbox id="bitly_login_fld" maxlength="100"/>
+     					</row>
+				</rows>
+			</grid>
+		</groupbox>	
+
+</dialog>

chrome/content/sample.xul

+<?xml version="1.0"?>
+<overlay id="sample" 
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ 
+	<toolbox>
+  		<toolbar id="ping-toolbar" toolbarname="PingToolbar">
+    		<toolbarbutton id="ping-ping"  accesskey="U" label="Ping!"/>
+    	</toolbar>
+	</toolbox>
+
+
+
+</overlay>

chrome/content/toolbar.js

+function PingFireProperties()
+{
+	//
+	// User Preferences Service
+	//
+	var PingTB_PrefService =
+		Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
+		
+	//
+	// Ping Fire's User Preferences Branch
+	//
+	this.PingTB_Branch = PingTB_PrefService.getBranch("extensions.pingfire.");
+	
+	//
+	// Debug Console
+	//
+	this.Ping_ConsoleService =
+	      Components.
+	          classes['@mozilla.org/consoleservice;1'].
+	              getService(Components.interfaces.nsIConsoleService);
+	              
+	//
+	// Used to post a ping
+	//
+	this.PING_POST = "http://api.ping.fm/v1/user.post";
+	
+	//
+	// Used to post a ping when a trigger is involved.
+	//
+	this.PING_TPOST = "http://api.ping.fm/v1/user.tpost";
+	
+	//
+	// Used to retrieve a user's triggers.
+	//
+	this.PING_TRIGGERS = "http://api.ping.fm/v1/user.triggers";
+	              
+	//
+	// Application's API Key
+	//
+	this.API_KEY = '79f116ff7d5caa311ae44b4a60560100';
+	
+	//
+	// Turn Ping.fm debug mode on.
+	//
+	this.DEBUG = false;
+	
+	//
+	// Mutex for preventing the submit button from being pressed more than once.
+	//
+	this.boolButtonPressed = false;
+	
+	//
+	// Mutex for preventing loadPostDialog from exiting until "Ping My" menu is loaded.
+	//
+	this.boolLoadingPingMy = false;
+	
+}
+
+/*
+	Logging method
+*/
+function m(aMessage)
+{
+//    Components.
+//	          classes['@mozilla.org/consoleservice;1'].
+//	              getService(Components.interfaces.nsIConsoleService).logStringMessage('<<Ping Fire 1.0.2>>: ' + aMessage);
+
+	getProperties().Ping_ConsoleService.logStringMessage('<<Ping Fire 1.0.3>>: ' + aMessage);
+
+}
+
+
+function getProperties()
+{
+	var PFP = null;
+	
+	try 
+	{
+		PFP = new PingFireProperties();
+	}
+	catch(a_e)
+	{
+		m('Error creating PFP object: ' + a_e);
+	}	
+	
+	return PFP;
+}
+
+/*
+	Displays the Ping dialog.
+*/
+function cmd_ping()
+{
+	m("Starting cmd_ping");
+	
+	var PFP = getProperties();
+	
+	//
+	// Get any highlighted text
+	//
+	try
+	{
+		var textWindow = document.commandDispatcher.focusedWindow;
+		var sSelectedText = textWindow.getSelection();   
+		var sSelectedTextURL = textWindow.location; 
+		PFP.PingTB_Branch.setCharPref('text', sSelectedText);
+		PFP.PingTB_Branch.setCharPref('location', sSelectedTextURL);
+	}
+	catch(a_e)
+	{
+		m('Error getting selected text: ' + a_e);
+	}
+	
+	var winPost = window.open("chrome://pingfire/content/post.xul", "postPing", "chrome, resizable=1");
+	
+	try
+	{
+		winPost.width = 350;
+		winPost.height = 300;
+		
+		var winW = window.innerWidth - winPost.width;
+		var winH = window.innerHeight - winPost.height;
+		
+		// m('[' + winW + ', ' + winH + ']');
+	
+		posX = winW / 2;
+		posY = winH / 2;
+	
+		winPost.moveTo(posX, posY);
+		
+	}
+	catch(e)
+	{
+		m(e);
+	}
+	
+}
+
+/*
+	Populates information in the Ping dialog.
+*/
+function loadPostDialog()
+{
+	
+	m("Starting loadPostDialog");
+	
+	var PFP = getProperties();
+	
+	//
+	// Add Quote if any text is selected.
+	//
+	try
+	{
+		var sSelectedText = PFP.PingTB_Branch.getCharPref('text');
+		var sSelectedURL = PFP.PingTB_Branch.getCharPref('location');
+		
+		if(sSelectedText != null && sSelectedText.length > 1)
+		{
+			sSelectedURL = shorten_url(sSelectedURL);
+			
+			// document.getElementById('pf_message_fld').value = "\"" + sSelectedText + "\"" 
+			// + " - " + sSelectedURL;
+			
+			document.getElementById('pf_message_fld').value = "\"" + sSelectedText + "\"" 
+				+ " - ";
+				
+			PFP.PingTB_Branch.setCharPref('text', "");
+			PFP.PingTB_Branch.setCharPref('location', "");
+			
+			charCount();
+		}
+		else
+		{   
+			//added by AM:
+			cur_url_short=PFP.PingTB_Branch.getBoolPref('cur_url_short');
+			if (cur_url_short!=0){
+			 var tiny = shorten_url(sSelectedURL); 
+			  
+             // document.getElementById('pf_message_fld').value = " - " + sSelectedURL + "\n tinyurl " + tiny;
+			}
+			// Location is always saved so we need to clear it.
+			PFP.PingTB_Branch.setCharPref('location', "");
+		}
+	}
+	catch(a_e)
+	{
+		m(a_e);
+	}
+}
+/*
+	Shortens a given URL using TinyArro.WS.  A special thanks 
+	to Alexander Mikhalev alex.mikhalev@gmail.com of http://alex.sci-blog.com/
+	for creating and implementing this method.
+	
+*/
+function shorten_url(url)
+{   
+    // TODO strip spacebar and CR in the end of API keys and log
+    var PFP = getProperties();
+    url_shortner=PFP.PingTB_Branch.getCharPref('url_shortner');
+    switch(url_shortner){
+        case('tinyurl'):
+            short_url_service="http://tinyurl.com/api-create.php?url=";
+            break;
+        case('bitly'):
+            short_url_service="http://api.bit.ly/shorten?version=2.0.1&format=xml&login="+PFP.PingTB_Branch.getCharPref('bitly_login').split(' ').join('')+'&apiKey='+PFP.PingTB_Branch.getCharPref('bitly_API_KEY').split(' ').join('')+'&longUrl=';
+            break;
+        default : short_url_service="http://tinyurl.com/api-create.php?url=";
+    }
+        url=encodeURIComponent(url);
+		
+        var req = new XMLHttpRequest();  
+    
+        req.open('GET',short_url_service + url, true);  
+    
+        req.onreadystatechange = function (aEvt) 
+        {  
+    		if (req.readyState == 4) 
+         	{  
+            	if(req.status == 200)    
+            	{   
+                	    if(url_shortner=='bitly')
+                	    {
+                	        try
+            				{    
+            				    xmlDoc=req.responseXML;
+                                shortURL=xmlDoc.getElementsByTagName("shortUrl")[0].textContent
+                                document.getElementById('pf_message_fld').value +=shortURL;
+
+            				}
+            				catch(e)
+            				{
+            					m(e);
+            				}           
+    			         }else{
+               		         document.getElementById('pf_message_fld').value += req.responseText;
+               	         }
+               	}
+              	else  
+              	{
+               		dump("Error loading page\n");  
+               	}
+         	}  
+         };  
+    
+    	req.send(null);
+        
+    
+  	return true;
+}  
+
+
+
+
+
+/*
+	Load the "Ping My" menu.
+*/
+function loadPingMy()
+{
+	m("Starting loadPingMy()");
+	
+	var PFP = getProperties();
+	
+	boolLoadingPingMy = true;
+	
+	var popPingMy = document.getElementById('pf_pingmy_pop');
+	
+	var req = new XMLHttpRequest();
+	var params = 'api_key=' + PFP.API_KEY + 
+		'&user_app_key=' + PFP.PingTB_Branch.getCharPref('password');
+	req.open('POST', 'http://api.ping.fm/v1/user.triggers', true); /* 3rd argument, true, marks this as async */
+	
+	req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+	req.setRequestHeader("Content-length", params.length);
+	req.setRequestHeader("Connection", "close");
+	
+	req.onreadystatechange = function (aEvt) 
+	{
+		if (req.readyState == 4) 
+		{
+			if(req.status == 200)
+			{
+				m('Custom Pings: ' + req.responseText);
+				
+				try
+				{
+					var xmlDoc = req.responseXML;
+					
+					var markers = xmlDoc.getElementsByTagName("trigger");
+
+					for ( var i = 0; i < markers.length ; i++ )
+					{
+						var sCustomTrigger = markers[i].getAttribute("id");
+						m("Trigger ID: " + sCustomTrigger);
+						
+						// Create a new menu item to be added
+						var tempItem = document.createElement("menuitem");
+						tempItem.setAttribute("label", sCustomTrigger);
+						tempItem.setAttribute("value", sCustomTrigger);
+						popPingMy.appendChild(tempItem);
+					}
+					
+					popPingMy.appendChild(document.createElement("menuseparator"));
+					
+				}
+				catch(e)
+				{
+					m(e);
+				}
+				
+				loadUserServices();
+				
+				boolLoadingPingMy = false;
+					
+			}
+			else
+			{
+				m("Error loading page\n");
+			}
+		}
+	};
+	
+	req.onprogress = function (e) 
+	{
+		m('Running ...');
+	}
+	
+
+
+	req.send(params); 
+	
+	
+	boolLoadingPingMy = false;
+}
+
+function loadUserServices()
+{
+	m("Starting loadUserServices()");
+	
+	var PFP = getProperties();
+	
+	boolLoadingPingMy = true;
+	
+	var popPingMy = document.getElementById('pf_pingmy_pop');
+	
+	var req = new XMLHttpRequest();
+	var params = 'api_key=' + PFP.API_KEY + 
+		'&user_app_key=' + PFP.PingTB_Branch.getCharPref('password');
+	req.open('POST', 'http://api.ping.fm/v1/user.services', true); /* 3rd argument, true, marks this as async */
+	
+	req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+	req.setRequestHeader("Content-length", params.length);
+	req.setRequestHeader("Connection", "close");
+	
+	req.onreadystatechange = function (aEvt) 
+	{
+		if (req.readyState == 4) 
+		{
+			if(req.status == 200)
+			{
+				m('Custom Pings: ' + req.responseText);
+				
+				try
+				{
+					var xmlDoc = req.responseXML;
+					
+					var markers 	= xmlDoc.getElementsByTagName("trigger") ;
+					var services	= xmlDoc.getElementsByTagName("service") ;
+
+					for ( var i = 0; i < markers.length ; i++ )
+					{
+						var sCustomTrigger 	= markers[i].textContent;
+						var sService		= services[i].getAttribute("id");
+						
+						m("Trigger ID: " + sCustomTrigger);
+						
+						// Create a new menu item to be added
+						var tempItem = document.createElement("menuitem");
+						tempItem.setAttribute("label", sCustomTrigger);
+						tempItem.setAttribute("value", sService);
+						popPingMy.appendChild(tempItem);
+					}
+				}
+				catch(e)
+				{
+					m(e);
+				}
+				
+				boolLoadingPingMy = false;
+					
+			}
+			else
+			{
+				m("Error loading page\n");
+			}
+		}
+	};
+	
+	req.onprogress = function (e) 
+	{
+		m('Running ...');
+	}
+	
+
+
+	req.send(params); 
+	
+	
+	boolLoadingPingMy = false;
+}
+
+
+function charCount()
+{
+	try
+	{
+		var sCurrValue = document.getElementById('pf_message_fld').value;
+		var iLength = sCurrValue.length;
+		var sMessage = iLength + ' of 140 characters.';
+		
+		if(iLength >= 130)
+		{
+			document.getElementById('pf_message_length_fld').style.color = '#FF0000';
+		}
+		else
+		{
+			document.getElementById('pf_message_length_fld').style.color = '#000000';
+		}
+		
+		document.getElementById('pf_message_length_fld').value = sMessage;
+	}
+	catch(e)
+	{
+		m(e);
+	}
+}
+
+function foo()
+{
+	// Body intentionally left blank.
+}
+
+
+
+
+
+
+function loadPreferences()
+{
+	m('loadPreferences');
+	var PFP = getProperties();
+	document.getElementById('pf_username_fld').value = PFP.PingTB_Branch.getCharPref('username');
+	document.getElementById('pf_password_fld').value = PFP.PingTB_Branch.getCharPref('password'); 
+	//Added by AM 
+    document.getElementById('url_shortner').value = PFP.PingTB_Branch.getCharPref('url_shortner');  
+    document.getElementById('cur_url_short_fld').checked = PFP.PingTB_Branch.getBoolPref('cur_url_short');
+    document.getElementById('bitly_api_fld').value=PFP.PingTB_Branch.getCharPref('bitly_API_KEY');
+    document.getElementById('bitly_login_fld').value=PFP.PingTB_Branch.getCharPref('bitly_login');
+
+}
+
+function savePreferences()
+{
+	m('Saving Preferences');
+	var PFP = getProperties();
+	PFP.PingTB_Branch.setCharPref('username', document.getElementById('pf_username_fld').value);
+	PFP.PingTB_Branch.setCharPref('password', document.getElementById('pf_password_fld').value);
+    // alert(document.getElementById('cur_url_short_fld').checked)
+  
+    url_shortener=document.getElementById('url_shortner').value 
+    bitly_API_KEY=document.getElementById('bitly_api_fld').value
+    bitly_login=document.getElementById('bitly_login_fld').value
+    if (url_shortener =='bitly')
+    {
+        if (bitly_API_KEY == null || bitly_API_KEY.length == 0)
+        {
+         m("bit.ly API Key is missing");
+         alert("Your bit.ly application key is missing.  It must be set to use bit.ly.");
+        }
+        if (bitly_login == null || bitly_login.length == 0)
+        {
+         m("bit.ly login is missing");
+         alert("Your bit.ly login is missing.  It must be set to use bit.ly.");
+        }
+    }
+    PFP.PingTB_Branch.setCharPref('bitly_API_KEY', bitly_API_KEY);
+    PFP.PingTB_Branch.setCharPref('bitly_login', bitly_login);
+    PFP.PingTB_Branch.setCharPref('url_shortner', url_shortener); 
+    PFP.PingTB_Branch.setBoolPref('cur_url_short', document.getElementById('cur_url_short_fld').checked);
+	
+	
+	m('Preferences Saved.');
+	return true;
+}
+
+function onPingMySelect(a_oSelectedElement)
+{
+	m('selected');
+	m(a_oSelectedElement.value);
+}
+
+function post()
+{
+	m("Starting post");
+	
+	var PFP = getProperties();
+	
+	var sAPIKey = null;
+	
+	try 
+	{
+		m("Checking API Key");
+		sAPIKey = PFP.PingTB_Branch.getCharPref('password');
+	}
+	catch(a_e)
+	{
+		m("Error getting API Key: " + a_e);	
+	}
+	
+	if (sAPIKey == null || sAPIKey.length == 0)
+	{
+		m("API Key is missing");
+		alert("Your application key is missing.  It must be set to use PingFire.");
+	}
+	else
+	{
+	
+    
+		var status;
+		var iElementIndex
+		var req = new XMLHttpRequest();
+		var sMessage = document.getElementById('pf_message_fld').value;
+		var sSubject = document.getElementById('pf_subject_fld').value;
+		var cboPingMy = document.getElementById('pf_pingmy_cbo');
+		var sPingMy = 'default';
+		var sService = 'foo';
+		var sRequestURL = PFP.PING_POST;
+		var params = 'api_key=' + PFP.API_KEY + '&user_app_key=' + PFP.PingTB_Branch.getCharPref('password');
+		//+ '&encoding=base64'
+		//
+		// Base the Request URL and some of the parameters on the "Ping My" value.
+		//
+		try
+		{
+			var sPingMy = cboPingMy.selectedItem.value;
+			var sService = cboPingMy.selectedItem.label;
+			
+			m('Ping My: ' + sPingMy);
+			m('Service: ' + sService);
+			
+			if(sPingMy == "default" || sPingMy == "microblog" || sPingMy == "status")
+			{
+				sRequestURL = PFP.PING_POST
+				params = params + "&post_method=" + sPingMy;
+			} 
+			else if(sPingMy == "blog")
+			{
+				if(sSubject == null || sSubject.length <= 1)
+				{
+					alert("A Title is required.");
+					return false;
+				}
+				else
+				{
+					sRequestURL = PFP.PING_POST;
+					// params = params + "&post_method=" + sPingMy + "&title=" + escape(sSubject);
+					params = params + "&post_method=" + sPingMy + "&title=" + encodeURIComponent(sSubject);
+				}
+			}
+			else if(sPingMy.toUpperCase() != sService.toUpperCase())
+			{
+				//
+				// Sending Ping to a particular service.
+				//
+				
+				sRequestURL = PFP.PING_POST;
+				
+				params = params + 
+					"&post_method="	+ "default" + 		// <<< --- Not the best way to handle this.
+					"&service=" 	+ sPingMy + 
+					"&title=" 		+ encodeURIComponent(sSubject);
+				
+			}
+			else
+			{
+				//
+				// Assume Custom Trigger.
+				//
+				
+				sPingMy = sPingMy.toLowerCase(); // need to force lower or request will fail!
+				sRequestURL = PFP.PING_TPOST
+				// params = params + "&trigger=" + sPingMy + "&title=" + escape(sSubject);
+				params = params + "&trigger=" + sPingMy + "&title=" + encodeURIComponent(sSubject);
+			}
+		}
+		catch(a_e)
+		{
+			m(a_e);
+			return false;
+		}
+		
+		//
+		// Add the Message.
+		//
+		// params = params + '&body=' + escape(sMessage);
+		params = params + '&body=' + encodeURIComponent(sMessage);
+		
+		//
+		// Debug?
+		//
+		if(PFP.DEBUG)
+		{
+			params = params + '&debug=1';
+		}
+		
+		m(params);
+		
+		if(PFP.boolButtonPressed)
+		{
+			return false;
+		}
+		else
+		{
+			PFP.boolButtonPressed = true;
+		}
+		
+		req.open('POST', sRequestURL, true); // 3rd argument, true, marks this as async
+		
+		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");
+		req.setRequestHeader("Content-length", params.length);
+		req.setRequestHeader("Connection", "close");
+		
+		req.onreadystatechange = function (aEvt) 
+		{
+			if (req.readyState == 4) 
+			{
+				if(req.status == 200)
+				{
+					m("Post Response: " + req.responseText);
+					
+					try
+					{
+						var xmlDoc = req.responseXML;
+						
+						var roottag = xmlDoc.documentElement;
+						
+						status = roottag.attributes.getNamedItem("status").value;
+	
+						m('Status: ' + status);
+						
+						if(status != 'OK')
+						{
+							m('FAIL!');
+							
+							var markers = xmlDoc.getElementsByTagName("message") ;
+	
+							var sError = "";
+							try
+							{
+								for ( var i = 0; i < markers.length ; i++ )
+								{
+									m(markers[i]);
+									sError = markers[i].textContent;
+								}
+							}
+							catch(a_e)
+							{
+								m(a_e);
+							}
+							
+							alert('Error: ' + sError);
+							PFP.boolButtonPressed = false;
+						}
+						else
+						{
+							m('Posted to Ping successfully.');
+							PFP.boolButtonPressed = false;
+							window.close();
+						}
+						
+					}
+					catch(e)
+					{
+						m(e);
+						PFP.boolButtonPressed = false;
+					}
+						
+				}
+				else
+				{
+					m("Error loading page\n");
+				}
+			}
+		};
+		
+		req.onprogress = function (e) 
+		{
+			m('Running ...');
+		}
+		
+		req.send(params);
+		
+		return false;
+	}
+}
+
+function validate()
+{ 
+    m("validate");
+    var PFP = getProperties();
+    var status;
+    var req = new XMLHttpRequest();
+	var params = 'api_key=' + PFP.API_KEY + 
+		'&user_app_key=' + PFP.PingTB_Branch.getCharPref('password');
+	req.open('POST', 'http://api.ping.fm/v1/user.validate', true); /* 3rd argument, true, marks this as async */
+	
+	req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+	req.setRequestHeader("Content-length", params.length);
+	req.setRequestHeader("Connection", "close");
+	
+	req.onreadystatechange = function (aEvt) 
+	{
+  		if (req.readyState == 4) 
+  		{
+     		if(req.status == 200)
+     		{
+      			m(req.responseText);
+      			
+      			try
+      			{
+      				var xmlDoc = req.responseXML;
+      				
+      				var roottag = xmlDoc.documentElement;
+      				
+	      			status = roottag.attributes.getNamedItem("status").value;
+
+					m('Status: ' + status);
+					
+				}
+				catch(e)
+				{
+					m(e);
+				}
+					
+			}
+			else
+			{
+      			m("Error loading page\n");
+      		}
+      	}
+	};
+	
+	req.onprogress = function (e) 
+	{
+  		m('Running ...');
+  	}
+  	
+
+
+	req.send(params); 
+} 
+
+/*
+	Code executed when browser loads ....
+*/
+
+var Prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                   .getService(Components.interfaces.nsIPrefService);
+                   // FIXED:Changed to extensions.pingfire. myext doesn't seems right
+Prefs = Prefs.getBranch("extensions.pingfire.");
+
+
+var Overlay = {
+  init: function(){
+  
+  
+  	m('Loading Ping Fire.');
+  	
+  	loadPingMy();
+  
+    var ver = -1, firstrun = true;
+
+    var gExtensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
+                            .getService(Components.interfaces.nsIExtensionManager);
+    var current = gExtensionManager.getItemForID("ping@zechariahs.org").version;
+    //gets the version number.
+    //"extension@guid.net" should be replaced with your extension's GUID.
+		
+    try{
+	ver = Prefs.getCharPref("version");
+	firstrun = Prefs.getBoolPref("firstrun");
+    }catch(e){
+      //nothing
+    }finally{
+      if (firstrun){
+        Prefs.setBoolPref("firstrun",false);
+        Prefs.setCharPref("version",current);
+	
+        // Insert code for first run here        
+
+        // The example below loads a page by opening a new tab.
+        // Useful for loading a mini tutorial
+        window.setTimeout(function(){
+          gBrowser.selectedTab = gBrowser.addTab("about:mozilla");
+        }, 1500); //Firefox 2 fix - or else tab will get closed
+				
+      }		
+      
+      if (ver!=current && !firstrun)
+	  { // !firstrun ensures that this section does not get loaded if its a first run.
+        Prefs.setCharPref("version",current);
+        
+        // Insert code if version is different here => upgrade
+      }
+	  
+	  if(firstrun)
+	  {
+	  	m("first run!");	
+	  }
+	  else
+	  {
+	  	m("Not a first run.");
+	  }
+	  
+    }
+    window.removeEventListener("load",function(){ Overlay.init(); },true);
+  }
+};
+
+
+window.addEventListener("load",function(){ Overlay.init(); },true);
+
+
+

chrome/content/toolbar.xul

+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://pingfire/skin/pingfire.css" type="text/css"?>
+                 
+<overlay id="ping-toolbar-palette-overlay" 
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+ 
+	<script type="application/x-javascript" src="chrome://pingfire/content/toolbar.js" />
+
+
+
+  		<toolbarpalette 
+  			id="BrowserToolbarPalette">
+    		
+    		<toolbarbutton 
+    			id="pf-ping-button"  
+    			tooltiptext="Ping!"
+    			class="toolbarbutton-1 chromeclass-toolbar-additional" 
+    			label="Ping"
+    			oncommand="cmd_ping();"/>
+    	
+    	</toolbarpalette>
+    	
+
+
+</overlay>

chrome/content/window.xul

+<?xml version="1.0"?>
+<overlay id="sample" 
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ 
+	<window id="ping-window" title="Ping!"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+         class="chromeclass-window"
+         style="background:#C0C0C0;">
+  		<vbox>
+    		<hbox>
+      			<description>Register Online!</description>
+    		</hbox>
+    		<groupbox align="start">
+      			<caption label="Your Information"/>
+      			<radiogroup>
+        			<vbox>
+          				<hbox>
+            				<label control="your-fname" value="Enter first name:"/>
+            				<textbox id="your-fname" value="Johan"/>
+          				</hbox>
+          				<hbox>
+            				<label control="your-lname" value="Enter last name:"/>
+            				<textbox id="your-lname" value="Hernandez"/>
+          				</hbox>
+          				<hbox>
+            				<button oncommand="alert('save!')">
+              					<description>Save</description>
+            				</button>
+          				</hbox>
+        			</vbox>
+      			</radiogroup>
+    		</groupbox>
+  		</vbox>
+
+	</window>
+
+
+
+
+</overlay>

chrome/skin/ping.jpg

Added
New image

chrome/skin/ping_hover.jpg

Added
New image

chrome/skin/ping_small.jpg

Added
New image

chrome/skin/pingfire.css

+#pf-ping-button
+{
+    list-style-image: url("chrome://pingfire/skin/ping.jpg");
+}
+
+#pf-ping-button:hover
+{
+    list-style-image: url("chrome://pingfire/skin/ping.jpg");
+}
+
+toolbar[iconsize="small"] #pf-ping-button {
+  list-style-image: url("chrome://pingfire/skin/ping_small.jpg");
+}
+
+<?xml version="1.0"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>ping@zechariahs.org</em:id>
+    <em:version>1.0.3</em:version>
+    <em:type>2</em:type>
+    <em:optionsURL>chrome://pingfire/content/preferences.xul</em:optionsURL>
+
+   
+    <!-- Target Application this extension can install into, 
+         with minimum and maximum supported versions. --> 
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>3.0</em:minVersion>
+        <em:maxVersion>3.5.*</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+   
+    <!-- Front End MetaData -->
+    <em:name>PingFire</em:name>
+    <em:description>Post to Ping.fm from FireFox.</em:description>
+    <em:creator>Zack Schwenk</em:creator>
+    <em:iconURL>chrome://pingfire/skin/ping.jpg</em:iconURL>
+    <em:homepageURL>http://www.pingfire.us</em:homepageURL>
+  </Description>      
+</RDF>
+Release Notes for PingFire Beta.
+--------------------------------------------------
+
+You can download the file from: http://www.pingfire.us 
+
+The extension is only compatible with FF3. 
+
+In order to start pinging from Firefox you must do two things:
+
+1. 	Add the "Ping" button to a menu.  You can do this by going 
+	to View >> Toolbars >> Customize ...
+2. 	Provide the extension with your Application Key.  
+	(You can find your key by going to: http://ping.fm/key.) 
+	From within Firefox, go to Tools >> Add-Ons.  Find "Ping Fire" 
+	in the list then click the "Preferences" button. 
+	Enter your User Name and your Application Key into the fields provided then click "Ok."
+	
+Licensing
+--------------------------------------------------
+
+This FireFox plug-in is free to use and distribute.  Feel free to look at the code, use
+the code, modify the code.
+
+This application comes with absolutely no warranty.  I can not and will not be held
+responsible for any trouble this application causes you.
+
+Author
+--------------------------------------------------
+
+PingFire was written by Zack Schwenk, pingfire@schwenkconsulting.com
+	
+