Attachment 'Gallery.patch'

Download

   1 --- C:\download\pmswiki\gallery\macro\Gallery-087.py	2006-07-24 11:26:59.296454000 +0200
   2 +++ Gallery.py	2006-07-27 13:34:11.325534400 +0200
   3 @@ -7,15 +7,15 @@
   4      @license: GPL
   5  
   6      Special thanks go to: 
   7 -	My beautiful wife Jenny: For keeping the kids at bay long enough for me to code it :-)
   8 +        My beautiful wife Jenny: For keeping the kids at bay long enough for me to code it :-)
   9          Adam Shand: For his GallerySoftware feature wish list, support, ideas and suggestions.
  10  
  11      Usage: [[Gallery(key1=value1,key2=value2....)]]
  12  
  13        where the following keys are valid:
  14 -	  thumbnailwidth     = no of pixels wide to make the thumbnails
  15 -	  webnailwidth       = width in pixels of the web sized images
  16 -	  numberofcolumns    = no of columns used in the thumbnail table
  17 +          thumbnailwidth     = no of pixels wide to make the thumbnails
  18 +          webnailwidth       = width in pixels of the web sized images
  19 +          numberofcolumns    = no of columns used in the thumbnail table
  20  
  21      Bugs:
  22  
  23 @@ -35,17 +35,17 @@
  24        Handling of video formats 
  25  
  26      Speed up:
  27 -	# When you get really sick of how slow the moinmoin image system is, 
  28 -	# you can either reconfigure your setup for FastCGI (highly recommended)
  29 -	# or: set the following variables in your wikiconfig.py
  30 -	gallerytempdir (the path to a writable directory)
  31 -	gallerytempurl (the path in your webservers url space where this directory can be read from)
  32 +        # When you get really sick of how slow the moinmoin image system is, 
  33 +        # you can either reconfigure your setup for FastCGI (highly recommended)
  34 +        # or: set the following variables in your wikiconfig.py
  35 +        gallerytempdir (the path to a writable directory)
  36 +        gallerytempurl (the path in your webservers url space where this directory can be read from)
  37          eg:
  38 -	    gallerytempdir='/var/www/html/nails'
  39 -	    gallerytempurl='/nails'
  40 -	  or maybe:
  41 -	    gallerytempurl=url_prefix+'/nails'
  42 -	# There are other ways of getting speedups for attachments, but these methods are the safest (IMHO)
  43 +            gallerytempdir='/var/www/html/nails'
  44 +            gallerytempurl='/nails'
  45 +          or maybe:
  46 +            gallerytempurl=url_prefix+'/nails'
  47 +        # There are other ways of getting speedups for attachments, but these methods are the safest (IMHO)
  48  
  49  """
  50  
  51 @@ -89,24 +89,24 @@
  52  
  53  def version():
  54          return(' version <b>'+Globs.version+'</b> by Simon D. Ryan.'+\
  55 -	'<br>Copyright 2004,2005 Simon D. Ryan<br>Gallery is a MoinMoin macro and is released under the '+\
  56 -	'<a href="http://www.gnu.org/licenses/gpl.txt">GPL</a>\n'+\
  57 -	'<p>Upload some images as attachments to <a href="'+Globs.baseurl+Globs.pagename+'?action=AttachFile"><b>'+Globs.pagename+'</b></a> and I will generate a gallery for you.')
  58 +        '<br>Copyright 2004,2005 Simon D. Ryan<br>Gallery is a MoinMoin macro and is released under the '+\
  59 +        '<a href="http://www.gnu.org/licenses/gpl.txt">GPL</a>\n'+\
  60 +        '<p>Upload some images as attachments to <a href="'+Globs.baseurl+Globs.pagename+'?action=AttachFile"><b>'+Globs.pagename+'</b></a> and I will generate a gallery for you.')
  61  
  62  # Thanks to denny<at>ece.arizona.edu
  63  # This can be replaced with a static translation table to speed things up (later)
  64  def mktrans():
  65          # Allow only letters and digits and a few other valid file characters
  66 -	alphanumeric=string.letters+string.digits+'.,-_\'!"'
  67 -	source_string=""
  68 -	destination_string=""
  69 -	for i in range(256):
  70 -		source_string=source_string+chr(i)
  71 -		if chr(i) in alphanumeric:
  72 -			destination_string=destination_string+chr(i)
  73 -		else:
  74 -			destination_string=destination_string+' '
  75 -	return string.maketrans(source_string,destination_string)
  76 +        alphanumeric=string.letters+string.digits+'.,-_\'!"'
  77 +        source_string=""
  78 +        destination_string=""
  79 +        for i in range(256):
  80 +                source_string=source_string+chr(i)
  81 +                if chr(i) in alphanumeric:
  82 +                        destination_string=destination_string+chr(i)
  83 +                else:
  84 +                        destination_string=destination_string+' '
  85 +        return string.maketrans(source_string,destination_string)
  86  
  87  def qlink(pagename, querystring, query, description=''):
  88      # Returns a hyperlink constructed as a form query on pagename
  89 @@ -124,20 +124,20 @@
  90      back,forward='',''
  91      if not index==0:
  92          # We are not the first so we can provide a back link
  93 -	back=qlink(Globs.pagename, querystring, positions[index-1], 'PREV')
  94 +        back=qlink(Globs.pagename, querystring, positions[index-1], 'PREV')
  95      if not index==len(positions)-1:
  96          # We are not the last so we can provide a forward link
  97 -	forward=qlink(Globs.pagename, querystring, positions[index+1], 'NEXT')
  98 +        forward=qlink(Globs.pagename, querystring, positions[index+1], 'NEXT')
  99      return '<table><tr><td>'+back+'</td><td>'+thumbs+'</td><td>'+forward+'</td></tr></table>'
 100  
 101  def toolbar(target,naillevel):
 102      if Globs.admin:
 103 -	rotateleft='<input type="submit" name="rotate" value="rotate left">'
 104 -	rotateright='<input type="submit" name="rotate" value="rotate right">'
 105 -	deleteitem='<input type="submit" name="delete" value="delete">'
 106 -	htarget='<input type=hidden value="'+target+'" name="'+naillevel+'">'
 107 -	compat='<input type=hidden value="show" name="action">'
 108 -	return '<form METHOD=POST><table><tr><td>'+rotateleft+'</td><td>'+rotateright+'</td><td>'+deleteitem+'</td></tr></table>\n'+htarget+compat+'</form>'
 109 +        rotateleft='<input type="submit" name="rotate" value="rotate left">'
 110 +        rotateright='<input type="submit" name="rotate" value="rotate right">'
 111 +        deleteitem='<input type="submit" name="delete" value="delete">'
 112 +        htarget='<input type=hidden value="'+target+'" name="'+naillevel+'">'
 113 +        compat='<input type=hidden value="show" name="action">'
 114 +        return '<form METHOD=POST><table><tr><td>'+rotateleft+'</td><td>'+rotateright+'</td><td>'+deleteitem+'</td></tr></table>\n'+htarget+compat+'</form>'
 115      else:
 116          return ''
 117  
 118 @@ -147,33 +147,33 @@
 119  
 120      # Make sure our temp directory is writable and generate a message if it isn't
 121      try:
 122 -	if not os.path.isfile(Globs.gallerytempdir+'/tmp.writetest'):
 123 -	    # There is probably a less ugly was to do this using stat (later)
 124 -	    open(Globs.gallerytempdir+'/tmp.writetest','w').close()
 125 +        if not os.path.isfile(Globs.gallerytempdir+'/autogenerated-writetest'):
 126 +            # There is probably a less ugly was to do this using stat (later)
 127 +            open(Globs.gallerytempdir+'/autogenerated-writetest','w').close()
 128      except IOError:
 129          message('I had some trouble writing to the temp directory. Is it owned by me and writable?',0)
 130  
 131      # Don't go further if there is a lock in place
 132 -    if os.path.isfile(Globs.attachmentdir+'/tmp.lock'):
 133 +    if os.path.isfile(Globs.attachmentdir+'/autogenerated-lock'):
 134          message("I'm currently busy generating thumbnails and webnails, please try again later.",0)
 135 -	return ''
 136 +        return ''
 137  
 138      # Find the convert binary in standard locations
 139      if not globals().has_key('Image'):
 140 -	if not os.path.isfile('/usr/bin/convert'):
 141 -	    if not os.path.isfile('/usr/X11R6/bin/convert'):
 142 -		message('<b>Please install ImageMagick or PIL so I can build thumbnails and webnails</b><p>',0)
 143 -		return
 144 -	    else:
 145 -		Globs.convertbin='/usr/X11R6/bin/convert'
 146 -	else:
 147 -	    Globs.convertbin='/usr/bin/convert'
 148 +        if not os.path.isfile('/usr/bin/convert'):
 149 +            if not os.path.isfile('/usr/X11R6/bin/convert'):
 150 +                message('<b>Please install ImageMagick or PIL so I can build thumbnails and webnails</b><p>',0)
 151 +                return
 152 +            else:
 153 +                Globs.convertbin='/usr/X11R6/bin/convert'
 154 +        else:
 155 +            Globs.convertbin='/usr/bin/convert'
 156      else:
 157          # Use Python Imaging Library
 158          Globs.convertbin='Image'
 159  
 160      # Create a lock file in the attachments dir so we can always remotely remove it if there is a problem
 161 -    open(Globs.attachmentdir+'/tmp.lock','w').close()
 162 +    open(Globs.attachmentdir+'/autogenerated-lock','w').close()
 163      
 164      import time
 165      tstart=time.time()
 166 @@ -183,69 +183,69 @@
 167      for item in items:
 168          basename,prefix,width=item
 169  
 170 -	# Check to see if we tarry too long on the road
 171 -	if tstart and (time.time()-tstart) > Globs.timeout:
 172 -	    # This is taking waaay too long let us fork and detach else the browser will time out or worse, the webserver may kill us
 173 -	    pid = os.fork()
 174 -	    if pid != 0:
 175 -	        # We are in the parent so we break out
 176 -		message('The thumbnail generation process was taking too long so it has been backgrounded. Please try again later to see the full set of thumbnails',0)
 177 -		break
 178 -	    else:
 179 -		# Once we are forked we want to ignore the time
 180 -		tstart=''
 181 -	        # Break away from the controlling terminal, so that the web server cannot kill us by killing our parent
 182 -	        os.setsid()
 183 -		# Fork again so we can get away without a controlling terminal
 184 -		pid2 = os.fork()
 185 -		if (pid2 != 0):
 186 -		    os._exit(0)
 187 -		else:
 188 -		    # Close all open file descriptors
 189 -		    try:
 190 -		        max_fd = os.sysconf("SC_OPEN_MAX")
 191 -		    except (AttributeError, ValueError):
 192 -		        max_fd = 256
 193 -		    for fd in range(0, max_fd):
 194 +        # Check to see if we tarry too long on the road
 195 +        if tstart and (time.time()-tstart) > Globs.timeout:
 196 +            # This is taking waaay too long let us fork and detach else the browser will time out or worse, the webserver may kill us
 197 +            pid = os.fork()
 198 +            if pid != 0:
 199 +                # We are in the parent so we break out
 200 +                message('The thumbnail generation process was taking too long so it has been backgrounded. Please try again later to see the full set of thumbnails',0)
 201 +                break
 202 +            else:
 203 +                # Once we are forked we want to ignore the time
 204 +                tstart=''
 205 +                # Break away from the controlling terminal, so that the web server cannot kill us by killing our parent
 206 +                os.setsid()
 207 +                # Fork again so we can get away without a controlling terminal
 208 +                pid2 = os.fork()
 209 +                if (pid2 != 0):
 210 +                    os._exit(0)
 211 +                else:
 212 +                    # Close all open file descriptors
 213 +                    try:
 214 +                        max_fd = os.sysconf("SC_OPEN_MAX")
 215 +                    except (AttributeError, ValueError):
 216 +                        max_fd = 256
 217 +                    for fd in range(0, max_fd):
 218                          try:
 219 -			    os.close(fd)
 220 -			except OSError:
 221 -			    pass
 222 -		    # Redirect the standard file descriptors to /dev/null
 223 -		    os.open("/dev/null", os.O_RDONLY)    # stdin
 224 -		    os.open("/dev/null", os.O_RDWR)      # stdout
 225 -		    os.open("/dev/null", os.O_RDWR)      # stderr
 226 -
 227 -		    # Now we are finally free to continue the conversions as a daemon
 228 -		    # If you would like to know more about the above, see:
 229 -		    #   Advanced Programming in the Unix Environment: W. Richard Stevens
 230 -		    # It is also explained in:
 231 -		    #   Unix Network Programming (Volume 1): W. Richard Stevens
 232 -
 233 -	#pathtooriginal='"'+Globs.attachmentdir+'/'+Globs.originals[basename]+'"'
 234 -	pathtooriginal='"'+os.path.join(Globs.attachmentdir,Globs.originals[basename])+'"'
 235 -	# Warning:
 236 -	# Take care if modifying the following line, 
 237 -	# you may inadvertantly overwrite your original images!
 238 -	if not Globs.convertbin == 'Image':
 239 -	    #print 'building nail for '+pathtooriginal
 240 -	    #convout=commands.getoutput('%s -geometry %s \"%s\" "\"%s/%s.%s.jpg\""' % (Globs.convertbin,width+'x'+width,pathtooriginal,Globs.gallerytempdir,prefix,basename))
 241 -	    convout=commands.getoutput('%s -geometry %s %s "%s/%s.%s.jpg"' % (Globs.convertbin,width+'x'+width,pathtooriginal,Globs.gallerytempdir,prefix,basename))
 242 -	    convout=''
 243 -	    convout=string.strip(convout)
 244 -	    if convout:
 245 -		message(convout)
 246 -	else:
 247 -	    # Use PIL  (strip off the "")
 248 -	    im = Image.open(pathtooriginal[1:-1])
 249 -	    # Use the integer version for PIL
 250 -	    width=string.atoi(width)
 251 -	    im.thumbnail((width,width), Image.ANTIALIAS)
 252 -	    im.save(os.path.join(Globs.gallerytempdir,prefix)+'.'+basename+'.jpg','JPEG')
 253 +                            os.close(fd)
 254 +                        except OSError:
 255 +                            pass
 256 +                    # Redirect the standard file descriptors to /dev/null
 257 +                    os.open("/dev/null", os.O_RDONLY)    # stdin
 258 +                    os.open("/dev/null", os.O_RDWR)      # stdout
 259 +                    os.open("/dev/null", os.O_RDWR)      # stderr
 260 +
 261 +                    # Now we are finally free to continue the conversions as a daemon
 262 +                    # If you would like to know more about the above, see:
 263 +                    #   Advanced Programming in the Unix Environment: W. Richard Stevens
 264 +                    # It is also explained in:
 265 +                    #   Unix Network Programming (Volume 1): W. Richard Stevens
 266 +
 267 +        #pathtooriginal='"'+Globs.attachmentdir+'/'+Globs.originals[basename]+'"'
 268 +        pathtooriginal='"'+os.path.join(Globs.attachmentdir,Globs.originals[basename])+'"'
 269 +        # Warning:
 270 +        # Take care if modifying the following line, 
 271 +        # you may inadvertantly overwrite your original images!
 272 +        if not Globs.convertbin == 'Image':
 273 +            #print 'building nail for '+pathtooriginal
 274 +            #convout=commands.getoutput('%s -geometry %s \"%s\" "\"%s/%s.%s.jpg\""' % (Globs.convertbin,width+'x'+width,pathtooriginal,Globs.gallerytempdir,prefix,basename))
 275 +            convout=commands.getoutput('%s -geometry %s %s "%s/%s.%s.jpg"' % (Globs.convertbin,width+'x'+width,pathtooriginal,Globs.gallerytempdir,prefix,basename))
 276 +            convout=''
 277 +            convout=string.strip(convout)
 278 +            if convout:
 279 +                message(convout)
 280 +        else:
 281 +            # Use PIL  (strip off the "")
 282 +            im = Image.open(pathtooriginal[1:-1])
 283 +            # Use the integer version for PIL
 284 +            width=string.atoi(width)
 285 +            im.thumbnail((width,width), Image.ANTIALIAS)
 286 +            im.save(os.path.join(Globs.gallerytempdir,prefix)+'.'+basename+'.jpg','JPEG')
 287  
 288      if (not pid) and (not pid2):
 289 -	# Release the lock file when finished
 290 -	os.unlink(Globs.attachmentdir+'/tmp.lock')
 291 +        # Release the lock file when finished
 292 +        os.unlink(Globs.attachmentdir+'/autogenerated-lock')
 293  
 294      # We have built thumbnails so we can deposit an indicator file to prevent rebuilding next time
 295      if not os.path.isfile(Globs.attachmentdir+'/delete.me.to.regenerate.thumbnails.and.webnails'):
 296 @@ -255,107 +255,107 @@
 297  def deletefromdisk(target):
 298      # Rotate the images
 299      # Don't go further if there is a lock in place
 300 -    if os.path.isfile(Globs.attachmentdir+'/tmp.lock'):
 301 +    if os.path.isfile(Globs.attachmentdir+'/autogenerated-lock'):
 302          message("I'm currently busy generating thumbnails and webnails. Please try your delete request again later.",0)
 303 -	return ''
 304 +        return ''
 305      # Ok do the actual delete 
 306      if 1:
 307          # Delete first the temp dir webnail and thumbnail
 308 -	try:
 309 -	    os.unlink(Globs.gallerytempdir+'/tmp.webnail.'+target+'.jpg')
 310 -	except:
 311 -	    pass
 312 -	try:
 313 -	    os.unlink(Globs.gallerytempdir+'/tmp.thumbnail.'+target+'.jpg')
 314 -	except:
 315 -	    pass
 316 -	try:
 317 -	    os.unlink(Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg')
 318 -	except:
 319 -	    pass
 320 -
 321 -	# Now delete the original (except we actually just move it to /tmp) 
 322 -	# TODO: insert a random number in the destination filename to cope with deleting files with same name
 323 -	origfn=Globs.originals[target]
 324 -	try:
 325 -	    #shutil.copy(Globs.attachmentdir+'/'+origfn,'/tmp/deleted.'+origfn)
 326 -	    shutil.copy(Globs.attachmentdir+'/'+origfn,'/tmp/'+origfn)
 327 -	    os.unlink(Globs.attachmentdir+'/'+origfn)
 328 -	except:
 329 -	    pass
 330 -	try:
 331 -	    #shutil.copy(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt','/tmp/deleted.tmp.annotation.'+target+'.txt')
 332 -	    shutil.copy(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt','/tmp/tmp.annotation.'+target+'.txt')
 333 -	    os.unlink(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt')
 334 -	except:
 335 -	    pass
 336 +        try:
 337 +            os.unlink(Globs.gallerytempdir+'/autogenerated-webnail.'+target+'.jpg')
 338 +        except:
 339 +            pass
 340 +        try:
 341 +            os.unlink(Globs.gallerytempdir+'/autogenerated-thumbnail.'+target+'.jpg')
 342 +        except:
 343 +            pass
 344 +        try:
 345 +            os.unlink(Globs.gallerytempdir+'/autogenerated-rotated.'+target+'.jpg')
 346 +        except:
 347 +            pass
 348 +
 349 +        # Now delete the original (except we actually just move it to /tmp) 
 350 +        # TODO: insert a random number in the destination filename to cope with deleting files with same name
 351 +        origfn=Globs.originals[target]
 352 +        try:
 353 +            #shutil.copy(Globs.attachmentdir+'/'+origfn,'/tmp/deleted.'+origfn)
 354 +            shutil.copy(Globs.attachmentdir+'/'+origfn,'/tmp/'+origfn)
 355 +            os.unlink(Globs.attachmentdir+'/'+origfn)
 356 +        except:
 357 +            pass
 358 +        try:
 359 +            #shutil.copy(Globs.attachmentdir+'/autogenerated-annotation.'+target+'.txt','/tmp/deleted.tmp.annotation.'+target+'.txt')
 360 +            shutil.copy(Globs.attachmentdir+'/autogenerated-annotation.'+target+'.txt','/tmp/autogenerated-annotation.'+target+'.txt')
 361 +            os.unlink(Globs.attachmentdir+'/autogenerated-annotation.'+target+'.txt')
 362 +        except:
 363 +            pass
 364  
 365  def rotate(target,direction):
 366      # Rotate the images
 367      # Don't go further if there is a lock in place
 368 -    if os.path.isfile(Globs.attachmentdir+'/tmp.lock'):
 369 +    if os.path.isfile(Globs.attachmentdir+'/autogenerated-lock'):
 370          message("I'm currently busy generating thumbnails and webnails. Please try your rotate request again later.",0)
 371 -	return ''
 372 +        return ''
 373  
 374      # Find the correct binary
 375      if not globals().has_key('Image'):
 376 -	if not os.path.isfile('/usr/bin/mogrify'):
 377 -	    if not os.path.isfile('/usr/X11R6/bin/mogrify'):
 378 -		message('<b>Please install ImageMagick so I can build thumbnails and webnails</b><p>',0)
 379 -		return
 380 -	    else:
 381 -		Globs.convertbin='/usr/X11R6/bin/mogrify'
 382 -	else:
 383 -	    Globs.convertbin='/usr/bin/mogrify'
 384 +        if not os.path.isfile('/usr/bin/mogrify'):
 385 +            if not os.path.isfile('/usr/X11R6/bin/mogrify'):
 386 +                message('<b>Please install ImageMagick so I can build thumbnails and webnails</b><p>',0)
 387 +                return
 388 +            else:
 389 +                Globs.convertbin='/usr/X11R6/bin/mogrify'
 390 +        else:
 391 +            Globs.convertbin='/usr/bin/mogrify'
 392      else:
 393          Globs.convertbin = 'Image'
 394  
 395      # Do the actual rotations
 396      if direction=='rotate right':
 397 -	degs='90'
 398 +        degs='90'
 399      else:
 400 -	degs='270'
 401 +        degs='270'
 402      if not Globs.convertbin == 'Image':
 403 -	convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/tmp.webnail.'+target+'.jpg"')
 404 -	convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/tmp.thumbnail.'+target+'.jpg"')
 405 -	# Don't bother rotating the original. Since we don't want to reduce its quality incase it is used for printing
 406 -	#if not os.path.isfile(Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg'):
 407 -	#    # Generate from original
 408 -	#    pathtooriginal=Globs.attachmentdir+'/'+Globs.originals[target]
 409 -	#    shutil.copy(pathtooriginal,Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg')
 410 -	#convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg"')
 411 +        convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/autogenerated-webnail.'+target+'.jpg"')
 412 +        convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/autogenerated-thumbnail.'+target+'.jpg"')
 413 +        # Don't bother rotating the original. Since we don't want to reduce its quality incase it is used for printing
 414 +        #if not os.path.isfile(Globs.gallerytempdir+'/autogenerated-rotated.'+target+'.jpg'):
 415 +        #    # Generate from original
 416 +        #    pathtooriginal=Globs.attachmentdir+'/'+Globs.originals[target]
 417 +        #    shutil.copy(pathtooriginal,Globs.gallerytempdir+'/autogenerated-rotated.'+target+'.jpg')
 418 +        #convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/autogenerated-rotated.'+target+'.jpg"')
 419      else:
 420 -	# Use PIL  (strip off the "")
 421 -	if direction=='rotate right':
 422 -	    degs=270.0
 423 -	else:
 424 -	    degs=90.0
 425 -	im = os.path.join(Globs.gallerytempdir,'tmp.webnail.')+target+'.jpg'
 426 -	imw = Image.open(im)
 427 -	imw.rotate(degs).save(im,'JPEG')
 428 -	im = os.path.join(Globs.gallerytempdir,'tmp.thumbnail.')+target+'.jpg'
 429 -	imw = Image.open(im)
 430 -	imw.rotate(degs).save(im,'JPEG')
 431 -	imo = os.path.join(Globs.gallerytempdir,'tmp.rotated.')+target+'.jpg'
 432 -	if not os.path.isfile(Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg'):
 433 -	    # Generate from original
 434 -	    im=Globs.attachmentdir+'/'+Globs.originals[target]
 435 -	else:
 436 -	    im = imo
 437 -	imw = Image.open(im)
 438 -	imw.rotate(degs).save(imo,'JPEG')
 439 +        # Use PIL  (strip off the "")
 440 +        if direction=='rotate right':
 441 +            degs=270.0
 442 +        else:
 443 +            degs=90.0
 444 +        im = os.path.join(Globs.gallerytempdir,'autogenerated-webnail.')+target+'.jpg'
 445 +        imw = Image.open(im)
 446 +        imw.rotate(degs).save(im,'JPEG')
 447 +        im = os.path.join(Globs.gallerytempdir,'autogenerated-thumbnail.')+target+'.jpg'
 448 +        imw = Image.open(im)
 449 +        imw.rotate(degs).save(im,'JPEG')
 450 +        imo = os.path.join(Globs.gallerytempdir,'autogenerated-rotated.')+target+'.jpg'
 451 +        if not os.path.isfile(Globs.gallerytempdir+'/autogenerated-rotated.'+target+'.jpg'):
 452 +            # Generate from original
 453 +            im=Globs.attachmentdir+'/'+Globs.originals[target]
 454 +        else:
 455 +            im = imo
 456 +        imw = Image.open(im)
 457 +        imw.rotate(degs).save(imo,'JPEG')
 458  
 459  def getannotation(target):
 460      # Annotations are stored as a file for now (later to be stored in images)
 461      atext=''
 462      if Globs.annotated.has_key(target):
 463          try:
 464 -	    atext=open(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt').readline()
 465 -	except:
 466 -	    atext=''
 467 -	message('was annotated')
 468 +            atext=open(Globs.attachmentdir+'/autogenerated-annotation.'+target+'.txt').readline()
 469 +        except:
 470 +            atext=''
 471 +        message('was annotated')
 472      else:
 473 -	message('was not annotated')
 474 +        message('was not annotated')
 475      # replace double quotes with the html escape so quoted annotations appear
 476      return string.replace(atext,'"','&quot;')
 477  
 478 @@ -384,24 +384,24 @@
 479  
 480      # process arguments
 481      if args:
 482 -	# Arguments are comma delimited key=value pairs
 483 -	sargs=string.split(args,',')
 484 -	for item in sargs:
 485 -	    sitem=string.split(item,'=')
 486 -	    if len(sitem)==2:
 487 -		key,value=sitem[0],sitem[1]
 488 -		if key=='thumbnailwidth':
 489 -		    Globs.thumbnailwidth=value
 490 -		elif key=='webnailwidth':
 491 -		    Globs.webnailwidth=value
 492 -		elif key=='numberofcolumns':
 493 -		    try:
 494 -			Globs.numberofcolumns=string.atoi(value)
 495 -		    except TypeError:
 496 -		        pass
 497 -		# Experimental, uncomment at own risk
 498 -		#elif key=='pagename':
 499 -		#    Globs.pagename=value
 500 +        # Arguments are comma delimited key=value pairs
 501 +        sargs=string.split(args,',')
 502 +        for item in sargs:
 503 +            sitem=string.split(item,'=')
 504 +            if len(sitem)==2:
 505 +                key,value=sitem[0],sitem[1]
 506 +                if key=='thumbnailwidth':
 507 +                    Globs.thumbnailwidth=value
 508 +                elif key=='webnailwidth':
 509 +                    Globs.webnailwidth=value
 510 +                elif key=='numberofcolumns':
 511 +                    try:
 512 +                        Globs.numberofcolumns=string.atoi(value)
 513 +                    except TypeError:
 514 +                        pass
 515 +                # Experimental, uncomment at own risk
 516 +                #elif key=='pagename':
 517 +                #    Globs.pagename=value
 518  
 519      transtable=mktrans()
 520  
 521 @@ -410,10 +410,10 @@
 522      annotationmessage=''
 523      Globs.baseurl=macro.request.getBaseURL()+'/'
 524      if not Globs.pagename:
 525 -	#Globs.pagename = string.replace(macro.formatter.page.page_name,'/','_2f')
 526 -	Globs.pagename = macro.formatter.page.page_name
 527 -	# This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
 528 -	Globs.subname = string.split(Globs.pagename,'/')[-1]
 529 +        #Globs.pagename = string.replace(macro.formatter.page.page_name,'/','_2f')
 530 +        Globs.pagename = macro.formatter.page.page_name
 531 +        # This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
 532 +        Globs.subname = string.split(Globs.pagename,'/')[-1]
 533      # Hmmm. A bug in moinmoin? underscores are getting escaped. These doubly escaped pagenames are even appearing in data/pages
 534      try:
 535          # Try the old MoinMoin-1.2.x way first
 536 @@ -424,24 +424,24 @@
 537      Globs.attachmentdir = pagepath+'/attachments'
 538      Globs.galleryrotchar='?'
 539      if hasattr(macro,'cfg') and hasattr(macro.cfg,'gallerytempdir') and hasattr(macro.cfg,'gallerytempurl'):
 540 -	Globs.gallerytempdirroot=macro.cfg.gallerytempdir
 541 -	Globs.gallerytempdir=macro.cfg.gallerytempdir+'/'+Globs.pagename+'/'
 542 -	Globs.gallerytempurl=macro.cfg.gallerytempurl+'/'+Globs.pagename+'/'
 543 +        Globs.gallerytempdirroot=macro.cfg.gallerytempdir
 544 +        Globs.gallerytempdir=macro.cfg.gallerytempdir+'/'+Globs.pagename+'/'
 545 +        Globs.gallerytempurl=macro.cfg.gallerytempurl+'/'+Globs.pagename+'/'
 546      elif hasattr(wikiconfig,'gallerytempdir') and hasattr(wikiconfig,'gallerytempurl'):
 547          message('gallerytempdir and gallerytempurl found')
 548 -	Globs.gallerytempdirroot=wikiconfig.gallerytempdir
 549 -	Globs.gallerytempdir=wikiconfig.gallerytempdir+'/'+Globs.pagename+'/'
 550 -	Globs.gallerytempurl=wikiconfig.gallerytempurl+'/'+Globs.pagename+'/'
 551 +        Globs.gallerytempdirroot=wikiconfig.gallerytempdir
 552 +        Globs.gallerytempdir=wikiconfig.gallerytempdir+'/'+Globs.pagename+'/'
 553 +        Globs.gallerytempurl=wikiconfig.gallerytempurl+'/'+Globs.pagename+'/'
 554      elif hasattr(wikiconfig,'attachments'):
 555 -	Globs.gallerytempdirroot=wikiconfig.attachments['dir']
 556 -	Globs.gallerytempdir=wikiconfig.attachments['dir']+'/'+Globs.pagename+'/attachments/'
 557 -	Globs.gallerytempurl=wikiconfig.attachments['url']+'/'+Globs.pagename+'/attachments/'
 558 -	Globs.attachmentdir = Globs.gallerytempdir
 559 +        Globs.gallerytempdirroot=wikiconfig.attachments['dir']
 560 +        Globs.gallerytempdir=wikiconfig.attachments['dir']+'/'+Globs.pagename+'/attachments/'
 561 +        Globs.gallerytempurl=wikiconfig.attachments['url']+'/'+Globs.pagename+'/attachments/'
 562 +        Globs.attachmentdir = Globs.gallerytempdir
 563      else:
 564 -	Globs.gallerytempdir=Globs.attachmentdir
 565 -	Globs.gallerytempurl=Globs.subname+'?action=AttachFile&amp;do=get&amp;target='
 566 -	# MoinMoin no longer allows us to use a ? to trigger a refetch, so we pass it a &
 567 -	Globs.galleryrotchar='&'
 568 +        Globs.gallerytempdir=Globs.attachmentdir
 569 +        Globs.gallerytempurl=Globs.subname+'?action=AttachFile&amp;do=get&amp;target='
 570 +        # MoinMoin no longer allows us to use a ? to trigger a refetch, so we pass it a &
 571 +        Globs.galleryrotchar='&'
 572      if args:
 573          args=macro.request.getText(args)
 574  
 575 @@ -454,26 +454,26 @@
 576      for item in macro.form.items():
 577          if not formvals.has_key(item[0]):
 578              # Here is where we clean the untrusted web input
 579 -	    # (sometimes we get foreign keys from moinmoin when the page is edited)
 580 -	    try:
 581 -		formvals[item[0]]=string.translate(item[1][0],transtable)
 582 -	    except AttributeError:
 583 -	        pass
 584 +            # (sometimes we get foreign keys from moinmoin when the page is edited)
 585 +            try:
 586 +                formvals[item[0]]=string.translate(item[1][0],transtable)
 587 +            except AttributeError:
 588 +                pass
 589  
 590      # Add this to the end of each URL to keep some versions of moinmoin happy 
 591      if formvals.has_key('action'):
 592          if formvals['action']=='content':
 593 -	    # translate content action to print action for now
 594 -	    Globs.bcomp='&action=print'
 595 -	else:
 596 -	    Globs.bcomp='&action='+formvals['action']
 597 +            # translate content action to print action for now
 598 +            Globs.bcomp='&action=print'
 599 +        else:
 600 +            Globs.bcomp='&action='+formvals['action']
 601      else:
 602 -	Globs.bcomp='&action=show'
 603 +        Globs.bcomp='&action=show'
 604  
 605      # Figure out if we have delete privs
 606      try:
 607          # If a user can delete the page containing the Gallery, then they are considered a Gallery administrator
 608 -	# This probably should be configurable via a wikiconfig variable eg: galleryadminreq = <admin|delete|any>
 609 +        # This probably should be configurable via a wikiconfig variable eg: galleryadminreq = <admin|delete|any>
 610          if macro.request.user.may.delete(macro.formatter.page.page_name):
 611              Globs.admin='true'
 612      except AttributeError:
 613 @@ -484,263 +484,265 @@
 614      # Grab a list of the files in the attachment directory
 615      if os.path.isdir(Globs.attachmentdir):
 616          if Globs.gallerytempdir==Globs.attachmentdir:
 617 -	    afiles=os.listdir(Globs.attachmentdir)
 618 -	else:
 619 -	    if not os.path.isdir(Globs.gallerytempdirroot):
 620 -	        message('You need to create the temp dir first:'+Globs.gallerytempdirroot,0)
 621 -		return macro.formatter.rawHTML(
 622 -		    Globs.adminmsg+'<p>')
 623 -	    if not os.path.isdir(Globs.gallerytempdir):
 624 -	        # Try to create it if it is absent
 625 -		spagename=string.split(Globs.pagename,'/')
 626 -		compbit=''
 627 -		for component in spagename:
 628 -		    compbit=compbit+'/'+component
 629 +            afiles=os.listdir(Globs.attachmentdir)
 630 +        else:
 631 +            if not os.path.isdir(Globs.gallerytempdirroot):
 632 +                message('You need to create the temp dir first:'+Globs.gallerytempdirroot,0)
 633 +                return macro.formatter.rawHTML(
 634 +                    Globs.adminmsg+'<p>')
 635 +            if not os.path.isdir(Globs.gallerytempdir):
 636 +                # Try to create it if it is absent
 637 +                spagename=string.split(Globs.pagename,'/')
 638 +                compbit=''
 639 +                for component in spagename:
 640 +                    compbit=compbit+'/'+component
 641                      try:
 642 -			# The following line stops an exception being raised when trying
 643 -			# to create a directory that already exists (thanks Magnus Wahrenberg)
 644 -			if not os.access(Globs.gallerytempdirroot+compbit, os.F_OK):
 645 -			    os.mkdir(Globs.gallerytempdirroot+compbit)
 646 +                        # The following line stops an exception being raised when trying
 647 +                        # to create a directory that already exists (thanks Magnus Wahrenberg)
 648 +                        if not os.access(Globs.gallerytempdirroot+compbit, os.F_OK):
 649 +                            os.mkdir(Globs.gallerytempdirroot+compbit)
 650  
 651                      except:
 652 -			message('Please check permissions on temp dir:'+Globs.gallerytempdirroot,0)
 653 -			return macro.formatter.rawHTML(
 654 -			    Globs.adminmsg+'<p>')
 655 +                        message('Please check permissions on temp dir:'+Globs.gallerytempdirroot,0)
 656 +                        return macro.formatter.rawHTML(
 657 +                            Globs.adminmsg+'<p>')
 658                          
 659 -	    if os.path.isdir(Globs.gallerytempdir):
 660 -		afiles=os.listdir(Globs.attachmentdir)+os.listdir(Globs.gallerytempdir)
 661 -	    else:
 662 -	        message('You need to create the temp dir first:'+Globs.gallerytempdir,0)
 663 -		return macro.formatter.rawHTML(
 664 -		    Globs.adminmsg+'<p>')
 665 -
 666 -	# Split out the thumbnails and webnails
 667 -	for item in afiles:
 668 -	    if item.startswith('tmp.thumbnail.'):
 669 -	        origname=item[14:-4]
 670 -		thumbnails[origname]=''
 671 -	    elif item.startswith('tmp.webnail.'):
 672 -	        origname=item[12:-4]
 673 -		webnails[origname]=''
 674 -	    elif item.startswith('tmp.rotated.'):
 675 -	        origname=item[12:-4]
 676 -		rotated[origname]=''
 677 -	    elif item.startswith('tmp.annotation.'):
 678 -	        origname=item[15:-4]
 679 -		Globs.annotated[origname]=''
 680 -	    elif item == 'delete.me.to.regenerate.thumbnails.and.webnails':
 681 -	        dontregen='true'
 682 -	    elif item == 'tmp.writetest' or item == 'tmp.lock':
 683 -	        pass
 684 -	    else:
 685 -	        # This must be one of the original images
 686 -		lastdot=string.rfind(item,'.')
 687 -		origname=item[:lastdot]
 688 +            if os.path.isdir(Globs.gallerytempdir):
 689 +                afiles=os.listdir(Globs.attachmentdir)+os.listdir(Globs.gallerytempdir)
 690 +            else:
 691 +                message('You need to create the temp dir first:'+Globs.gallerytempdir,0)
 692 +                return macro.formatter.rawHTML(
 693 +                    Globs.adminmsg+'<p>')
 694 +
 695 +        # Split out the thumbnails and webnails
 696 +        for item in afiles:
 697 +            if item.startswith('autogenerated-thumbnail.'):
 698 +                origname=item[14:-4]
 699 +                thumbnails[origname]=''
 700 +            elif item.startswith('autogenerated-webnail.'):
 701 +                origname=item[12:-4]
 702 +                webnails[origname]=''
 703 +            elif item.startswith('autogenerated-rotated.'):
 704 +                origname=item[12:-4]
 705 +                rotated[origname]=''
 706 +            elif item.startswith('autogenerated-annotation.'):
 707 +                origname=item[15:-4]
 708 +                Globs.annotated[origname]=''
 709 +            elif item == 'delete.me.to.regenerate.thumbnails.and.webnails':
 710 +                dontregen='true'
 711 +            elif item == 'autogenerated-writetest' or item == 'autogenerated-lock':
 712 +                pass
 713 +            elif item.startswith('autogenerated-'):
 714 +                pass
 715 +            else:
 716 +                # This must be one of the original images
 717 +                lastdot=string.rfind(item,'.')
 718 +                origname=item[:lastdot]
 719                  ext = item[lastdot+1:]
 720                  if string.lower(ext) not in Globs.allowedextensions:
 721                      continue
 722 -		Globs.originals[origname]=item
 723 +                Globs.originals[origname]=item
 724      else:
 725          message(version(),0)
 726 -	return macro.formatter.rawHTML( Globs.adminmsg )
 727 +        return macro.formatter.rawHTML( Globs.adminmsg )
 728  
 729 -    if not Globs.gallerytempdir==Globs.attachmentdir and os.path.isfile(Globs.attachmentdir+'/tmp.writetest'):
 730 -	    # If we are using the new gallerytempdir and we were using the old system then make sure there are no 
 731 -	    # remnant files from the old system in the attachment dir to confuse us
 732 -	    message('You have changed to using a gallerytempdir so I am cleaning old tmp files from your attachment dir.',0)
 733 -	    for item in webnails.keys():
 734 -	        try:
 735 -		    os.unlink(Globs.attachmentdir+'/tmp.webnail.'+item+'.jpg')
 736 -		except:
 737 -		    pass
 738 -	    # Try deleting any old thumbnails which may be in the attachment directory
 739 -            for item in thumbnails.keys():	
 740 -	        try:
 741 -		    os.unlink(Globs.attachmentdir+'/tmp.thumbnail.'+item+'.jpg')
 742 -		except:
 743 -		    pass
 744 -	    # Try deleting any old rotated originals which may be in the attachment directory
 745 -            for item in rotated.keys():	
 746 -	        try:
 747 -		    os.unlink(Globs.attachmentdir+'/tmp.rotated.'+item+'.jpg')
 748 -		except:
 749 -		    pass
 750 -	    os.unlink(Globs.attachmentdir+'/tmp.writetest')
 751 +    if not Globs.gallerytempdir==Globs.attachmentdir and os.path.isfile(Globs.attachmentdir+'/autogenerated-writetest'):
 752 +            # If we are using the new gallerytempdir and we were using the old system then make sure there are no 
 753 +            # remnant files from the old system in the attachment dir to confuse us
 754 +            message('You have changed to using a gallerytempdir so I am cleaning old tmp files from your attachment dir.',0)
 755 +            for item in webnails.keys():
 756 +                try:
 757 +                    os.unlink(Globs.attachmentdir+'/autogenerated-webnail.'+item+'.jpg')
 758 +                except:
 759 +                    pass
 760 +            # Try deleting any old thumbnails which may be in the attachment directory
 761 +            for item in thumbnails.keys():      
 762 +                try:
 763 +                    os.unlink(Globs.attachmentdir+'/autogenerated-thumbnail.'+item+'.jpg')
 764 +                except:
 765 +                    pass
 766 +            # Try deleting any old rotated originals which may be in the attachment directory
 767 +            for item in rotated.keys(): 
 768 +                try:
 769 +                    os.unlink(Globs.attachmentdir+'/autogenerated-rotated.'+item+'.jpg')
 770 +                except:
 771 +                    pass
 772 +            os.unlink(Globs.attachmentdir+'/autogenerated-writetest')
 773  
 774      newnails=[]
 775      # Any thumbnails need to be built?
 776      for key in Globs.originals.keys():
 777          if (not thumbnails.has_key(key)) or (not dontregen):
 778 -	    # Create a thumbnail for this original
 779 -	    newnails.append((key,'tmp.thumbnail',Globs.thumbnailwidth))
 780 +            # Create a thumbnail for this original
 781 +            newnails.append((key,'autogenerated-thumbnail',Globs.thumbnailwidth))
 782      # Any webnails need to be built?
 783      for key in Globs.originals.keys():
 784          if (not webnails.has_key(key)) or (not dontregen):
 785 -	    # Create a webnail for this original
 786 -	    newnails.append((key,'tmp.webnail',Globs.webnailwidth))
 787 +            # Create a webnail for this original
 788 +            newnails.append((key,'autogenerated-webnail',Globs.webnailwidth))
 789      # Ok, lets build them all at once
 790      if not len(newnails)==0:
 791 -	buildnails(newnails)
 792 +        buildnails(newnails)
 793  
 794 -    # If a regen of thumbnails and webnails has occurred, then we should also delete any tmp.rotated files.
 795 +    # If a regen of thumbnails and webnails has occurred, then we should also delete any autogenerated-rotated files.
 796      if not dontregen:
 797          for key in rotated.keys():
 798 -	    # Wrapped in a try except since child processes may try to unlink a second time
 799 -	    try:
 800 -		os.unlink(Globs.gallerytempdir+'/tmp.rotated.'+key+'.jpg')
 801 -	    except:
 802 -		pass
 803 +            # Wrapped in a try except since child processes may try to unlink a second time
 804 +            try:
 805 +                os.unlink(Globs.gallerytempdir+'/autogenerated-rotated.'+key+'.jpg')
 806 +            except:
 807 +                pass
 808  
 809      if formvals.has_key('annotate'):
 810          if Globs.admin and formvals.has_key('target'):
 811 -	    target=formvals['target']
 812 -	    # Write an annotation file
 813 -	    atext=string.replace(formvals['annotate'],'"','&quot;')
 814 -	    ouf=open(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt','w')
 815 -	    ouf.write(atext)
 816 -	    ouf.close()
 817 -	    message('Annotation updated to <i>'+atext+'</i>',0)
 818 -	    # Now update the annotated dictionary
 819 +            target=formvals['target']
 820 +            # Write an annotation file
 821 +            atext=string.replace(formvals['annotate'],'"','&quot;')
 822 +            ouf=open(Globs.attachmentdir+'/autogenerated-annotation.'+target+'.txt','w')
 823 +            ouf.write(atext)
 824 +            ouf.close()
 825 +            message('Annotation updated to <i>'+atext+'</i>',0)
 826 +            # Now update the annotated dictionary
 827              if not Globs.annotated.has_key(target):
 828 -	        Globs.annotated[target]=''
 829 +                Globs.annotated[target]=''
 830  
 831      if formvals.has_key('webnail'):
 832 -	# Does the webnail exist?
 833 +        # Does the webnail exist?
 834          message('webnail requested')
 835 -	target=formvals['webnail']
 836 -	rotend=''
 837 -	if Globs.originals.has_key(target):
 838 -	    out.write(navibar(target,'webnail'))
 839 -	    out.write(toolbar(target,'webnail'))
 840 -	    if formvals.has_key('rotate'):
 841 -		direction=formvals['rotate']
 842 -		message(direction)
 843 -		rotate(target,direction)
 844 -		rotend=Globs.galleryrotchar+'rot='+repr(randint(1,10000))
 845 -	    if formvals.has_key('delete'):
 846 -	        message('Deleted <i>'+target+'</i>',0)
 847 -	        deletefromdisk(target)
 848 -	    # Put things in a table
 849 -	    out.write(tleft)
 850 -	    # Lets build up an image tag
 851 -	    out.write('<a href="'+Globs.baseurl+Globs.pagename+'?original='+target+'&action=content"><img src="'+Globs.gallerytempurl+'tmp.webnail.'+target+'.jpg'+rotend+'"></a>\n')
 852 -	    out.write(trigh)
 853 -	    out.write(tleft)
 854 -
 855 -	    atext=getannotation(target)
 856 -
 857 -	    # Are we an administrator?
 858 -	    if Globs.admin:
 859 -	        # We always provide an annotation text field
 860 -		out.write('<form action='+Globs.subname+' name=annotate METHOD=POST>')
 861 -		out.write('<input maxLength=256 size=55 name=annotate value="'+atext+'">')
 862 -		out.write('<input type=hidden value="'+target+'" name="target">')
 863 -		out.write('<input type=hidden value="show" name="action">')
 864 -		out.write('<input type=hidden value="'+target+'" name="webnail">')
 865 -		out.write('</form>')
 866 -	    else:
 867 -		out.write(atext)
 868 -	    out.write(trigh)
 869 -	    #out.write(toolbar(target,'webnail'))
 870 +        target=formvals['webnail']
 871 +        rotend=''
 872 +        if Globs.originals.has_key(target):
 873 +            out.write(navibar(target,'webnail'))
 874 +            out.write(toolbar(target,'webnail'))
 875 +            if formvals.has_key('rotate'):
 876 +                direction=formvals['rotate']
 877 +                message(direction)
 878 +                rotate(target,direction)
 879 +                rotend=Globs.galleryrotchar+'rot='+repr(randint(1,10000))
 880 +            if formvals.has_key('delete'):
 881 +                message('Deleted <i>'+target+'</i>',0)
 882 +                deletefromdisk(target)
 883 +            # Put things in a table
 884 +            out.write(tleft)
 885 +            # Lets build up an image tag
 886 +            out.write('<a href="'+Globs.baseurl+Globs.pagename+'?original='+target+'&action=content"><img src="'+Globs.gallerytempurl+'autogenerated-webnail.'+target+'.jpg'+rotend+'"></a>\n')
 887 +            out.write(trigh)
 888 +            out.write(tleft)
 889 +
 890 +            atext=getannotation(target)
 891 +
 892 +            # Are we an administrator?
 893 +            if Globs.admin:
 894 +                # We always provide an annotation text field
 895 +                out.write('<form action='+Globs.subname+' name=annotate METHOD=POST>')
 896 +                out.write('<input maxLength=256 size=55 name=annotate value="'+atext+'">')
 897 +                out.write('<input type=hidden value="'+target+'" name="target">')
 898 +                out.write('<input type=hidden value="show" name="action">')
 899 +                out.write('<input type=hidden value="'+target+'" name="webnail">')
 900 +                out.write('</form>')
 901 +            else:
 902 +                out.write(atext)
 903 +            out.write(trigh)
 904 +            #out.write(toolbar(target,'webnail'))
 905  
 906 -	else:
 907 -	    message('I do not have file: '+target,0)
 908 +        else:
 909 +            message('I do not have file: '+target,0)
 910      elif formvals.has_key('original'):
 911 -	# Now we just construct a single item rather than a table
 912 -	# Does the webnail exist?
 913 +        # Now we just construct a single item rather than a table
 914 +        # Does the webnail exist?
 915          message('original requested')
 916 -	target=formvals['original']
 917 -	rotend=''
 918 -	if not Globs.originals.has_key(target):
 919 -	    message('I do not have file: '+target,0)
 920 -	else:
 921 -	    if formvals.has_key('rotate'):
 922 -		direction=formvals['rotate']
 923 -		message(direction)
 924 -		rotate(target,direction)
 925 -		rotend=Globs.galleryrotchar+'rot='+repr(randint(1,10000))
 926 -		rotated[target]=''
 927 -	    # Lets build up an image tag
 928 -	    out.write(navibar(target,'original'))
 929 -	    out.write(tleft)
 930 -	    originalfilename=Globs.originals[target]
 931 -	    # If there is a rotated version, show that instead
 932 -	    if rotated.has_key(target):
 933 -		out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.gallerytempurl+'tmp.rotated.'+target+'.jpg'+rotend+'"></a>\n')
 934 -	    else:
 935 -		out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.subname+'?action=AttachFile&amp;do=get&amp;target='+originalfilename+'"></a>\n')
 936 -	    out.write(trigh)
 937 -	    out.write(tleft)
 938 -
 939 -	    atext=getannotation(target)
 940 -
 941 -	    # Are we an administrator?
 942 -	    if Globs.admin:
 943 -	        # We always provide an annotation text field
 944 -		out.write('<form action='+Globs.subname+' name=annotate METHOD=POST>')
 945 -		out.write('<input maxLength=256 size=55 name=annotate value="'+atext+'">')
 946 -		out.write('<input type=hidden value="'+target+'" name="target">')
 947 -		out.write('<input type=hidden value="show" name="action">')
 948 -		out.write('<input type=hidden value="'+target+'" name="original">')
 949 -		out.write('</form>')
 950 -	    else:
 951 -		out.write(atext)
 952 -	    out.write(trigh)
 953 -	    out.write(toolbar(target,'original'))
 954 +        target=formvals['original']
 955 +        rotend=''
 956 +        if not Globs.originals.has_key(target):
 957 +            message('I do not have file: '+target,0)
 958 +        else:
 959 +            if formvals.has_key('rotate'):
 960 +                direction=formvals['rotate']
 961 +                message(direction)
 962 +                rotate(target,direction)
 963 +                rotend=Globs.galleryrotchar+'rot='+repr(randint(1,10000))
 964 +                rotated[target]=''
 965 +            # Lets build up an image tag
 966 +            out.write(navibar(target,'original'))
 967 +            out.write(tleft)
 968 +            originalfilename=Globs.originals[target]
 969 +            # If there is a rotated version, show that instead
 970 +            if rotated.has_key(target):
 971 +                out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.gallerytempurl+'autogenerated-rotated.'+target+'.jpg'+rotend+'"></a>\n')
 972 +            else:
 973 +                out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.subname+'?action=AttachFile&amp;do=get&amp;target='+originalfilename+'"></a>\n')
 974 +            out.write(trigh)
 975 +            out.write(tleft)
 976 +
 977 +            atext=getannotation(target)
 978 +
 979 +            # Are we an administrator?
 980 +            if Globs.admin:
 981 +                # We always provide an annotation text field
 982 +                out.write('<form action='+Globs.subname+' name=annotate METHOD=POST>')
 983 +                out.write('<input maxLength=256 size=55 name=annotate value="'+atext+'">')
 984 +                out.write('<input type=hidden value="'+target+'" name="target">')
 985 +                out.write('<input type=hidden value="show" name="action">')
 986 +                out.write('<input type=hidden value="'+target+'" name="original">')
 987 +                out.write('</form>')
 988 +            else:
 989 +                out.write(atext)
 990 +            out.write(trigh)
 991 +            out.write(toolbar(target,'original'))
 992  
 993      elif formvals.has_key('rotate'):
 994          # We rotate all sizes of this image to the left or right
 995 -	message('rotate requested')
 996 -	target=formvals['target']
 997 -	direction=formvals['rotate']
 998 -	if not Globs.originals.has_key(target):
 999 -	    message('I do not have file: '+target,0)
1000 -	else:
1001 -	    # Do the rotation
1002 -	    rotate(target,direction)
1003 +        message('rotate requested')
1004 +        target=formvals['target']
1005 +        direction=formvals['rotate']
1006 +        if not Globs.originals.has_key(target):
1007 +            message('I do not have file: '+target,0)
1008 +        else:
1009 +            # Do the rotation
1010 +            rotate(target,direction)
1011              # Display the new image in webnail mode 
1012 -	    # We may need a way of forcing the browser to reload the newly rotated image here (later)
1013 -	    out.write(tleft)
1014 -	    out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.gallerytempurl+'tmp.webnail.'+target+'.jpg"></a>\n')
1015 -	    out.write(trigh)
1016 +            # We may need a way of forcing the browser to reload the newly rotated image here (later)
1017 +            out.write(tleft)
1018 +            out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.gallerytempurl+'autogenerated-webnail.'+target+'.jpg"></a>\n')
1019 +            out.write(trigh)
1020  
1021      else:
1022 -	# Finally lets build a table of thumbnails
1023 -	thumbs=Globs.originals.keys()
1024 -	thumbs.sort()
1025 -	thumbs.reverse()
1026 -	# If version number is requested (append a ?version=tellme&action=show to the page request)
1027 -	# or if there are no original images, just give help message and return
1028 -	if formvals.has_key('version') or len(thumbs)==0:
1029 -	    message(version(),0)
1030 -	    return macro.formatter.rawHTML( Globs.adminmsg )
1031 -	out.write('\n<table>')
1032 -	cease=''
1033 -	rollover=''
1034 -	while 1:
1035 -	    out.write('<tr>')
1036 -	    for i in range(Globs.numberofcolumns):
1037 -		try:
1038 -		    item=thumbs.pop()
1039 -		except IndexError:
1040 -		    cease='true'
1041 -		    break
1042 -
1043 -		# Alt text
1044 -		atext=getannotation(item)
1045 -		rollover='alt="'+atext+'" title="'+atext+'"'
1046 -
1047 -		# Table entry for thumbnail image
1048 -		out.write('<td><a href="'+Globs.baseurl+Globs.pagename+'?webnail='+item+Globs.bcomp+'"><center><img src="'+Globs.gallerytempurl+'tmp.thumbnail.'+item+'.jpg" '+rollover+'></a></center></td>')
1049 -	    out.write('</tr>\n')
1050 -	    if cease:
1051 -		out.write('</table>')
1052 -		break
1053 -	
1054 +        # Finally lets build a table of thumbnails
1055 +        thumbs=Globs.originals.keys()
1056 +        thumbs.sort()
1057 +        thumbs.reverse()
1058 +        # If version number is requested (append a ?version=tellme&action=show to the page request)
1059 +        # or if there are no original images, just give help message and return
1060 +        if formvals.has_key('version') or len(thumbs)==0:
1061 +            message(version(),0)
1062 +            return macro.formatter.rawHTML( Globs.adminmsg )
1063 +        out.write('\n<table>')
1064 +        cease=''
1065 +        rollover=''
1066 +        while 1:
1067 +            out.write('<tr>')
1068 +            for i in range(Globs.numberofcolumns):
1069 +                try:
1070 +                    item=thumbs.pop()
1071 +                except IndexError:
1072 +                    cease='true'
1073 +                    break
1074 +
1075 +                # Alt text
1076 +                atext=getannotation(item)
1077 +                rollover='alt="'+atext+'" title="'+atext+'"'
1078 +
1079 +                # Table entry for thumbnail image
1080 +                out.write('<td><a href="'+Globs.baseurl+Globs.pagename+'?webnail='+item+Globs.bcomp+'"><center><img src="'+Globs.gallerytempurl+'autogenerated-thumbnail.'+item+'.jpg" '+rollover+'></a></center></td>')
1081 +            out.write('</tr>\n')
1082 +            if cease:
1083 +                out.write('</table>')
1084 +                break
1085 +        
1086      out.seek(0)
1087      # Finally output any administrative messages at the top followed by any generated content
1088      return macro.formatter.rawHTML(
1089          Globs.adminmsg+'<p>'
1090 -        +out.read()	
1091 +        +out.read()     
1092      )
1093  

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2006-07-27 13:28:42, 41.0 KB) [[attachment:EXIF.py]]
  • [get | view] (2006-07-27 18:28:39, 2.8 KB) [[attachment:EXIF_patch.patch]]
  • [get | view] (2006-07-27 18:29:41, 50.5 KB) [[attachment:Gallery.patch]]
  • [get | view] (2006-07-27 19:15:39, 25.6 KB) [[attachment:Gallery2.patch]]
  • [get | view] (2006-07-27 13:33:03, 3175.6 KB) [[attachment:Gallery2_additional_files_win32.zip]]
  • [get | view] (2006-07-27 18:25:50, 4.5 KB) [[attachment:if_modified_since.patch]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.