new personal record
working day from 8:45 am to 12:57pm ...
working day from 8:45 am to 12:57pm ...
a small patch with a big speedup when you got the latest lighttpd running:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | --- ../backups/14022010/Sources/Display.php 2010-02-14 21:42:33.000000000 +0000 +++ Sources/Display.php 2010-03-31 23:01:06.000000000 +0000 @@ -1317,6 +1335,9 @@ // This is done to clear any output that was made before now. (would use ob_clean(), but that's PHP 4.2.0+...) ob_end_clean(); + + /* + // XXX: MOD NO COMPRESSION! if (!empty($modSettings['enableCompressedOutput']) && @version_compare(PHP_VERSION, '4.2.0') >= 0 && @filesize($filename) <= 4194304 && in_array($file_ext, array('txt', 'html', 'htm', 'js', 'doc', 'pdf', 'docx', 'rtf', 'css', 'php', 'log', 'xml', 'sql', 'c', 'java'))) @ob_start('ob_gzhandler'); else @@ -1324,6 +1345,8 @@ ob_start(); header('Content-Encoding: none'); } + */ + header('Content-Encoding: none'); // No point in a nicer message, because this is supposed to be an attachment anyway... if (!file_exists($filename)) @@ -1419,6 +1442,12 @@ else header('Cache-Control: max-age=' . (525600 * 60) . ', private'); + // XXX: lighttpd x sendfile optimization + header('Content-Length: '.ob_get_length()); + header("x-sendfile: $filename"); + die(0); + + /* if (empty($modSettings['enableCompressedOutput']) || filesize($filename) > 4194304) header('Content-Length: ' . filesize($filename)); @@ -1468,6 +1497,7 @@ echo isset($callback) ? $callback(file_get_contents($filename)) : file_get_contents($filename); obExit(false); + */ } function loadAttachmentContext($id_msg) |
so there is a project that implements identicons in php: problem is that they are hardcoded, low res and not good looking.
i wanted it more the gravatar style:

so i found this nice wordpress plugin: http://scott.sherrillmix.com/blog/blogger/wp_identicon/
which i (hackish) converted to pure php, so you can use it anywhere outside of wordpress:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | <?php /* Plugin Name: WP_Identicon Version: 1.02 Plugin URI: http://scott.sherrillmix.com/blog/blogger/wp_identicon/ Description: This plugin generates persistent specific geometric icons for each user based on the ideas of Don Park. Author: Scott Sherrill-Mix Author URI: http://scott.sherrillmix.com/blog/ Author non WP port: thomas{AT}thomasfischer{DOT}biz */ function identicon_get_options(){ //Set Default Values Here //$default_array=array('size'=>35,'backr'=>array(255,255),'backg'=>array(255,255),'backb'=>array(255,255), 'forer'=>array(1,255),'foreg'=>array(1,255),'foreb'=>array(1,255),'squares'=>4,'autoadd'=>1,'gravatar'=>0,'grey'=>0); $default_array=array( 'size'=>300, 'backr'=>array(225,255), 'backg'=>array(225,255), 'backb'=>array(225,255), 'forer'=>array(1,205), 'foreg'=>array(1,205), 'foreb'=>array(1,205), 'squares'=>5, 'autoadd'=>0, 'gravatar'=>0, 'grey'=>0); return($default_array); } class identicon { var $identicon_options; var $blocks; var $shapes; var $rotatable; var $square; var $im; var $colors; var $size; var $blocksize; var $quarter; var $half; var $diagonal; var $halfdiag; var $transparent=false; var $centers; var $shapes_mat; var $symmetric_num; var $rot_mat; var $invert_mat; var $rotations; //constructor function identicon($blocks='') { $this->identicon_options=identicon_get_options(); if ($blocks) $this->blocks=$blocks; else $this->blocks=$this->identicon_options['squares']; $this->blocksize=80; $this->size=$this->blocks*$this->blocksize; $this->quarter=$this->blocksize/4; $this->half=$this->blocksize/2; $this->diagonal=sqrt($this->half*$this->half+$this->half*$this->half); $this->halfdiag=$this->diagonal/2; $this->shapes=array( array(array(array(90,$this->half),array(135,$this->diagonal),array(225,$this->diagonal),array(270,$this->half))),//0 rectangular half block array(array(array(45,$this->diagonal),array(135,$this->diagonal),array(225,$this->diagonal),array(315,$this->diagonal))),//1 full block array(array(array(45,$this->diagonal),array(135,$this->diagonal),array(225,$this->diagonal))),//2 diagonal half block array(array(array(90,$this->half),array(225,$this->diagonal),array(315,$this->diagonal))),//3 triangle array(array(array(0,$this->half),array(90,$this->half),array(180,$this->half),array(270,$this->half))),//4 diamond array(array(array(0,$this->half),array(135,$this->diagonal),array(270,$this->half),array(315,$this->diagonal))),//5 stretched diamond array(array(array(0,$this->quarter),array(90,$this->half),array(180,$this->quarter)), array(array(0,$this->quarter),array(315,$this->diagonal),array(270,$this->half)), array(array(270,$this->half),array(180,$this->quarter),array(225,$this->diagonal))),// 6 triple triangle array(array(array(0,$this->half),array(135,$this->diagonal),array(270,$this->half))),//7 pointer array(array(array(45,$this->halfdiag),array(135,$this->halfdiag),array(225,$this->halfdiag),array(315,$this->halfdiag))),//9 center square array(array(array(180,$this->half),array(225,$this->diagonal),array(0,0)), array(array(45,$this->diagonal),array(90,$this->half),array(0,0))),//9 double triangle diagonal array(array(array(90,$this->half),array(135,$this->diagonal),array(180,$this->half),array(0,0))),//10 diagonal square array(array(array(0,$this->half),array(180,$this->half),array(270,$this->half))),//11 quarter triangle out array(array(array(315,$this->diagonal),array(225,$this->diagonal),array(0,0))),//12quarter triangle in array(array(array(90,$this->half),array(180,$this->half),array(0,0))),//13 eighth triangle in array(array(array(90,$this->half),array(135,$this->diagonal),array(180,$this->half))),//14 eighth triangle out array(array(array(90,$this->half),array(135,$this->diagonal),array(180,$this->half),array(0,0)), array(array(0,$this->half),array(315,$this->diagonal),array(270,$this->half),array(0,0))),//15 double corner square array(array(array(315,$this->diagonal),array(225,$this->diagonal),array(0,0)), array(array(45,$this->diagonal),array(135,$this->diagonal),array(0,0))),//16 double quarter triangle in array(array(array(90,$this->half),array(135,$this->diagonal),array(225,$this->diagonal))),//17 tall quarter triangle array(array(array(90,$this->half),array(135,$this->diagonal),array(225,$this->diagonal)), array(array(45,$this->diagonal),array(90,$this->half),array(270,$this->half))),//18 double tall quarter triangle array(array(array(90,$this->half),array(135,$this->diagonal),array(225,$this->diagonal)), array(array(45,$this->diagonal),array(90,$this->half),array(0,0))),//19 tall quarter + eighth triangles array(array(array(135,$this->diagonal),array(270,$this->half),array(315,$this->diagonal))),//20 tipped over tall triangle array(array(array(180,$this->half),array(225,$this->diagonal),array(0,0)), array(array(45,$this->diagonal),array(90,$this->half),array(0,0)), array(array(0,$this->half),array(0,0),array(270,$this->half))),//21 triple triangle diagonal array(array(array(0,$this->quarter),array(315,$this->diagonal),array(270,$this->half)), array(array(270,$this->half),array(180,$this->quarter),array(225,$this->diagonal))),//22 double triangle flat array(array(array(0,$this->quarter),array(45,$this->diagonal),array(315,$this->diagonal)), array(array(180,$this->quarter),array(135,$this->diagonal),array(225,$this->diagonal))),//23 opposite 8th triangles array(array(array(0,$this->quarter),array(45,$this->diagonal),array(315,$this->diagonal)), array(array(180,$this->quarter),array(135,$this->diagonal),array(225,$this->diagonal)), array(array(180,$this->quarter),array(90,$this->half),array(0,$this->quarter),array(270,$this->half))),//24 opposite 8th triangles + diamond array(array(array(0,$this->quarter),array(90,$this->quarter),array(180,$this->quarter),array(270,$this->quarter))),//25 small diamond array(array(array(0,$this->quarter),array(45,$this->diagonal),array(315,$this->diagonal)), array(array(180,$this->quarter),array(135,$this->diagonal),array(225,$this->diagonal)), array(array(270,$this->quarter),array(225,$this->diagonal),array(315,$this->diagonal)),array(array(90,$this->quarter),array(135,$this->diagonal),array(45,$this->diagonal))),//26 4 opposite 8th triangles array(array(array(315,$this->diagonal),array(225,$this->diagonal),array(0,0)), array(array(0,$this->half),array(90,$this->half),array(180,$this->half))),//27 double quarter triangle parallel array(array(array(135,$this->diagonal),array(270,$this->half),array(315,$this->diagonal)), array(array(225,$this->diagonal),array(90,$this->half),array(45,$this->diagonal))),//28 double overlapping tipped over tall triangle array(array(array(90,$this->half),array(135,$this->diagonal),array(225,$this->diagonal)), array(array(315,$this->diagonal),array(45,$this->diagonal),array(270,$this->half))),//29 opposite double tall quarter triangle array(array(array(0,$this->quarter),array(45,$this->diagonal),array(315,$this->diagonal)), array(array(180,$this->quarter),array(135,$this->diagonal),array(225,$this->diagonal)), array(array(270,$this->quarter),array(225,$this->diagonal),array(315,$this->diagonal)),array(array(90,$this->quarter),array(135,$this->diagonal),array(45,$this->diagonal)),array(array(0,$this->quarter),array(90,$this->quarter),array(180,$this->quarter),array(270,$this->quarter))),//30 4 opposite 8th triangles+tiny diamond array(array(array(0,$this->half),array(90,$this->half),array(180,$this->half),array(270,$this->half), array(270,$this->quarter),array(180,$this->quarter),array(90,$this->quarter),array(0,$this->quarter))),//31 diamond C array(array(array(0,$this->quarter),array(90,$this->half),array(180,$this->quarter),array(270,$this->half))),//32 narrow diamond array(array(array(180,$this->half),array(225,$this->diagonal),array(0,0)), array(array(45,$this->diagonal),array(90,$this->half),array(0,0)), array(array(0,$this->half),array(0,0),array(270,$this->half)), array(array(90,$this->half),array(135,$this->diagonal),array(180,$this->half))),//33 quadruple triangle diagonal array(array(array(0,$this->half),array(90,$this->half),array(180,$this->half),array(270,$this->half),array(0,$this->half), array(0,$this->quarter),array(270,$this->quarter),array(180,$this->quarter),array(90,$this->quarter),array(0,$this->quarter))),//34 diamond donut array(array(array(90,$this->half),array(45,$this->diagonal),array(0,$this->quarter)), array(array(0,$this->half),array(315,$this->diagonal),array(270,$this->quarter)), array(array(270,$this->half),array(225,$this->diagonal),array(180,$this->quarter))),//35 triple turning triangle array(array(array(90,$this->half),array(45,$this->diagonal),array(0,$this->quarter)), array(array(0,$this->half),array(315,$this->diagonal),array(270,$this->quarter))),//36 double turning triangle array(array(array(90,$this->half),array(45,$this->diagonal),array(0,$this->quarter)), array(array(270,$this->half),array(225,$this->diagonal),array(180,$this->quarter))),//37 diagonal opposite inward double triangle array(array(array(90,$this->half),array(225,$this->diagonal),array(0,0),array(315,$this->diagonal))),//38 star fleet array(array(array(90,$this->half),array(225,$this->diagonal),array(0,0),array(315,$this->halfdiag),array(225,$this->halfdiag), array(225,$this->diagonal),array(315,$this->diagonal))),//39 hollow half triangle array(array(array(90,$this->half),array(135,$this->diagonal),array(180,$this->half)), array(array(270,$this->half),array(315,$this->diagonal),array(0,$this->half))),//40 double eighth triangle out array(array(array(90,$this->half),array(135,$this->diagonal),array(180,$this->half),array(180,$this->quarter)), array(array(270,$this->half),array(315,$this->diagonal),array(0,$this->half),array(0,$this->quarter))),//42 double slanted square array(array(array(0,$this->half),array(45,$this->halfdiag), array(0,0),array(315,$this->halfdiag)), array(array(180,$this->half),array(135,$this->halfdiag), array(0,0),array(225,$this->halfdiag))),//43 double diamond array(array(array(0,$this->half),array(45,$this->diagonal), array(0,0),array(315,$this->halfdiag)), array(array(180,$this->half),array(135,$this->halfdiag), array(0,0),array(225,$this->diagonal))),//44 double pointer ); $this->rotatable=array(1,4,8,25,26,30,34); $this->square=$this->shapes[1][0]; $this->symmetric_num=ceil($this->blocks*$this->blocks/4); for ($i=0;$i<$this->blocks;$i++){ for ($j=0;$j<$this->blocks;$j++){ $this->centers[$i][$j]=array($this->half+$this->blocksize*$j,$this->half+$this->blocksize*$i); $this->shapes_mat[$this->xy2symmetric($i,$j)]=1; $this->rot_mat[$this->xy2symmetric($i,$j)]=0; $this->invert_mat[$this->xy2symmetric($i,$j)]=0; if (floor(($this->blocks-1)/2-$i)>=0&floor(($this->blocks-1)/2-$j)>=0&($j>=$i|$this->blocks%2==0)){ $inversei=$this->blocks-1-$i; $inversej=$this->blocks-1-$j; $symmetrics=array(array($i,$j),array($inversej,$i),array($inversei,$inversej),array($j,$inversei)); $fill=array(0,270,180,90); for ($k=0;$k<count($symmetrics);$k++){ $this->rotations[$symmetrics[$k][0]][$symmetrics[$k][1]]=$fill[$k]; } } } } } function xy2symmetric($x,$y){ $index=array(floor(abs(($this->blocks-1)/2-$x)),floor(abs(($this->blocks-1)/2-$y))); sort($index); $index[1]*=ceil($this->blocks/2); $index=array_sum($index); return $index; } //convert array(array(heading1,distance1),array(heading1,distance1)) to array(x1,y1,x2,y2) function identicon_calc_x_y($array,$centers,$rotation=0){ $output=array(); $centerx=$centers[0]; $centery=$centers[1]; while($thispoint=array_pop($array)){ $y=round($centery+sin(deg2rad($thispoint[0]+$rotation))*$thispoint[1]); $x=round($centerx+cos(deg2rad($thispoint[0]+$rotation))*$thispoint[1]); array_push($output,$x,$y); } return $output; } //draw filled polygon based on an array of (x1,y1,x2,y2,..) function identicon_draw_shape($x,$y){ $index=$this->xy2symmetric($x,$y); $shape=$this->shapes[$this->shapes_mat[$index]]; $invert=$this->invert_mat[$index]; $rotation=$this->rot_mat[$index]; $centers=$this->centers[$x][$y]; $invert2=abs($invert-1); $points=$this->identicon_calc_x_y($this->square,$centers,0); $num = count($points) / 2; imagefilledpolygon($this->im, $points, $num, $this->colors[$invert2]); foreach($shape as $subshape){ $points=$this->identicon_calc_x_y($subshape,$centers,$rotation+$this->rotations[$x][$y]); $num = count($points) / 2; imagefilledpolygon($this->im, $points, $num,$this->colors[$invert]); } } //use a seed value to determine shape, rotation, and color function identicon_set_randomness($seed=""){ //set seed $twister=new identicon_mersenne_twister(hexdec($seed)); foreach ($this->rot_mat as $key => $value){ $this->rot_mat[$key]=$twister->rand(0,3)*90; $this->invert_mat[$key]=$twister->rand(0,1); #&$this->blocks%2 if ($key==0) $this->shapes_mat[$key]=$this->rotatable[$twister->array_rand($this->rotatable)]; else $this->shapes_mat[$key]=$twister->array_rand($this->shapes); } $forecolors=array($twister->rand($this->identicon_options['forer'][0],$this->identicon_options['forer'][1]), $twister->rand($this->identicon_options['foreg'][0],$this->identicon_options['foreg'][1]), $twister->rand($this->identicon_options['foreb'][0],$this->identicon_options['foreb'][1])); $this->colors[1]=imagecolorallocate($this->im, $forecolors[0],$forecolors[1],$forecolors[2]); if (array_sum($this->identicon_options['backr']) + array_sum($this->identicon_options['backg']) + array_sum($this->identicon_options['backb'])==0) { $this->colors[0]=imagecolorallocatealpha($this->im,0,0,0,127); $this->transparent=true; imagealphablending ($this->im,false); imagesavealpha($this->im,true); } else { $backcolors=array($twister->rand($this->identicon_options['backr'][0],$this->identicon_options['backr'][1]), $twister->rand($this->identicon_options['backg'][0],$this->identicon_options['backg'][1]), $twister->rand($this->identicon_options['backb'][0],$this->identicon_options['backb'][1])); $this->colors[0]=imagecolorallocate($this->im, $backcolors[0],$backcolors[1],$backcolors[2]); } if($this->identicon_options['grey']){ $this->colors[1]=imagecolorallocate($this->im, $forecolors[0],$forecolors[0],$forecolors[0]); if(!$this->transparent) $this->colors[0]=imagecolorallocate($this->im, $backcolors[0],$backcolors[0],$backcolors[0]); } return true; } function identicon_build($seed='',$altImgText='',$img=true,$outsize='',$write=true,$random=true,$displaysize='',$gravataron=true){ $filepath = '/var/www/your/path/ident/'; //make an identicon and return the filepath or if write=false return picture directly if (function_exists("gd_info")){ // init random seed //$id=$seed; $id=substr(sha1($seed),0,12); $fn=$id.'.png'; $filename=$filepath.$fn; if ($outsize=='') $outsize=$this->identicon_options['size']; if($displaysize=='') $displaysize=$outsize; //if (!file_exists($filename)) { $this->im = imagecreatetruecolor($this->size,$this->size); $this->colors = array(imagecolorallocate($this->im, 255,255,255)); if ($random) $this->identicon_set_randomness($id); else {$this->colors = array(imagecolorallocate($this->im, 255,255,255),imagecolorallocate($this->im, 0,0,0));$this->transparent=false;}; imagefill($this->im,0,0,$this->colors[0]); for ($i=0;$i<$this->blocks;$i++){ for ($j=0;$j<$this->blocks;$j++){ $this->identicon_draw_shape($i,$j); } } $out = @imagecreatetruecolor($outsize,$outsize); imagesavealpha($out,true); imagealphablending($out,false); imagecopyresampled($out,$this->im,0,0,0,0,$outsize,$outsize,$this->size,$this->size); imagedestroy($this->im); if ($write){ $wrote=imagepng($out,$filename); if(!$wrote) return false; //something went wrong but don't want to mess up blog layout }else{ header ("Content-type: image/png"); imagepng($out); } imagedestroy($out); } $filename=$filename; if($this->identicon_options['gravatar']&&$gravataron) $filename = "http://www.gravatar.com/avatar.php?gravatar_id=".md5($seed)."&size=$outsize&default=$filename"; if ($img){ $filename='<img class="identicon" src="'.$fn.'" alt="'.str_replace('"',"'",$altImgText).' Identicon Icon" height="'.$displaysize.'" width="'.$displaysize.'" />'; } return $filename; } else { //php GD image manipulation is required return false; //php GD image isn't installed but don't want to mess up blog layout } } function identicon_display_parts(){ $this->identicon(1); for ($i=0;$i<count($this->shapes);$i++){ $this->shapes_mat=array($i); $this->invert_mat=array(1); $output.=$this->identicon_build($seed='example'.$i,$altImgText='',$img=true,$outsize=30,$write=true,$random=false); $counter++; } $this->identicon(); return $output; } } //create identicon for later use global $identicon; $identicon = new identicon; class identicon_mersenne_twister{ //Copied from wikipedia pseudocode //Don't call over 600 times (without recalling the constructor) // Create a length 624 array to store the state of the generator var $MT; var $i; // Initialise the generator from a seed function identicon_mersenne_twister ($seed=123456) { $this->MT[0] = $seed; $this->i=1; for ($i=1;$i<624;$i++) { // loop over each other element $this->MT[$i] = $this->mysql_math('(1812433253 * ('.$this->MT[$i-1].' ^ ('.$this->MT[$i-1]." >> 30)) + $i) & 0xffffffff"); } $this->generateNumbers(); } //(some) PHP integers don't have enough bits for Mersenne Twister so use mysql function mysql_math($equation){ $equation='select '.$equation; //echo $equation; $dblink=mysql_connect("localhost","username","password") or die (mysql_error()); $res = mysql_query($equation,$dblink) or die (mysql_error()); $arr=mysql_fetch_array($res); mysql_close($dblink) or die (mysql_error()); //global $wpdb; //$query="SELECT ".$equation; //$answer=$wpdb->get_var($query); //echo $equation; //echo $arr[0].'<br/>'; return $arr[0];//$answer; } // Generate an array of 624 untempered numbers function generateNumbers() { for ($i=0;$i<624;$i++) { $y = $this->mysql_math('('.$this->MT[$i].' & 0x7fffffff) + ('.$this->MT[($i+1)%624].' & 0xfffffffe)'); $even=$this->mysql_math($y.' ^ 0x00000001'); if ($even) { $this->MT[$i] = $this->mysql_math($this->MT[($i + 397) % 624]." ^ ($y >> 1)"); } else { $this->MT[$i] = $this->mysql_math($this->MT[($i + 397) % 624]." ^ ($y >>1) ^ (2567483615)"); // 0x9908b0df } } } // Extract a tempered pseudorandom number based on the i-th value // generateNumbers() will have to be called again once the array of 624 numbers is exhausted function extractNumber() { $y = $this->MT[$this->i]; $y = $this->mysql_math("$y ^ ($y >>11) ^ (($y << 7) & 2636928640) ^ (($y << 15) & 4022730752) ^ ($y >>18)"); $this->i++; return $y/0xffffffff; } function rand($low,$high){ $pick=floor($low+($high-$low+1)*$this->extractNumber()); return ($pick); } function array_rand($array){ return($this->rand(0,count($array)-1)); } } echo $identicon->identicon_build($_GET['hash'], '', true, '', true, true); echo '<br/>'; echo '<br/>'; echo $identicon->identicon_build($_GET['hash'].'1', '', true, '', true, true); echo '<br/>'; echo '<br/>'; echo $identicon->identicon_build($_GET['hash'].'2', '', true, '', true, true); echo '<br/>'; echo '<br/>'; ?> |
the images above were produced by this code.
have fun using it
1 2 | emerge -av app-text/pdfjam pdfnup --nup 2x2 --column true --frame true your_pdf.pdf |
read this interesting article to get to know: http://www.xboxist.com/xbox-360/games/xna-community-games-is-a-failed-experiment-010122.php
nice quote:
As Fouts revealed in his blog post, Microsoft takes a base cut of 30% plus an additional 10-30% for advertising. Simply put, 40-60% of profits goes to Microsoft, and the remainder to the developers.
press CTRL+SHIFT+*, enables the drawing of space/tab characters
As i wrote earlier, you are able to write your own little mailserver.
With the following handling routine, it filters out the mailserver rejected mails correctly. (at least for the mailserver combination i am using)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | def process_message(self, peer, mailfrom, rcpttos, data): if not '<SOME VERY LONG SECURE KEY>@<YOUR IP>' in rcpttos: # drop spam return if DEBUG: print '%s' % '='*80 print 'peer: ', peer print 'mailfrom: ', mailfrom print 'rcpttos: ', rcpttos print 'data: ', data lines = data.split('\n') counter = 0 info = '' failline = '' failline_count = 0 for line in lines: if line.strip() == 'The mail system': counter = 5 continue if counter > 0: counter -= 1 if counter == 0: break if line.strip() != '' and failline_count < 2: failline += line failline_count += 1 info += line + '\n' mailsrch = re.compile(r'<[\w\-][\w\-\.]+@[\w\-][\w\-\.]+[a-zA-Z]{1,4}>') mails = mailsrch.findall(info) if len(mails) > 0: email = mails[0].strip(' <>') print "fail mail found: ", email cmd = '/your/command/to/process/this/event %s "%s" "%s"' % (email, failline, data.replace('"', '\'')) commands.getstatusoutput(cmd) else: print 'no emails found :(' print 'info: ', info |
you might want to exchange '<SOME VERY LONG SECURE KEY>', '<YOUR IP>' and /your/command/to/process/this/event.
The custom command will post a new post in a forum thread in my case, but it could also move the user to a special group or something.
small update on some side projects i started over the last months:
(all of those are currently actively used by me, so if you get problems, let me know)
before you try to use svnsync, you might want to try this first:
rsync -av PROJECTNAME.svn.sourceforge.net::svn/PROJECTNAME/* .
as noted on http://sourceforge.net/apps/trac/sourceforge/wiki/SVN%20adminrepo
so we have the problem that we have a forum of 10th's of users, and if we announce a topic or anything, we get back lots of mails of remote mailservers rejecting the email for various reasons. So we had a problem with handling those properly (inform the user, etc)
Thus we had the following idea:
- filter mails coming in using out google apps
- redirect mails to a special written new, slim mailserver that processes those emails correctly.
You can find that mailserver below, modify to what you need:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import sys import asyncore import threading import smtpd import time # written by thomas fischer thomas{AT}thomasfischer{DOT}biz # idea based on http://code.activestate.com/recipes/440690/ class MySMTPServer(smtpd.SMTPServer): def __init__(self, localaddr, remoteaddr): smtpd.SMTPServer.__init__(self, localaddr, remoteaddr) def process_message(self, peer, mailfrom, rcpttos, data): print '%s' % '='*80 print 'peer: ', peer print 'mailfrom: ', mailfrom print 'rcpttos: ', rcpttos print 'data: ', data class MyEmailServer(threading.Thread): def __init__(self, ipport): threading.Thread.__init__(self) self._stopevent = threading.Event() self.server = MySMTPServer(ipport, None) def run(self): while not self._stopevent.isSet(): asyncore.loop(timeout = 0.001, count = 1) def stop(self, timeout=None): self._stopevent.set() threading.Thread.join(self, timeout) self.server.close() if __name__ == "__main__": if len(sys.argv) != 2: print "usage: ip:port" sys.exit(1) ar = sys.argv[1].split(":") ar[1] = int(ar[1]) ipport = tuple(ar) mailServer = MyEmailServer(ipport) mailServer.start() print "running" running = True while running: try: time.sleep(1) except: print "stopping" mailServer.stop() del mailServer running = False |
so, in order to test:
1 | python mailserver.py 0.0.0.0:25 |
and send an email to your ip
below is an example of what it looks like when you send your IP an email using google mail with the above script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | $ python mailserver.py 0.0.0.0:25 running ================================================================================ peer: ('209.85.211.186', 45480) mailfrom: thomas@thomasfischer.biz rcpttos: ['thomas@<YOUR IP>'] data: Received: by ywh16 with SMTP id 16so461179ywh.24 for <thomas@<YOUR IP>>; Wed, 05 Aug 2009 12:33:52 -0700 (PDT) MIME-Version: 1.0 Received: by 10.150.216.1 with SMTP id o1mr12837562ybg.183.1209500824x39; Wed, 05 Aug 2009 12:33:44 -0700 (PDT) Date: Wed, 5 Aug 2009 21:33:44 +0200 Message-ID: <f4dad1470908051233l5c5f6ddea57878c8c0c0ek6ed@mail.gmail.com> Subject: test From: Thomas Fischer <thomas@thomasf1scher.biz> To: thomas@<YOUR IP> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit foobar! |