[Clipart] r32 - in makerelease: . template template/css template/images

noreply at openclipart.org noreply at openclipart.org
Sat Mar 28 01:46:18 PDT 2009


Author: jstaerk
Date: Sat Mar 28 08:46:17 2009
New Revision: 32

Log:
by jstaerk at usegroup.de, new script to create file releases as of 0.19

Added:
   makerelease/
   makerelease/downloader.php
   makerelease/template/
   makerelease/template/css/
   makerelease/template/css/main.css
   makerelease/template/images/
   makerelease/template/images/bg.png   (contents, props changed)
   makerelease/template/images/bgl.png   (contents, props changed)
   makerelease/template/images/bullet.gif   (contents, props changed)
   makerelease/template/images/logo.jpg   (contents, props changed)
   makerelease/template/images/openclipart.png   (contents, props changed)
   makerelease/template/images/publicdomain.png   (contents, props changed)
   makerelease/template/images/s-b.png   (contents, props changed)
   makerelease/template/index.html

Added: makerelease/downloader.php
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ makerelease/downloader.php	Sat Mar 28 08:46:17 2009	(r32)
@@ -0,0 +1,792 @@
+<?php
+
+/**
+ * @author Jochen Stärk <jstaerk at usegroup.de>
+ * @version 1.1
+ * @date 2009-03-19
+ * 
+ * This php shell script creates a openclipart file release.   
+ * 
+ * It uses wget to download the daily SVG tarball from openclipart.org, 
+ * fires inkscape to rasterize all images and create thumbnails,
+ * creates a HTML-Gallery for offline viewing, creates .zip, .tar.gz and .tar.bz2
+ * bundles and uploads them with rsync. 
+ * A log with all messages is stored in lastrun.log 
+ * 
+ * It has been developed for windows and linux
+ * 
+ * It requires the following tools to be installed:
+ *  - php (obviously, to run this script, fire <path to your php>\php downloader.php). For windows you can also use xampp, http://www.apachefriends.org/en/xampp-windows.html
+ *  - the GD-extension of PHP
+ *  - a high memory_limit in the php.ini file. 32mb didn't suffice for big PNGs but I never had any issue with 320...
+ * 	- wget, tar, bzip2 (for windows: http://getgnuwin32.sourceforge.net/)
+ *  - the templates for the HTML gallery in a subdirectory called template
+ * 	- inkscape (www.inkcape.org) to create png thumbnails
+ *  - optional: rsync to upload, for windows e.g. cwrsync, http://www.rsync.net/resources/howto/windows_rsync.html
+ *    in case you want to use this feature you will have to setup cwrsync so that it connects to the remote host 
+ *    w/o asking for a password or host authentication confirmation. Ted Ruegsegger has written a documentation 
+ *    on that on http://www.tux.org/~tbr/rsync/#What1 but I think it's even easier: 
+ *    the home directory on vista is automatically c:\users\<username>.
+ *    On XP and older your homedir might be somewhere else, e.g. "c:\documents and settings"
+ *    run rsync once manually from the rsync path, rsyncing anything you like to 
+ *    your destination host to get the .ssh directory and confirm host authentity:
+ *    Step 1 (confirm host):
+ *    	cd "\program files\cwrsync\bin"
+ *    	rsync -avzP plink.exe <yourusername>@<yourhostname>:/tmp/
+ *      (confirm host identity and type your password manually)
+ *      (this should transmit plink.exe to <yourhostname>/tmp/ just as a test)
+ *    Step 2 (generate and submit keys):    
+ *    	(still in "\program files\cwrsync\bin")
+ *	  	ssh-keygen -t dsa -N "" -f \users\<username>\.ssh\id_dsa
+ *	  	rsync -avzP \users\<username>\.ssh\id_dsa.pub <yourusername>@<yourhostname>:/tmp/id_dsa.pub
+ *    Step 3 (host to accept the keys):
+ *    	ssh to your host, e.g. via putty, with <yourusername>
+ *    	rm /tmp/plink.exe (as this was just a test)
+ *    	cat /tmp/id_dsa.pub >> ~/.ssh/authorized_keys
+ *    	(keep this window open, I'll call it remote window)
+ *    Step 4 (test)
+ *    	(back on local window in "\program files\cwrsync\bin")
+ *    	rsync -avzP plink.exe <yourusername>@<yourhostname>:/tmp/
+ *    	(this should now NOT ask for host authentication NOR password)
+ *    	(on remote window)
+ *      rm /tmp/plink.exe 
+ *      exit
+ *    	(and you can also exit your local window)
+ * 
+ * see also http://www.openclipart.org/wiki/Release_Procedure
+ * */
+
+/**
+ * This class was just a test for obtaining metadata but it never worked properly 
+ * and is not used at all at this time
+ 
+class tagParser {
+
+    // XML parser variables
+    var $parser;
+    var $name;
+    var $attr;
+    private $lastContent;
+    private $numItemsRetrieved;
+    private $numItemsToRetrieve=300;
+    private $chop=0;
+    private $tag;
+    private $completeContent="";
+    private $emptyTranslations=array();
+  
+
+    // function with the default parameter value
+    // it will automatically add &limit=300&chop=0
+    function __construct($tag) {
+        $this->tag  = $tag;
+        
+        $translations = get_html_translation_table(HTML_ENTITIES);
+        $this->emptyTranslations=array();
+        foreach ($translations as $key=>$translation) {
+        	$this->emptyTranslations[$translation]="?";
+        } 
+        
+    }
+  
+    // parse XML data
+    function parse()
+    {
+    	$this->numItemsRetrieved=0;
+        $this->parser = xml_parser_create ("UTF-8");
+        xml_set_object($this->parser, $this);
+        xml_set_element_handler($this->parser, 'startXML', 'endXML');
+        xml_set_character_data_handler($this->parser, 'charXML');
+
+        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
+        
+            	
+//        die(strtr("dies ist alles & nichts ", $emptyTranslations));
+        do  {
+        	$completeURL="http://openclipart.org/media/api/query?f=rss&tags=".$this->tag."&limit=300&offset=".$this->chop;
+            // if use type = 'url' now we open the XML with fopen
+          
+            if (!($fp = @fopen($completeURL, 'rb'))) {
+                $this->error("Cannot open {$this->url}");
+            }
+
+            while (($data = fread($fp, 8192))) {
+  				$data=strtr($data, $this->emptyTranslations);
+            	$this->completeContent.=$data;	
+  				if (!xml_parse($this->parser, $data, feof($fp))) {
+                    $this->error(sprintf('XML error at line %d column %d',
+                    xml_get_current_line_number($this->parser),
+                    xml_get_current_column_number($this->parser)),$data);
+                }
+            }
+            fclose($fp);
+        	$this->chop+=$this->numItemsRetrieved;
+            echo "$completeURL\n";
+        } while (!$this->isCompleted());
+        
+        echo "retrieved ".$this->numItemsRetrieved." items for tag ".$this->tag."\n";
+    }
+
+    function startXML($parser, $name, $attr)    {
+    	$this->lastContent="";
+    	if ($name=="item") {
+    		$this->numItemsRetrieved++;
+    	}
+     
+    }
+
+    function endXML($parser, $name)    {
+    	if ($name=="guid") {
+    	   	//$progFile=fopen("prog.txt","a");
+        	print($this->chop." ".$this->lastContent."\n");
+        	//fclose ($progFile);
+    	} 
+    	
+    }
+    
+    function isCompleted() {
+    	return $this->numItemsRetrieved<$this->numItemsToRetrieve;
+    }
+
+    function charXML($parser, $data)    {
+    	$this->lastContent.=$data;
+    }
+
+    function error($msg, $data=null)    {
+        echo "$msg";
+        if ($data!=null) {
+        	$errFile=fopen("err.txt","w");
+        	fwrite($errFile, $data);
+        	fclose ($errFile);
+        }
+        exit();
+    }
+}
+
+//$tags=array("abstract","activity","anatomy","ancient","animal","apple","arcade","architecture","armor","arrow","art","baby","ball","barbering","bear","beer","beverage","bird","birthday","black","blue","boat","book","border","bottle","box","boy","building","button","calligraphic","callout","camera","candle","car","card","cartography","cartoon","castle","cat","character","chicken","child","christmas","circuit","city","clock","clothing","cloud","coat_of_arms","color","colouring_book","comic","computer","container","contour","costume","country","cow","crest","danger","decoration","decorative","design","dessert","diagram","dog","drink","earth","egg","electric","electrical_appliances","electricity","electronics","epa","epa_sunwise","equipment","europe","eye","face","fantasy","farm","feline","female","figure","fire","fish","flag","flower","fly","food","frame","france","fruit","funny","furniture","fws","fws_lineart","game","geography","germany","girl","glass","globe","glossy","god
 ","greek","green","guitar","guy","hair","halloween","hand","happy","hardware","hat","head","heart","helmet","heraldry","historical","history","holiday","home","horse","house","household","human","icon","iec","illustration","inkscape","insect","instrument","japanese","jigsaw","key","kitchen","land","landscape","leaf","letter","line_art","literature","loc","logo","love","mammal","man","map","maritime","meat","medical","medicine","medieval","metal","military","money","monitor","mouse","music","mythology","nation","nature","night","no_contour","ocean","office","orange","outline","paper","party","pc_for_alla","pen","penguin","people","person","pet","phone","photorealistic","pink","pirate","plane","planet","plant","play","poland","portrait","puzzle","rabbit","reading","red","religion","roadsign","sailing","santa","scene","school","science","screen","sea","season","semaphore","shape","ship","sign","signal","silhouette","skull","sky","smiley","smiling","snow","sound","space","sport"
 ,"star","storage","sun","sweden","swiss","sword","symbol","tangram","technology","time","tool","tower","toy","traffic","transportation","tree","united_nations_member","uspto","valentine","vegetable","vehicle","war","warning","water","weapon","weather","white","wikimedia_commons","wine","wing","winter","woman","wood","work","world","worldlabel","writing","yellow");
+
+foreach ($tags as $tag) {
+	
+	$rp=new tagParser($tag);
+	$rp->parse();
+	
+	  
+}*/
+
+class opsysDependendEntity{
+	protected $opsys; // 1=windows, 0=linux, adjusted in checkOpsys
+	protected $opsysQuotes;//quotes around directories with spaces (and commands with multiple directories with spaces), none in linux, " in windows, adjusted in checkOpsys
+	protected $opsysDirSep;//delimiter between directories and subdirectories or files, "/" in linux, "\" in windows, adjusted in checkOpsys
+	protected $path_wget; // the full path and file name of the "wget" executable. Default assigned in checkOpsys, user will be prompted if not found there
+	protected $path_tar;  // where "wget" is found. Default assigned in..., user will be prompted...
+	protected $path_bunzip;
+	protected $path_gzip;
+	protected $path_bzip;
+	protected $path_zip;
+	protected $path_inkscape;
+	protected $path_rsync;
+	
+	public function checkOpsys() {
+		if (file_exists("/etc")) {
+			//unixoid opsys, lets assume it's linuxoid... 
+			$this->opsys=0;
+			$this->opsysQuotes="";
+			$this->opsysDirSep="/";
+
+
+			$this->path_wget="/usr/bin/wget";
+			$this->path_tar="/bin/tar";
+			$this->path_bunzip="/bin/bunzip2";
+			$this->path_gzip="/bin/gzip";
+			$this->path_bzip="/bin/bzip2";
+			$this->path_zip="/usr/bin/zip";
+			$this->path_inkscape="/usr/bin/inkscape";
+			$this->path_rsync="/usr/bin/rsync";
+		} else {
+			$this->opsys=1;
+			$this->opsysQuotes="\"";
+			$this->opsysDirSep="\\";
+
+			$this->path_wget="c:\\program files\\gnu\\gnuwin32\\bin\\wget.exe";
+			$this->path_tar="c:\\program files\\gnu\\gnuwin32\\bin\\tar.exe";
+			$this->path_bunzip="c:\\program files\\gnu\\gnuwin32\\bin\\bunzip2.exe";
+			$this->path_gzip="c:\\program files\\gnu\\gnuwin32\\bin\\gzip.exe";
+			$this->path_bzip="c:\\program files\\gnu\\gnuwin32\\bin\\bzip2.exe";
+			$this->path_zip="c:\\program files\\gnu\\gnuwin32\\bin\\zip.exe";
+			$this->path_inkscape="c:\\program files\\inkscape\\inkscape.exe";
+			$this->path_rsync="c:\\program files\\cwRsync\\bin\\rsync.exe";
+	
+		}
+	}		
+	
+	
+}
+
+class logger extends opsysDependendEntity {
+	private $logfile; // the file handle of the open lastrun.log file
+	private $startTime; // the microtime (true) when the run started. Used to calculate runtime in status messages 
+
+	public function __construct() {
+		$this->logfile=fopen("lastrun.log", "w");
+		$this->startTime=microtime(true);
+		$this->checkOpsys();
+		
+	}
+	/**
+	 * this function will give an echo and log on the logfile
+	 * */
+	function shout($message) {
+		echo $message;
+		fwrite($this->logfile, $message);
+		
+	}
+	
+	function shoutNewStatus($message) {
+		$time=microtime(true);
+		$runTime=$time-$this->startTime;
+		$this->shout("===$message===\n");
+		$this->shout("@$runTime\n");
+	}
+	public function __destruct() {
+		$this->shoutNewStatus("done");
+	
+		fclose($this->logfile);
+	}
+	
+	
+}
+
+class HTMLPreviewBuilder extends opsysDependendEntity {
+	private $images;
+	private $logger;
+	private $destinationPath;
+	private $thumbsProPage=50;
+	private $currentPageIndex=0;
+	private $numPages=0;
+	private $templateLines=array();
+	private $version;
+	private $pagesLinked;
+	
+	public function __construct(logger $logger, $version) {
+		$this->images=array();
+		$this->logger=$logger;
+		$this->version=$version;
+		$this->checkOpsys();		
+	}
+	
+	public function addImage($filepath) {
+		$this->images[]=$filepath;
+	}
+	
+	private function dir_copy($srcdir, $dstdir, $offset = '', $verbose = false)
+	{// source: http://de3.php.net/copy#89299
+	    // A function to copy files from one directory to another one, including subdirectories and
+	    // nonexisting or newer files. Function returns number of files copied.
+	    // This function is PHP implementation of Windows xcopy  A:\dir1\* B:\dir2 /D /E /F /H /R /Y
+	    // Syntaxis: [$returnstring =] dircopy($sourcedirectory, $destinationdirectory [, $offset] [, $verbose]);
+	    // Example: $num = dircopy('A:\dir1', 'B:\dir2', 1);
+	
+	    // Original by SkyEye.  Remake by AngelKiha.
+	    // Linux compatibility by marajax.
+	    // ([danbrown AT php DOT net): *NIX-compatibility noted by Belandi.]
+	    // Offset count added for the possibilty that it somehow miscounts your files.  This is NOT required.
+	    // Remake returns an explodable string with comma differentiables, in the order of:
+	    // Number copied files, Number of files which failed to copy, Total size (in bytes) of the copied files,
+	    // and the files which fail to copy.  Example: 5,2,150000,\SOMEPATH\SOMEFILE.EXT|\SOMEPATH\SOMEOTHERFILE.EXT
+	    // If you feel adventurous, or have an error reporting system that can log the failed copy files, they can be
+	    // exploded using the | differentiable, after exploding the result string.
+	    //
+	    if(!isset($offset)) $offset=0;
+	    $num = 0;
+	    $fail = 0;
+	    $sizetotal = 0;
+	    $fifail = '';
+	    if(!is_dir($dstdir)) mkdir($dstdir);
+	    if($curdir = opendir($srcdir)) {
+	        while($file = readdir($curdir)) {
+	            if($file != '.' && $file != '..') {
+	//                $srcfile = $srcdir . '\\' . $file;    # deleted by marajax
+	//                $dstfile = $dstdir . '\\' . $file;    # deleted by marajax
+	                $srcfile = $srcdir . '/' . $file;    # added by marajax
+	                $dstfile = $dstdir . '/' . $file;    # added by marajax
+	                if(is_file($srcfile)) {
+	                    if(is_file($dstfile)) $ow = filemtime($srcfile) - filemtime($dstfile); else $ow = 1;
+	                    if($ow > 0) {
+	                        if($verbose) echo "Copying '$srcfile' to '$dstfile'...<br />";
+	                        if(copy($srcfile, $dstfile)) {
+	                            touch($dstfile, filemtime($srcfile)); $num++;
+	                            chmod($dstfile, 0777);    # added by marajax
+	                            $sizetotal = ($sizetotal + filesize($dstfile));
+	                            if($verbose) echo "OK\n";
+	                        }
+	                        else {
+	                            echo "Error: File '$srcfile' could not be copied!<br />\n";
+	                            $fail++;
+	                            $fifail = $fifail.$srcfile.'|';
+	                        }
+	                    }
+	                }
+	                else if(is_dir($srcfile)) {
+	                    $res = explode(',',$ret);
+	//                    $ret = dircopy($srcfile, $dstfile, $verbose); # deleted by patrick
+	                    $ret = $this->dir_copy($srcfile, $dstfile, $verbose); # added by patrick
+	                    $mod = explode(',',$ret);
+	                    $imp = array($res[0] + $mod[0],$mod[1] + $res[1],$mod[2] + $res[2],$mod[3].$res[3]);
+	                    $ret = implode(',',$imp);
+	                }
+	            }
+	        }
+	        closedir($curdir);
+	    }
+	    $red = explode(',',$ret);
+	    $ret = ($num + $red[0]).','.(($fail-$offset) + $red[1]).','.($sizetotal + $red[2]).','.$fifail.$red[3];
+	    return $ret;
+	} 
+	
+	private function copyTemplateFiles() {
+		$this->dir_copy("template",$this->destinationPath);		
+	}
+	
+	private function getFilenameForIndex($idx) {
+		$filenameSuffix="_".$idx;
+		if ($idx==1) {
+			$filenameSuffix="";
+		}
+		return "index".$filenameSuffix.".html";
+	}
+
+	private function calculateLink($fromWhere, $distance, $ascending) {
+		$target=null;
+		if ($fromWhere%$distance==0) {
+			if ($ascending) {
+				$target=$fromWhere+$distance;
+			} else {
+				$target=$fromWhere-$distance;	
+			}
+				
+		} else {
+			if ($ascending) {
+				$target=ceil($fromWhere/$distance)*$distance;
+			} else {
+				$target=floor($fromWhere/$distance)*$distance;
+			}
+			
+		}
+		return $target;
+		
+	}
+	/**
+	 * will return 1 for OK, 0 for try again and -1 for not ok
+	 * */
+	private function checkAndInsertLink($toWhere) {
+		$possible=($toWhere>0)&&($toWhere<=count($this->images));
+		if (!$possible) {
+			return -1;			
+		}
+		if (in_array($toWhere, $this->pagesLinked)) {
+			return 0;
+		} else {
+			$this->pagesLinked[]=$toWhere;
+			return 1;
+		}
+	}
+	
+	private function linkFarAway($distance, $ascending) {
+		//can only link to e.g. the last 10 if page number >10
+
+		$target=$this->calculateLink($this->currentPageIndex, $distance, $ascending);
+		$successful=$this->checkAndInsertLink($target);
+		while ($successful===0) {
+			// was already there
+			if ($ascending) {
+				$target+=$distance;
+			} else {
+				$target-=$distance;
+				
+			}
+			$successful=$this->checkAndInsertLink($target);
+		} 
+		
+		
+	}
+	/**
+	 * Copies the dependencies (.css, .js, .jpg files) to the directory specified
+	 * in $path and generates the index .html file and the .html files for all pages
+	 * */
+	public function writeHTML($path) {
+		$this->destinationPath=$path;
+		$this->logger->shoutNewStatus("Generating HTML");
+		$this->copyTemplateFiles();
+		$this->templateLines=file("template".$this->opsysDirSep."index.html");
+		unlink($path.$this->opsysDirSep."index.html");
+		$this->numPages	=ceil(count($this->images)/$this->thumbsProPage);
+		for($pageStartIndex=0; $pageStartIndex<count($this->images); $pageStartIndex+=$this->thumbsProPage) {
+			$this->currentPageIndex++;
+			
+			$f=fopen($path.$this->opsysDirSep.$this->getFilenameForIndex($this->currentPageIndex), "w");
+			
+			$contentHTML="";
+			for ($thumbIndex=$pageStartIndex; (($thumbIndex<count($this->images))&&($thumbIndex<$pageStartIndex+$this->thumbsProPage));$thumbIndex++) {
+				$image=$this->images[$thumbIndex];
+				$svgFile=substr($image,strlen($path));
+				$svgFile=str_replace($this->opsysDirSep,"/",$svgFile);
+				$dirParts=explode($this->opsysDirSep,$image);
+				$artist="undefined";
+				$artistDisplayName=$artist;
+				$title="undefined";
+				if (count($dirParts)>2) {
+					// the lower most directory name is also the name of the artist
+					$artist=$dirParts[count($dirParts)-2];
+					$artistDisplayName=str_replace("_"," ",$artist);
+					
+				}
+				if (count($dirParts)>1) {
+					// the lower most directory name is also the name of the artist
+					$title=substr($dirParts[count($dirParts)-1], strlen($artist)+1);
+					$title=str_replace("_"," ", $title);
+					$title=substr($title,0,strrpos($title, "."));
+					
+				}
+				$pngFile=str_replace(".svg",".png",$svgFile);
+				$contentHTML.="		
+				<div class='r-img'>
+					<div>
+						<a href='$svgFile' title='$title'><img src='$pngFile' alt='#'></a>
+					</div>
+					<h4><a href='$svgFile'>$title</a></h4>
+					<p>by <a href='http://openclipart.org/media/people/$artist'>$artistDisplayName</a></p>
+				</div> \n";
+			}
+			// page navi: e.g. for page 136 we want links like
+			// 1 100 130 134 135 *136* 137 138 140 200 236
+			// means: the current page is always visible w/o link
+			// if the page>1 insert link to page one
+			// if the page>2 insert link to previous page as well
+			// if the page>3 insert link to pre-previous page as well
+			
+			// if the page>50, insert link to last 50er (floor(page/50))*50 and, if available, to the next 50er
+			// if the page%100>0 insert link to last 10er (floor(page%100/10))*10 and, if available, to the next 10er
+
+			// if the page<last page insert link to last page
+			
+			$this->pagesLinked=array();
+			// first: link first, last, next 2 and previous 2 pages
+			$this->checkAndInsertLink(1);
+			$this->checkAndInsertLink($this->numPages);
+			$this->checkAndInsertLink($this->currentPageIndex);
+			$this->checkAndInsertLink($this->currentPageIndex-1);
+			$this->checkAndInsertLink($this->currentPageIndex-2);
+			$this->checkAndInsertLink($this->currentPageIndex+1);
+			$this->checkAndInsertLink($this->currentPageIndex+2);
+			
+			// now find out what to do with 10ers and 50ers, and keep in mind 
+			// next 10er or 50er page might already be linked via the "next two"
+			// pages e.g. on pg 48 (49,50...)
+
+			// link to next 50er have lower priority than to next 10er, i.e. on 99 link to 100 (10) and 150 
+			$this->linkFarAway(10,false); 			
+			$this->linkFarAway(10,true); 			
+			$this->linkFarAway(50,false); 			
+			$this->linkFarAway(50,true); 			
+			
+			
+			$pageNavi="";
+			sort($this->pagesLinked);
+			foreach ($this->pagesLinked as $pageLink) {
+				$prefix="<li><a href='".$this->getFilenameForIndex($pageLink)."'>";
+				$suffix="</a></li>";
+				if ($pageLink==$this->currentPageIndex) {
+					$prefix="<li id='active'>";
+					$suffix="</li>";
+				}
+				$pageNavi.=$prefix.$pageLink.$suffix;
+			}
+			
+			foreach ($this->templateLines as $indexLine) {
+				$indexLine=str_replace("[title]","OpenClipart $this->version",$indexLine);
+				$indexLine=str_replace("[subtitle]","Page {$this->currentPageIndex} of {$this->numPages}",$indexLine);
+				$indexLine=str_replace("[pages]",$pageNavi,$indexLine);
+				$indexLine=str_replace("[thumbnails]",$contentHTML,$indexLine);
+				fwrite($f, $indexLine);
+			}
+		}
+		
+		
+		
+		fclose($f);
+	}
+}
+
+class releaser extends opsysDependendEntity {
+
+	private $maxWidth=64;  // maximal thumbnail width
+	private $maxHeight=64; // max thumbnail height
+	// technically maxWidth and maxHeight form a bounding box in 
+	// which the thumbnail will always fit (usually with free space around) 
+	
+	
+	private $rsyncUser; // upload user name entered by the user
+	private $rsyncHost; // upload host name entered by the user 
+	private $rsyncDir; // upload directory entered by the user
+	
+	private $numSVGsAvailable; // the total number of svgs
+	private $numThumbsGenerated; // the number of SVGs generated in this run. If a run is stopped(killed) and continued afterwards this can differ from the total number of svg files  
+	private $version; // version nr of this release, e.g. 0.19
+	private $doDownload; // boolean if daily_svg_snapshot is to be downloaded (otherwise we just continue a previous run)
+	private $doUnzip; // boolean if daily_svg_snapshot is to be unzipped again
+	private $doRsync; // boolean if release is to be uploaded
+	
+	private $files; // in the end contains an array of all files, to be passed to a HTMLPreviewBuilder 
+	private $HTMLpreview;
+	private $logger;
+	
+	function __construct() {
+		if (!empty($_SERVER['SERVER_NAME'])) {
+			die("This is a command line script. Please run it from the shell with 'php downloader.php'.");
+		}
+		$this->numThumbsGenerated=0;
+		$this->numSVGsAvailable=0;
+		$this->checkOpsys();
+		$this->logger=new logger();
+		
+	}
+
+
+	private function generate_thumbnails($dir) {
+		
+		if (is_dir($dir)) {
+		    if ($dh = opendir($dir)) {
+		        while (($file = readdir($dh)) !== false) {
+		        	if (($file!=".")&&($file!="..")) {
+		        		$completeFileLocation=$dir.$this->opsysDirSep.$file;
+		            	if (is_dir($completeFileLocation))  {
+		           		 	$this->generate_thumbnails($completeFileLocation);
+		          		} else {
+		            		if (strpos($file,".svg")!==false) {
+			          			$this->numSVGsAvailable++;
+			            		echo "File {$this->numSVGsAvailable} Creating thumbnail #{$this->numThumbsGenerated} for: $completeFileLocation \n";
+		// my inkscape 0.46 for windows and linux crashes on orangeobject_background-ribbon.svg which destroys the overnight batch run, so lets leave it out
+			            		if (strpos($completeFileLocation,"orangeobject_background-ribbon.svg")===false) {
+			            			$this->HTMLpreview->addImage($completeFileLocation);
+			            			$pngFilename=str_replace(".svg",".png",$completeFileLocation);
+			            			$this->files[]=$completeFileLocation;
+				          			if (!file_exists($pngFilename)) {
+			          					$this->numThumbsGenerated++;
+				          				$this->myExec($this->path_inkscape,'-f "'.$completeFileLocation.'" -e "'.$pngFilename.'" -w '.$this->maxWidth);
+				          				list($width, $height)=getimagesize($pngFilename);
+				          				// the GD library cant determine the aspect ratio of a SVG and I would not know how to do it in pure PHP, so
+				          				// we create a png thumbnail with maxWidth, use the GD library on the thumbnail to find out if it was
+				          				// a vertical image (height>maxHeigth) and if so, overwrite the thumbnail with a version enforcing maxHeigth  
+				          				if ($height>$this->maxHeight) {
+				          					$this->myExec($this->path_inkscape,'-f "'.$completeFileLocation.'" -e "'.$pngFilename.'" -h '.$this->maxHeight);
+				          					
+				          				}
+				          							          					
+/*					          				if we had a png version which was guranteedly bigger than maxsize or minsize, we could create the thumb using gd as follows:
+ * 											// the GD library cant determine the aspect ratio of a SVG and I would not know how to do it in pure PHP, so
+					          				// we create a png thumbnail with maxWidth, use the GD library on the thumbnail to find out if it was
+					          				// a vertical image (height>maxHeigth) and if so, overwrite the thumbnail with a version enforcing maxHeigth  
+					          				if ($height>$width) {
+					          					$newHeight=$this->maxHeight;
+					          					$newWidth=$width/$height*$newHeight;
+					          				} else {
+					          					$newWidth=$this->maxWidth;
+					          					$newHeight=$height/$width*$newWidth;
+					          				}
+											$big= ImageCreateFromPNG($pngFilename);
+											$thumb= imagecreatetruecolor($newWidth,$newHeight);
+											// true color images seem to have by default bgcolor black: change this to transparent 
+											imagesavealpha($thumb, true);
+											$trans_colour = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
+											imagefill($thumb, 0, 0, $trans_colour);
+	    										
+											imagecopyresampled($thumb,$big,0,0,0,0,$newWidth,$newHeight,$width,$height);
+											imagepng($thumb,$pngThumbFilename);*/
+					          			
+				          			}
+			            		}
+			            			
+			            	} 
+		          		}
+	
+		        	}
+		        }
+		        closedir($dh);
+		    }
+		}
+		
+	}
+	/**
+	 * This function will run a command and show the output as soon as it receives anything
+	 * from the program invoked.
+	 * It also shows error out (also used for status info), as it redirects stderr to stdout (2>&1)
+	 * In windows, it takes care of inserting the quotes to handle directories with spaces
+	 *    
+	 * */
+	private function myExec($cmd, $args, $message=null) {
+		
+		if (strpos($cmd," ")!==false) {
+			$cmd=$this->opsysQuotes.$cmd.$this->opsysQuotes;
+		}
+		$args=$args." 2>&1"; //info on inkscape command line on windows http://kaioa.com/node/42, http://kaioa.com/node/63
+		$msgToOutput="";
+		if ($message!=null) {
+			$msgToOutput="($message)";
+		}
+		$this->logger->shout("\nExecuting: $cmd $args $msgToOutput\n");
+		
+		$fp = popen("{$this->opsysQuotes}$cmd $args{$this->opsysQuotes}", "r"); //the args can contain paths, so they have to be quoted, 
+		// but the whole command has to be quoted as well in case both the cmd and the args contain directories with spaces.
+	    while(!feof($fp))
+	    {
+	        // send what has been read from the program to the console
+	        $this->logger->shout(fread($fp, 1024));
+	        // flush, in case any output should be cached somewhere
+	        flush();
+	    }
+	    fclose($fp);
+
+	}
+	
+	private function prompt($prompt) {
+		echo $prompt;
+		$fp = fopen('php://stdin', 'r');
+		return trim(fgets(STDIN));
+	}
+	
+	private function checkProgramme($name, $defaultPath) {
+		if (!file_exists($defaultPath)) {
+			return $this->prompt("Where is your $name (not found in $defaultPath)?");
+		} else {
+			return $defaultPath;
+		}
+	}
+	
+	private function checkPrerequisites() {
+		$this->path_wget=$this->checkProgramme("wget", $this->path_wget);
+		$this->path_tar=$this->checkProgramme("tar", $this->path_tar);
+		$this->path_bunzip=$this->checkProgramme("bunzip2", $this->path_bunzip);
+		$this->path_gzip=$this->checkProgramme("gzip", $this->path_gzip);
+		$this->path_bzip=$this->checkProgramme("bzip", $this->path_bzip);
+		$this->path_zip=$this->checkProgramme("zip", $this->path_zip);
+		$this->path_inkscape=$this->checkProgramme("inkscape", $this->path_inkscape);
+		if ($this->doRsync) {
+			$this->path_rsync=$this->checkProgramme("rsync", $this->path_rsync);
+		}
+
+		
+	}
+	
+	
+	public function run() {
+		$this->version=$this->prompt("Release version (e.g. 0.19):");
+		$this->HTMLpreview=new HTMLPreviewBuilder($this->logger, $this->version);
+		$this->doDownload=true;
+		$this->doUnzip=true;
+		if (file_exists("daily_SVG_snapshot.tar.bz2")) {
+			$this->doDownload=false;
+			$shallDownload=$this->prompt("Create n)ew release, u)nzip and continue already downloaded daily_SVG_snapshot.tar.bz2 or c)ontinue previous run after unzip:");
+			
+			if (($shallDownload=="n")||($shallDownload=="N")) {
+				$this->doDownload=true;
+				$this->doUnzip=true;
+			}			
+			if (($shallDownload=="u")||($shallDownload=="U")) {
+				$this->doDownload=false;
+				$this->doUnzip=true;
+			}			
+			if (($shallDownload=="c")||($shallDownload=="C")) {
+				$this->doDownload=false;
+				$this->doUnzip=false;
+			}			
+		}
+		$rsyncResponse=$this->prompt("Upload release after creation? This will require a non-interactive rsync connection to your host (y/n)?:");
+		if (($rsyncResponse=="y")||($rsyncResponse=="Y")) {
+			$this->rsyncUser=$this->prompt("Upload user name:");
+			$this->rsyncHost=$this->prompt("Upload host name:");
+			$this->rsyncDir=$this->prompt("Upload directory (please include trailing slash, e.g. /var/www/):");
+			$this->doRsync=true;
+		}
+		$this->checkPrerequisites();
+		
+		if ($this->doDownload) {
+			$this->logger->shoutNewStatus("Downloading");
+			if (file_exists("daily_SVG_snapshot.tar.bz2")) {
+				unlink("daily_SVG_snapshot.tar.bz2");
+			}
+			$this->myExec($this->path_wget,"http://download.openclipart.org/downloads/daily_SVG_snapshot.tar.bz2");
+		}
+		
+		$subdirname="openclipart";
+		if (!file_exists($subdirname)) {
+			mkdir($subdirname);
+		}
+		
+		if ($this->doUnzip) {
+			$this->logger->shoutNewStatus("Unzipping");
+			$this->myExec($this->path_bunzip,"-v daily_SVG_snapshot.tar.bz2", "This will take 5 minutes");
+		} 			
+		chdir($subdirname);
+		if ($this->doUnzip) {
+			$this->logger->shoutNewStatus("Untaring");
+			$this->myExec($this->path_tar,"xvf ..{$this->opsysDirSep}daily_SVG_snapshot.tar ");
+		}
+		
+		$this->logger->shoutNewStatus("Thumbnailing");
+		$this->generate_thumbnails(getcwd());
+		$this->logger->shout("Generated {$this->numThumbsGenerated} new thumbnails for {$this->numSVGsAvailable} files");
+		chdir("..");
+		$this->HTMLpreview->writeHTML(getcwd().$this->opsysDirSep."openclipart".$this->opsysDirSep);
+		$this->logger->shoutNewStatus("Taring");
+		$tarFile="openclipart{$this->version}.tar";
+		if (file_exists($tarFile)) {
+			unlink($tarFile);
+		}
+		$this->myExec($this->path_tar,"cvf $tarFile openclipart");
+		$this->logger->shoutNewStatus("BZipping");
+		$bzFile="openclipart{$this->version}.tar.bz2";
+		if (file_exists($bzFile)) {
+			unlink($bzFile);
+		}
+		$this->myExec($this->path_bzip,"-k $tarFile");
+		$this->logger->shoutNewStatus("GZipping");
+		$tgzFile="openclipart{$this->version}.tar.gz";
+		if (file_exists($tgzFile)) {
+			unlink($tgzFile);
+		}
+		$this->myExec($this->path_gzip,$tarFile);
+		
+		$this->logger->shoutNewStatus("Zipping");
+		$zipFile="openclipart{$this->version}.zip";
+		if (file_exists($zipFile)) {
+			unlink($zipFile);
+		}
+		$this->myExec($this->path_zip,"-r openclipart{$this->version}.zip openclipart");
+		if ($this->doRsync) {
+			$this->logger->shoutNewStatus("Uploading");
+			$sourceDir=getcwd();
+			$rsyncDir=substr($this->path_rsync,0,strrpos($this->path_rsync,$this->opsysDirSep));
+			chdir($rsyncDir);
+			$RsyncSourceDir=$sourceDir;
+			if ($this->opsys==1) {
+				// windows cwrsync requires ssh.exe to be in the local path which is only the case if
+				// one changes dir to the rsync programme
+				$RsyncSourceDir=str_replace("\\","/",$sourceDir);
+				// additionally, d:\\xyz would be /cygdrive/d in cwrsync
+				if ($RsyncSourceDir{1}==':') {
+					$RsyncSourceDir="/cygdrive/".$RsyncSourceDir{0}.substr($RsyncSourceDir,2);
+				}
+			}
+			
+			$this->myExec($this->path_rsync,"-avzP {$RsyncSourceDir}/$bzFile {$this->rsyncUser}@{$this->rsyncHost}:{$this->rsyncDir}");
+			$this->myExec($this->path_rsync,"-avzP {$RsyncSourceDir}/$tgzFile {$this->rsyncUser}@{$this->rsyncHost}:{$this->rsyncDir}");
+			$this->myExec($this->path_rsync,"-avzP {$RsyncSourceDir}/$zipFile {$this->rsyncUser}@{$this->rsyncHost}:{$this->rsyncDir}");
+			chdir($sourceDir);
+		}
+	}
+
+
+}
+
+$rel=new releaser();
+$rel->run();
+?>

Added: makerelease/template/css/main.css
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ makerelease/template/css/main.css	Sat Mar 28 08:46:17 2009	(r32)
@@ -0,0 +1,335 @@
+html, body, div, span, applet, object, h1, h2, h3, h4, h5, h6, p, a, em, img, strong, ol, ul, li, dl, dd, dt, form, label, input  {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    outline: 0;
+    font-style: inherit;
+    font-size: 100%;
+    font-family: inherit;
+    vertical-align: baseline;
+    background: transparent;
+}
+:focus {
+    outline: 0;
+}
+ul, ol {
+    list-style: none;
+}
+body {
+    padding: 0;
+    margin: 0;
+    font-family: Arial, Tahoma, sans-serif;
+    font-size: 9pt;
+    color: #000;
+    height: 100%;
+    background: #FFF;
+    text-align: center;
+    line-height: 1;
+}
+img {
+    border: 0;
+}
+a:link, a:visited {
+    outline: none;
+    text-decoration: none;
+    color: #ce5c00;
+}
+a:hover, a:active {
+    text-decoration: underline;
+}
+.clear {
+    clear: both;
+    font-size: 0.3pt;
+}
+.clearfix:after {
+	content: ".";
+	display: block;
+	clear: both;
+	visibility: hidden;
+	line-height: 0;
+	height: 0;
+}
+.clearfix {
+	display: inline-block;
+}
+html[xmlns] .clearfix {
+	display: block;
+}
+* html .clearfix {
+	height: 1%;
+}
+#main {
+    width: 960px;
+    text-align: left;
+    margin: 0 auto;
+    background: url(../images/bg.png) 50% 0% repeat-y;
+}
+#header {
+    height: 122px;
+    background: #e58620 url(../images/bgl.png) 0 0 repeat-x;
+    margin: 0 16px;
+    position: relative;
+}
+#logo {
+    position: absolute;
+    top: 18px;
+    left: 15px;
+    color: #FFF;
+    font-size: 30pt;
+    font-weight: bold;
+    line-height: 2;
+}
+#logo a:link, #logo a:visited {
+    color: #FFF;
+}
+#logged {
+    color: #FFF;
+    font-size: 11pt;
+    text-align: right;
+    padding: 14px 20px 20px 10px;
+}
+#mainnav {
+    border-top: 1px solid #d6792e;
+    border-bottom: 1px solid #b8bab7;
+    background: #e2e2e2 url(../images/bgl.png) 0 -123px repeat-x;
+    margin: 0 16px;
+}
+#mainnav li {
+    height: 39px;
+    line-height: 39px;
+    overflow: hidden;
+    float: left;
+    color: #2e3436;
+}
+#mainnav li a:link, #mainnav li a:visited {
+    color: #2e3436;
+    text-decoration: none;
+    display: block;
+    padding: 0 28px 0 25px;
+    font-size: 11pt;
+    background: url(../images/fornav.png) 100% 0 no-repeat;
+}
+#mainnav li a:hover, #mainnav li a:active {
+    color: #000;
+    background-color: #FFF;
+}
+#mainnav li#active {
+    color: #000;
+    background-color: #FFF;
+    text-decoration: underline;
+    font-size: 150%;
+    font-weight: bold; 
+    padding: 0 28px 0 25px;
+}
+#content {
+   margin: 0 16px;
+   padding: 30px 20px;
+   background: url(../images/shadow-rb.jpg) 50% 0 no-repeat;
+}
+#content h2 {
+    color: #ce5c00;
+    font-size: 21pt;
+    font-weight: normal;
+    letter-spacing: 1px;
+    padding: 0 0 23px 0;
+}
+#content h2 img {
+    position: relative;
+    top: 3px;
+}
+#sidebar-nav li a:link, #sidebar-nav li a:visited {
+    color: #555753;
+}
+#recent {
+   padding: 0 0 20px 0;
+   margin-left: 30px;
+}
+#recent strong {
+    display: block;
+    font-weight: normal;
+    font-size: 13.5pt;
+    line-height: 1.2;
+}
+#recent li {
+   color: #888a85;
+   padding: 0 0 5px 20px;
+   min-height: 1%;
+   background: url(../images/dot.png) 0 6px no-repeat;
+}
+* html #recent li {
+   height: 1%;
+}
+#recent li a:link, #recent li a:visited {
+    color: #888a85;
+}
+#recent li a:hover, #recent li a:active {
+    color: #000;
+    text-decoration: none;
+}
+#footer {
+    margin: 0 16px;
+    clear: both;
+}
+#forfooter {
+    height: 150px;
+    background: #e17f1a url(../images/bgl.png) 0 -357px repeat-x;
+}
+#forfooter dl {
+    float: left;
+    width: 33%;
+    padding: 34px 0 0 0;
+    color: #FFF;
+    font-size: 8.5pt;
+    line-height: 1.2;
+}
+#forfooter dt {
+    text-align: center;
+    height: 50px;
+    padding: 0 20px;
+}
+#forfooter dt a:link, #forfooter dt a:visited {
+    color: #FFF;
+    font-size: 9pt;
+}
+#forfooter dd {
+    padding: 10px 20px 5px;
+    text-align: justify;
+}
+#links {
+    height: 50px;
+    background: #4f514d url(../images/bgl.png) 0 -510px repeat-x;
+    color: #FFF;
+    line-height: 50px;
+    font-size: 7.5pt;
+    text-align: center;
+}
+#links a:link, #links a:visited {
+    color: #FFF;
+    text-decoration: none;
+}
+#links a:hover, #links a:active {
+    text-decoration: underline;
+}
+
+/* For recent */
+
+#sidebar-r {
+    width: 322px;
+    float: right;
+    margin-right: -14px;
+}
+* html #sidebar-r {
+    display: inline;
+}
+#p-tags, #categories, #stats {
+    background: url(../images/s-b.png) -322px 0 repeat-y;
+    margin: 0 0 18px 0;
+}
+#p-tags h3, #categories h3, #stats h3 {
+    background: url(../images/s-b.png) 0 0 no-repeat;
+    color: #888a85;
+    font-size: 11pt;
+    font-weight: bold;
+    line-height: 1.5;
+    padding: 12px 17px 0;
+}
+#p-tags ul {
+    background: url(../images/s-b.png) -644px 100% no-repeat;
+    padding: 0 17px 12px;
+    font-size: 16pt;
+}
+#p-tags ul li {
+    display: inline;
+    padding: 0 12px 0 0;
+    line-height: 1.3;
+}
+#p-tags ul a:link, #p-tags ul a:visited {
+    text-decoration: underline;
+}
+#p-tags ul a:hover, #p-tags ul a:active {
+    text-decoration: none;
+}
+#p-tags .t1 {
+    font-size: 100%;
+}
+#p-tags .t2 {
+    font-size: 80%;
+}
+#p-tags .t3 {
+    font-size: 60%;
+}
+#p-tags .t4 {
+    font-size: 40%;
+}
+#categories div {
+    background: url(../images/s-b.png) -644px 100% no-repeat;
+}
+#categories a:link, #categories a:visited {
+    color: #000;
+}
+#categories a:hover, #categories a:active {
+    text-decoration: underline;
+}
+#categories ul {
+    float: left;
+    padding: 5px 0 15px 17px;
+    font-size: 10pt;
+    line-height: 1.5;
+}
+#categories ul li {
+    width: 89px;
+}
+#stats div {
+    background: url(../images/s-b.png) -644px 100% no-repeat;
+    padding: 5px 0 15px;
+}
+#stats h3 {
+    color: #ce5c00;
+    font-size: 10.5pt;
+}
+#stats div dl {
+    background: url(../images/stat.png) 26px 8px no-repeat;
+    padding: 0 25px 0 115px;
+    line-height: 1.5;
+    font-size: 10.5pt;
+}
+#stats div dt {
+    width: 130px;
+    float: left;
+    clear: both;
+    color: #555753;
+    font-weight: bold;
+}
+#stats div dd {
+    text-align: right;
+    color: #b2b3b0;
+}
+.r-img {
+    width: 280px;
+    float: left;
+    padding: 0 0 15px;
+    border-right: 5px solid #FFF;
+}
+.r-img div {
+    float: left;
+    width: 110px;
+}
+.r-img h4 {
+    font-size: 11pt;
+    line-height: 1.2;
+    padding: 3px 0 3px;
+    font-weight: bold;
+}
+.r-img p {
+    color: #555753;
+    font-size: 9pt;
+    line-height: 1.1;
+}
+.r-img p a:link, .r-img p a:visited {
+    color: #555753;
+    font-weight: bold;
+}
+.r-img .stars {
+    display: block;
+    margin-top: 5px;
+}

Added: makerelease/template/images/bg.png
==============================================================================
Binary file. No diff available.

Added: makerelease/template/images/bgl.png
==============================================================================
Binary file. No diff available.

Added: makerelease/template/images/bullet.gif
==============================================================================
Binary file. No diff available.

Added: makerelease/template/images/logo.jpg
==============================================================================
Binary file. No diff available.

Added: makerelease/template/images/openclipart.png
==============================================================================
Binary file. No diff available.

Added: makerelease/template/images/publicdomain.png
==============================================================================
Binary file. No diff available.

Added: makerelease/template/images/s-b.png
==============================================================================
Binary file. No diff available.

Added: makerelease/template/index.html
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ makerelease/template/index.html	Sat Mar 28 08:46:17 2009	(r32)
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
+
+
+	<title>Open ClipArt Library</title>
+	<link href="css/main.css" type="text/css" rel="stylesheet">
+
+	<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
+	
+</head><body>
+<div id="main">
+	<div id="header">
+		<h1 id="logo">
+			<a href="http://www.openclipart.org"><img src="images/logo.jpg" alt="Open ClipArt Library"></a>
+		</h1>
+		<div id='logged'>
+		  [title]
+		</div>
+	</div>
+	<ul id="mainnav" class="clearfix">
+	[pages]
+	</ul>
+	<div id="content" class="clearfix">
+	<h2>[subtitle]</h2>
+		<div id="recent-img">
+			[thumbnails]
+
+
+		</div>
+	</div>
+	<div id="footer">
+		<div id="forfooter" class="clearfix">
+			<dl>
+				<dt><a href="http://creativecommons.org/licenses/publicdomain/"><img src="images/publicdomain.png" alt="Public Domain"></a></dt>
+				<dd>The actual clipart content on open clipart library is Public domain</dd>
+			</dl>
+			<dl>
+				<dt><a href="http://www.openclipart.org"><img src="images/openclipart.png" alt="Open ClipArt Library"></a></dt>
+				<dd>Open Clipart Library is made with ccHost, licensed under CC-GNU-GPL</dd>
+			</dl>
+		</div>
+		<div id="links">
+		</div>
+	</div>
+</div>
+</body></html>



More information about the clipart mailing list