• 0

PHP + Picasa


Question

I upload my photos via Picasa to Picasa Web Albums (powered by Google). I am looking to pull off my photos and display them on my site.

I'd like to do this using PHP. I've looked through the API provided and have to admit I think they are too complicated for my task - they all want me to login, etc - assuming I am going to be uploading and so on - I simply want to be able to query an API to get, for example:

List of albums

Photos in an album

Can anyone please give me some pointers or provide some example code?

Many thanks

Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/
Share on other sites

14 answers to this question

Recommended Posts

  • 0

OK, I have gotten so far but am stuck - and it's probably down to my understanding of XML.

Anyhow, I am trying to consume this feed: http://picasaweb.google.com/data/feed/api/user/njlouch

My code is as such:

<?php
$xmlPath = "http://picasaweb.google.com/data/feed/api/user/njlouch/albumid/5243351093451015857";
if (!$myxml=simplexml_load_file($xmlPath)){
	echo 'Error reading the XML file';
} else{
	foreach($myxml->entry as $track){
		echo('<b><a href="'.$track->id.'">'.$track->title.'</a></b>');
		echo('<b>'.$track->summary.'</b>');
		echo('<img src="'.$track->content->href.'">');


	}
}
?>

All I want to do at this stage is to access the image name, description and the image itself. The first two are simple, but it's the image I am stuck at. But ultimately I want to show for each entry:

- published

- title

- summary

- media:thumbnail

- media:content

This is the content of the feed:

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:exif='http://schemas.google.com/photos/exif/2007' xmlns:geo='http://www.w3.org/2003/01/geo/wgs84_pos#' xmlns:gml='http://www.opengis.net/gml' xmlns:georss='http://www.georss.org/georss' xmlns:photo='http://www.pheed.com/pheed/' xmlns:media='http://search.yahoo.com/mrss/' xmlns:batch='http://schemas.google.com/gdata/batch' xmlns:gphoto='http://schemas.google.com/photos/2007'>
	<id>http://picasaweb.google.com/data/feed/api/user/njlouch/albumid/5243351093451015857</id>
	<updated>2008-09-07T18:40:14.000Z</updated>
	<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'/>
	<title type='text'>20080907</title>
	<subtitle type='text'></subtitle>
	<rights type='text'>public</rights>
	<icon>http://lh6.ggpht.com/njlouch/SMQgCf3NxrE/AAAAAAAAAEQ/KtOgOMDMgho/s160-c/20080907.jpg</icon>
	<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://picasaweb.google.com/data/feed/api/user/njlouch/albumid/5243351093451015857'/>
	<link rel='alternate' type='text/html' href='http://picasaweb.google.com/njlouch/20080907'/>
	<link rel='http://schemas.google.com/photos/2007#slideshow' type='application/x-shockwave-flash' href='http://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&RGB=0x000000&feed=http%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2Fnjlouch%2Falbumid%2F5243351093451015857%3Falt%3Drss'/>
	<link rel='http://schemas.google.com/photos/2007#report' type='text/html' href='http://picasaweb.google.com/lh/reportAbuse?uname=njlouch&aid=5243351093451015857'/>
	<link rel='self' type='application/atom+xml' href='http://picasaweb.google.com/data/feed/api/user/njlouch/albumid/5243351093451015857?start-index=1&max-results=1000'/>
	<author>
		<name>Niki</name>
		<uri>http://picasaweb.google.com/njlouch</uri>
	</author>
	<generator version='1.00' uri='http://picasaweb.google.com/'>Picasaweb</generator>
	<openSearch:totalResults>2</openSearch:totalResults>
	<openSearch:startIndex>1</openSearch:startIndex>
	<openSearch:itemsPerPage>1000</openSearch:itemsPerPage>
	<gphoto:id>5243351093451015857</gphoto:id>
	<gphoto:name>20080907</gphoto:name>
	<gphoto:location></gphoto:location>
	<gphoto:access>public</gphoto:access>
	<gphoto:timestamp>1220747072000</gphoto:timestamp>
	<gphoto:numphotos>2</gphoto:numphotos>
	<gphoto:user>njlouch</gphoto:user>
	<gphoto:nickname>Niki</gphoto:nickname>
	<gphoto:commentingEnabled>true</gphoto:commentingEnabled>
	<gphoto:commentCount>0</gphoto:commentCount>
	<gphoto:allowPrints>true</gphoto:allowPrints>
	<gphoto:allowDownloads>true</gphoto:allowDownloads>
	<entry>
		<id>http://picasaweb.google.com/data/entry/api/user/njlouch/albumid/5243351093451015857/photoid/5243351093575526146</id>
		<published>2008-09-07T18:40:10.000Z</published>
		<updated>2008-09-07T18:40:10.000Z</updated>
		<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#photo'/>
		<title type='text'>012431.jpg</title>
		<summary type='text'></summary>
		<content type='image/jpeg' src='http://lh4.ggpht.com/njlouch/SMQgCgU5pwI/AAAAAAAAAEE/lB3WuZX9bQ4/012431.jpg'/>
		<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://picasaweb.google.com/data/feed/api/user/njlouch/albumid/5243351093451015857/photoid/5243351093575526146'/>
		<link rel='alternate' type='text/html' href='http://picasaweb.google.com/lh/photo/7I4RFVbODHoFcaenV8xFXQ'/>
		<link rel='self' type='application/atom+xml' href='http://picasaweb.google.com/data/entry/api/user/njlouch/albumid/5243351093451015857/photoid/5243351093575526146'/>
		<link rel='http://schemas.google.com/photos/2007#report' type='text/html' href='http://picasaweb.google.com/lh/reportAbuse?uname=njlouch&aid=5243351093451015857&iid=5243351093575526146'/>
		<gphoto:id>5243351093575526146</gphoto:id>
		<gphoto:version>1220812810331000</gphoto:version>
		<gphoto:position>1.04209837E9</gphoto:position>
		<gphoto:albumid>5243351093451015857</gphoto:albumid>
		<gphoto:width>640</gphoto:width>
		<gphoto:height>480</gphoto:height>
		<gphoto:size>41233</gphoto:size>
		<gphoto:client>picasa</gphoto:client>
		<gphoto:checksum>760c1fda</gphoto:checksum>
		<gphoto:timestamp>1220747072000</gphoto:timestamp>
		<exif:tags>
			<exif:imageUniqueID>1e8b8741694f39bc7380e1222fbd3fe1</exif:imageUniqueID>
		</exif:tags>
		<gphoto:commentingEnabled>true</gphoto:commentingEnabled>
		<gphoto:commentCount>0</gphoto:commentCount>
		<media:group>
			<media:title type='plain'>012431.jpg</media:title>
			<media:description type='plain'></media:description>
			<media:keywords></media:keywords>
			<media:content url='http://lh4.ggpht.com/njlouch/SMQgCgU5pwI/AAAAAAAAAEE/lB3WuZX9bQ4/012431.jpg' height='480' width='640' type='image/jpeg' medium='image'/>
			<media:thumbnail url='http://lh4.ggpht.com/njlouch/SMQgCgU5pwI/AAAAAAAAAEE/lB3WuZX9bQ4/s72/012431.jpg' height='54' width='72'/>
			<media:thumbnail url='http://lh4.ggpht.com/njlouch/SMQgCgU5pwI/AAAAAAAAAEE/lB3WuZX9bQ4/s144/012431.jpg' height='108' width='144'/>
			<media:thumbnail url='http://lh4.ggpht.com/njlouch/SMQgCgU5pwI/AAAAAAAAAEE/lB3WuZX9bQ4/s288/012431.jpg' height='216' width='288'/>
			<media:credit>Niki</media:credit>
		</media:group>
	</entry>
	<entry>
		<id>http://picasaweb.google.com/data/entry/api/user/njlouch/albumid/5243351093451015857/photoid/5243351114783303842</id>
		<published>2008-09-07T18:40:14.000Z</published>
		<updated>2008-09-07T18:40:14.000Z</updated>
		<category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#photo'/>
		<title type='text'>012448.jpg</title>
		<summary type='text'></summary>
		<content type='image/jpeg' src='http://lh5.ggpht.com/njlouch/SMQgDvVOqKI/AAAAAAAAAEM/-Egc7UiyN9Q/012448.jpg'/>
		<link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://picasaweb.google.com/data/feed/api/user/njlouch/albumid/5243351093451015857/photoid/5243351114783303842'/>
		<link rel='alternate' type='text/html' href='http://picasaweb.google.com/lh/photo/VhQPN7Sc63O7porpugkfnQ'/>
		<link rel='self' type='application/atom+xml' href='http://picasaweb.google.com/data/entry/api/user/njlouch/albumid/5243351093451015857/photoid/5243351114783303842'/>
		<link rel='http://schemas.google.com/photos/2007#report' type='text/html' href='http://picasaweb.google.com/lh/reportAbuse?uname=njlouch&aid=5243351093451015857&iid=5243351114783303842'/>
		<gphoto:id>5243351114783303842</gphoto:id>
		<gphoto:version>1220812814313000</gphoto:version>
		<gphoto:position>1.0421024E9</gphoto:position>
		<gphoto:albumid>5243351093451015857</gphoto:albumid>
		<gphoto:width>640</gphoto:width>
		<gphoto:height>480</gphoto:height>
		<gphoto:size>41342</gphoto:size>
		<gphoto:client>picasa</gphoto:client>
		<gphoto:checksum>760e3fda</gphoto:checksum>
		<gphoto:timestamp>1220747089000</gphoto:timestamp>
		<exif:tags>
			<exif:imageUniqueID>2ff7ea92c91f6a0d6e8000b92655c836</exif:imageUniqueID>
		</exif:tags>
		<gphoto:commentingEnabled>true</gphoto:commentingEnabled>
		<gphoto:commentCount>0</gphoto:commentCount>
		<media:group>
			<media:title type='plain'>012448.jpg</media:title>
			<media:description type='plain'></media:description>
			<media:keywords></media:keywords>
			<media:content url='http://lh5.ggpht.com/njlouch/SMQgDvVOqKI/AAAAAAAAAEM/-Egc7UiyN9Q/012448.jpg' height='480' width='640' type='image/jpeg' medium='image'/>
			<media:thumbnail url='http://lh5.ggpht.com/njlouch/SMQgDvVOqKI/AAAAAAAAAEM/-Egc7UiyN9Q/s72/012448.jpg' height='54' width='72'/>
			<media:thumbnail url='http://lh5.ggpht.com/njlouch/SMQgDvVOqKI/AAAAAAAAAEM/-Egc7UiyN9Q/s144/012448.jpg' height='108' width='144'/>
			<media:thumbnail url='http://lh5.ggpht.com/njlouch/SMQgDvVOqKI/AAAAAAAAAEM/-Egc7UiyN9Q/s288/012448.jpg' height='216' width='288'/>
			<media:credit>Niki</media:credit>
		</media:group>
	</entry>
</feed>

Can anyone help please?

Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/#findComment-589813858
Share on other sites

  • 0

Well, to be honest its the name spaces which are throwing you off here. Name spaces are, IMO a real PIA for such small responses.

This is what I have, I was tasked to create an object that would take namespaced XML and remove all occurrences of the namespace.

It works, in fact, it works really well....I've extended the DOMDocument as to allow easier manipulation with it's methods.

I've tested it on internal, Youtube and Yahoo namespaced XML and it works a treat, but there's still work to be done I think.

Try it out with my blessings.

Class.NamespaceNulledXMLDocument.php

<?php
/**
 * @author		 Anthony David Sterling
 * 
 * @copyright	Anthony David Sterling
 * 
 * @version	 1.0
 * 
 * @desc		Removes namespace prefixes
 *				 programmatically based on the 
 *				 declared namespaces contained
 *				 within the document itself.
 * 
 * @todo		
 */
Class NamespaceNulledXMLDocument Extends DOMDocument
{
	/**
	 * @var		Boolean		Indicates whether we found any namespaces to remove.
	 */
	public $foundNamespaces = false;

	/**
	 * @var		Array		Holds all namespaces we found and processed.
	 */
	public $removedNamespaces = array();

	/**
	 * @param	String	$sXML	An XML document in string form.
	 * @return	 Void
	 */
	public function __construct( $sXML )
	{
		//--> Call the DOMDocument constructor to instantiate.
		parent::__construct();
		//--> Load our 'cleaned' XML into the DOMDocument.
		parent::loadXML( self::removeNamespaces($sXML) );
	}

	/**
	 * @param	String	$sXML	An XML document in string form.
	 * @return	String
	 */
	private function removeNamespaces( $sXML )
	{
		//--> Collecting all 'declared' namespace prefixes from within the XML document itself.
		$aNamespaces = ( preg_match_all( '/(?<=xmlns:).*?(?==)/' , $sXML , $aMatches , PREG_PATTERN_ORDER ) ) ? $aMatches[0] : array();
		//--> Before continuing, we'll check if we actually have any prefixes to remove.
		if( count($aNamespaces) > 0 )
		{
			//--> Logging the fact we found some namespaces to remove.
			$this->foundNamespaces = true;
			//--> Walking through each of the matched namespace prefixes and removing the prefix from every element.
			foreach ( $aNamespaces as $sNamespace )
			{
				//--> Log the namespace we are processing.
				$this->removedNamespaces[] = $sNamespace;
				//--> Replace any node with a namespace.
				$sXML =  preg_replace( "%(?<=<|</){$sNamespace}:%" , '' , $sXML );
				//--> Replace any attribute with a namespace.
				$sXML =  preg_replace( "/(?<=\\s){$sNamespace}:(?=.*?=\".*?\")/" , '' , $sXML );
			}
			//--> Return the new, clean, all singing, all dancing namespace nulled XML.
			return $sXML;
		}
		else
		{
			//--> Hmm, no namespaces to remove, so we'll just return the original XML that was supplied.
			return $sXML;
		}
	}
}
?>

Usage.php

<?php
//--> Load the class.
require_once( 'class.NamespaceNulledXMLDocument.php' );
//--> Obtain the namespaced XML.
$sXMLData = @file_get_contents('sample.xml');
//--> Create a NamespaceNulledXMLDocument, passing it the namespaced XML.
$oXML = new NamespaceNulledXMLDocument( $sXMLData );
//--> Using DOMDocument methods, format the output.
$oXML->formatOutput = true;
//--> Output the XML.
echo $oXML->saveXML();
?>

Enjoy!

SilverB.

Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/#findComment-589820242
Share on other sites

  • 0

Please excuse m noobishness... Is this correct?

<?php
//--> Load the class.
require_once( 'class.NamespaceNulledXMLDocument.php' );
//--> Obtain the namespaced XML.
$sXMLData = @file_get_contents('localfeed.xml');
//--> Create a NamespaceNulledXMLDocument, passing it the namespaced XML.
$oXML = new NamespaceNulledXMLDocument( $sXMLData );
//--> Using DOMDocument methods, format the output.
$oXML->formatOutput = true;
//--> Output the XML.
//echo $oXML->saveXML();
$myXML = $oXML->saveXML();
foreach($myXML>entry as $track){
	echo('<b><a href="'.$track->id.'">'.$track->title.'</a></b>');
	echo('<b>'.$track->summary.'</b>');
	echo('<img src="'.$track->content->href.'">');
}
?>

Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/#findComment-589840828
Share on other sites

  • 0

Here you go Nik, a quick demonstration for you.

<?php

require_once('class.NamespaceNulledXMLDocument.php');

$sData = @file_get_contents('localFeed.xml');

$oDocument = simplexml_import_dom( new NamespaceNulledXMLDocument( $sData ) );

echo sprintf("<h1>Album %s by %s</h1>\r\n",(String)$oDocument->name,(String)$oDocument->user);
echo '<hr />';

foreach ($oDocument->entry as $oEntry)
{
	echo sprintf("\r\n<h2>%s</h2>\r\n",(String)$oEntry->title);
	echo '<ul>';
	echo sprintf("<li>%s: %s</li>\r\n",'Height',(Integer)$oEntry->height);
	echo sprintf("<li>%s: %s</li>\r\n",'Width',(Integer)$oEntry->width);
	echo sprintf("<li>%s: %s bytes.</li>\r\n",'Size',(Integer)$oEntry->size);
	echo "</ul>\r\n";
	echo sprintf('<a href="%s" title="%s" target="_blank">Download</a>',(String)$oEntry->content['src'],(String)$oEntry->title);
}

?>

I've used the sample XML you provided in post #4 as a base.

I've basically, obtained the XML data (a local file called localFeed.xml), then passed that data to my class which creates an object with all the name spaces removed. We then pass that object to the simplexml_import_dom() function, which converts the DOM Document to a SimpleXML object for easier access.

We can now use any of the SimpleXML functions on our object ($oDocument).

Then we just iterate through the entries delivering the required data as needed.

Just so you're aware, you will unable to use the image paths supplied by the feed to embed images on another site. Google / Picasa deliver headers to the requesting agent to force download the image.

I guess this is to stop people doing what you are attempting.

You could bypass these headers, but that would be another lesson!

Feel free to pester me for advice.

SilverB.

Edited by SilverBulletUK
Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/#findComment-589847274
Share on other sites

  • 0

Thank you so much.

With reference to your header sorting script - Please see above link - am getting an error.

Fatal error: Call to undefined function curl_init() in C:\wamp\www\displaypic.php on line 3

Sorry - didn't enable CURL!

Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/#findComment-589848376
Share on other sites

  • 0

You don't have cURL installed, try this.

demo.php

<?php
require_once('class.NamespaceNulledXMLDocument.php');
$sData = @file_get_contents('localFeed.xml');
$oDocument = simplexml_import_dom( new NamespaceNulledXMLDocument( $sData ) );
echo sprintf("<h1>Album %s by %s</h1>\r\n",(String)$oDocument->name,(String)$oDocument->user);
echo "<hr />\r\n";
foreach ($oDocument->entry as $oEntry)
{
	echo sprintf("<h2>%s</h2>\r\n",(String)$oEntry->title);
	echo '<ul>';
	echo sprintf("<li>%s: %s</li>\r\n",'Height',(Integer)$oEntry->height);
	echo sprintf("<li>%s: %s</li>\r\n",'Width',(Integer)$oEntry->width);
	echo sprintf("<li>%s: %s bytes.</li>\r\n",'Size',(Integer)$oEntry->size);
	echo "</ul>\r\n";
	echo sprintf('<img src="picasaImage.php?picasaImage=%s" alt="%s" />',base64_encode((String)$oEntry->content['src']),(String)$oEntry->title);
}
?>

picasaImage.php

<?php
if( isset($_GET['picasaImage']) )
{
	$sImageURL = base64_decode( $_GET['picasaImage'] );
	if( $sImageData = @file_get_contents($sImageURL) )
	{
		header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
		header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
		header( 'Content-Type: image/jpg' );
		header( 'Cache-Control: no-store, no-cache, must-revalidate' );
		header( 'Cache-Control: post-check=0, pre-check=0', false );
		header( 'Pragma: no-cache' );
		echo $sImageData;
		exit;
	}
}
exit;
?>

Place both of those on your server, it should do the trick.

SilverB.

Edited by SilverBulletUK
Link to comment
https://www.neowin.net/forum/topic/666422-php-picasa/#findComment-589848420
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Anybody that thinks flying cars were possible are idiots. Everyone would basically need a pilot licence, can you imagine how insane and dangerous that would be, people can barely handle driving on land safely right now.
    • Microsoft Edge 149.0.4022.80 by Razvan Serea Microsoft Edge is a super fast and secure web browser from Microsoft. It works on almost any device, including PCs, iPhones and Androids. It keeps you safe online, protects your privacy, and lets you browse the web quickly. You can even use it on all your devices and keep your browsing history and favorites synced up. Built on the same technology as Chrome, Microsoft Edge has additional built-in features like Startup boost and Sleeping tabs, which boost your browsing experience with world class performance and speed that are optimized to work best with Windows. Microsoft Edge security and privacy features such as Microsoft Defender SmartScreen, Password Monitor, InPrivate search, and Kids Mode help keep you and your loved ones protected and secure online. Microsoft Edge has features to keep both you and your family protected. Enable content filters and access activity reports with your Microsoft Family Safety account and experience a kid-friendly web with Kids Mode. The new Microsoft Edge is now compatible with your favorite extensions, so it’s easy to personalize your browsing experience. Microsoft Edge 149.0.4022.80 changelog: Fixes Fixed an issue that prevented QR code generation from working. Feature updates Intune MAM Protected Downloads. The protected downloads feature for Intune MAM will now save downloaded files to the Documents > Microsoft Edge > Downloads folder in OneDrive. Extensions monitoring in the Edge management service. The Microsoft Edge management service now allows admins to gain visibility into extensions installed across their managed users. From the extensions monitoring page, admins can see which extensions have been installed as well as manage user requests for blocked extensions. For more information, see Microsoft Edge Extensions Monitoring. Validate Edge builds early with enterprise preview. Enterprise preview provides a simpler way for admins to flight pre-release Edge builds to their users. To reduce friction and bolster usage, users will receive pre-release builds directly inside of their Stable Edge application. Admins can allow users to easily opt-out of the preview experience, using built-in rollback to switch between their pre-release and stable channels with ease. Microsoft 365 admin center users can configure the feature, view their flighting population, and receive personalized recommendations all in one place. For more information, see Get started with Enterprise Preview in Microsoft Edge. Download: Microsoft Edge (64-bit) | 193.0 MB (Freeware) Download: Microsoft Edge (32-bit) | 170.0 MB Download: Microsoft Edge (ARM64) | 188.0 MB View: Microsoft Edge Website | Release History Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • The machines are starting to fight back any way they can.
    • No news articles about the Arch Linux repo being majorly infected with malware?!?
    • Waymo recalls self-driving software after cars enter closed freeway work zones by Paul Hill Waymo, the self-driving car maker owned by Alphabet – the parent company of Google –, has recalled some of its fifth-generation Automated Driving Systems (ADS). It did so after some of its cars drove through closed construction zones. According to the National Highway Traffic Safety Administration (NHTSA), the affected vehicles were capable of driving through a closed freeway construction zone and continuing to drive at speed. The listing on the NHTSA website says that Waymo is currently developing a solution to fix this issue, but in the meantime, freeway driving is being restricted. Waymo will update its ADS software so that vehicles can detect when they can avoid entering construction zones. According to the Safety Recall Report, on April 20, 2026, Waymo’s Field Safety Committee began meetings reviewing an event from April 11, 2026, and five events from April 19, 2026, where Waymo’s autonomous vehicles didn’t recognize and drove past ramp closure signs into the pre-planned freeway construction zones. This took place in Phoenix, Arizona. Separately, on May 18, 2026, seven Waymo vehicles entered freeway lanes with active construction in the San Francisco Bay Area by driving between cones that were placed to show the lane was closed. On the back of both of these events, Waymo restricted freeway driving until it could address the issue. In June, Waymo’s Safety Board reviewed the issue and additional information related to ADS performances around construction zones; then, as a result, it decided to conduct a recall. This development is not good for Waymo as it adds to a growing list of technical hiccups its cars have experienced. Ultimately, it will lead to more scrutiny from lawmakers around the world who will be more cautious about letting autonomous vehicles on their roads without tighter regulation. For readers in areas where Waymo operates, does this news make you more wary about stepping into one of these vehicles?
  • Recent Achievements

    • Week One Done
      Eurosoft10 earned a badge
      Week One Done
    • One Month Later
      Eurosoft10 earned a badge
      One Month Later
    • One Year In
      Skeet Campbell earned a badge
      One Year In
    • One Month Later
      Sharbel earned a badge
      One Month Later
    • First Post
      BizSAR earned a badge
      First Post
  • Popular Contributors

    1. 1
      +primortal
      599
    2. 2
      +Edouard
      190
    3. 3
      PsYcHoKiLLa
      79
    4. 4
      Michael Scrip
      77
    5. 5
      Steven P.
      69
  • Tell a friend

    Love Neowin? Tell a friend!