[PHP]IMAPでメールの文字コード判定を行うには

なぜかimap_headerinfo()の戻り値にはContent-Typeが含まれないので、
直に取得する力技で解決。

When you try to get charset of a mail on IMAP, imap_headerinfo() doesn’t include ‘Content-Type’ in the return value.
Below is a function to get type of charset from a mail header directly by calling imap_fetchheader.


<?

/**

@context IMAPハンドル

@number  メールのID

@defcharset 失敗した時に返すデフォルトの文字セット名

@return 文字セット名

*/

function imap_getcharset($context, $number, $defcharset = "iso-2022-jp")

{

    

    
// Get charset

    
$h = imap_fetchheader($context, $number);

    
$mc = preg_match("/charsets*=s*(.+?)[;\n]/s", $h, $m);

    
$charset = $m[1] ? strtolower(trim($m[1])) : $defcharset;

    

}

?>


Particle Emitter on Proce55ing 1.0.3

Recently I have upgraded proce55ing to version 1.0.3.
And I tried to run a sketch “Particle Emitter” on FLIGHT404.

But I got this error:

"The method bindTexture(PImage) from the type PGraphicsOpenGL is not visible."

Because this sketch was built with v.135, it’s no longer available to call bindTexture().
So I found a solution.

Instead of

   pgl.bindTexture( images.particle );

We can use this:

  glParticle.bind();
  glParticle.enable();
  // rendering goes here
  glParticle.disable();

where images.glParticle is

  Texture glParticle;
  glParticle = TextureIO.newTexture(new File(dataPath("particle.png")), true);

Finally, here is the fixed code in emitter.pde.

import com.sun.opengl.util.texture.*;

class Emitter{
  Vec3D loc;
  Vec3D vel;
  Vec3D velToMouse;
  float radius;

  Texture coronaTex; 
  Texture emitterTex; 
  Texture particleTex; 
  Texture reflectionTex;

  color myColor;

  ArrayList particles;
  ArrayList nebulae;

  Emitter(  ){

    try {
      coronaTex = TextureIO.newTexture(new File(dataPath("corona.png")), true); 
      emitterTex = TextureIO.newTexture(new File(dataPath("emitter.png")), true); 
      particleTex = TextureIO.newTexture(new File(dataPath("particle.png")), true); 
      reflectionTex = TextureIO.newTexture(new File(dataPath("reflection.png")), true); 
    }
    catch (IOException e) {    
      println("Texture file is missing");
      exit();  // or handle it some other way
    }  

    loc        = new Vec3D();
    vel        = new Vec3D();
    velToMouse = new Vec3D();

    radius     = 100;

    myColor    = color( 1, 1, 1 );

    particles  = new ArrayList();
    nebulae    = new ArrayList();
  }

  void exist(){
    findVelocity();
    setPosition();
    iterateListExist();
    render();

    gl.glDisable( GL.GL_TEXTURE_2D );

    if( ALLOWTRAILS )
      iterateListRenderTrails();
  }

  void findVelocity(){
    Vec3D dirToMouse = new Vec3D( mouse.loc.sub( loc ).scale( .15 ) );
    vel.set( dirToMouse );
  }

  void setPosition(){
    loc.addSelf( vel );

    if( ALLOWFLOOR ){
      if( loc.y > floorLevel ){
        loc.y = floorLevel;
        vel.y = 0;
      }
    }
  }

  void iterateListExist(){
    gl.glEnable( GL.GL_TEXTURE_2D );


    int mylength = particles.size(); 
    for( int i=mylength-1; i>=0; i-- ){ 
      Particle p = ( Particle )particles.get(i); 
      if( p.ISSPLIT ) 
        addParticles( p ); 

      if ( !p.ISDEAD ){
        //        pgl.bindTexture( images.particle );
        particleTex.bind();
        particleTex.enable();
        p.exist();
        particleTex.disable();

      }
      else { 
        particles.set( i, particles.get( particles.size() - 1 ) );
        particles.remove( particles.size() - 1 );
      }
    }

    if( ALLOWFLOOR ){
      //      pgl.bindTexture( images.reflection );
      reflectionTex.bind();
      reflectionTex.enable();
      for( Iterator it = particles.iterator(); it.hasNext(); ){
        Particle p = (Particle) it.next();
        p.renderReflection();
      }
      reflectionTex.disable();
    }

    //    pgl.bindTexture( images.corona );
    coronaTex.bind();
    coronaTex.enable();
    for( Iterator it = nebulae.iterator(); it.hasNext(); ){
      Nebula n = (Nebula) it.next();
      if( !n.ISDEAD ){
        n.exist();
      } 
      else {
        it.remove();
      }
    }
    coronaTex.disable();
  }


  void render(){
    //    pgl.bindTexture( images.emitter );
    emitterTex.bind();
    emitterTex.enable();
    renderImage( loc, radius, myColor, 1.0 );
    emitterTex.enable();

    if( ALLOWNEBULA ){
      nebulae.add( new Nebula( loc, 15.0, true ) );
      nebulae.add( new Nebula( loc, 45.0, true ) );
    }


    if( ALLOWFLOOR ){
      //      pgl.bindTexture( images.reflection );
      reflectionTex.bind();
      reflectionTex.enable();
      renderReflection();
      reflectionTex.disable();
    }
  }

  void renderReflection(){
    float altitude           = floorLevel - loc.y;
    float reflectMaxAltitude = 300.0;
    float yPer               = 1.0 - altitude/reflectMaxAltitude;

    if( yPer > .05 )
      renderImageOnFloor( new Vec3D( loc.x, floorLevel, loc.z ), radius * 10.0, color( 0.5, 1.0, yPer*.25 ), yPer );

    if( mousePressed )
      renderImageOnFloor( new Vec3D( loc.x, floorLevel, loc.z ), radius + ( yPer + 1.0 ) * radius * random( 2.0, 3.5 ), color( 1.0, 0, 0 ), yPer );
  }

  void iterateListRenderTrails(){
    for( Iterator it = particles.iterator(); it.hasNext(); ){
      Particle p = (Particle) it.next();
      p.renderTrails();
    }
  }

  void addParticles( int _amt ){
    for( int i=0; i<_amt; i++ ){
      particles.add( new Particle( 1, loc, vel ) );
    }

    if( ALLOWNEBULA ){
      nebulae.add( new Nebula( loc, 40.0, false ) );
      nebulae.add( new Nebula( loc, 100.0, false ) );
    }
  }

  void addParticles( Particle _p ){
    // play with amt if you want to control how many particles spawn when splitting
    int amt = (int)( _p.radius * .15 );
    for( int i=0; i<amt; i++ ){
      particles.add( new Particle( _p.gen + 1, _p.loc[0], _p.vel ) );
      if( ALLOWNEBULA )
        nebulae.add( new Nebula( _p.loc[0], random( 5.0, 50.0 ), true ) );
    }
  }
}

Then it got worked!
Particle Emitter


EclipseでProce55ingのOpenGLを使用する

EclipseでProce55ingするにはここを参照。

  1. プロジェクトを右クリックして[プロパティ]を選択
  2. [ビルドパス]の[ライブラリ]タブでjogl.jarの[Native library location]のところに、例えば C:\processing-0125-expert\libraries\opengl\library と入力する。
  3. さらに、JFrame 内でPAppletEmbedded として動作させるには、
    public static void main(String[] args) { 
        JFrame f = new JFrame(&quot;Embedded&quot;);  
        f.setLayout(new BorderLayout()); 
        PApplet embed = new <font color="blue">PAppletのクラス名</font><font>(); 
        f.add(embed, BorderLayout.CENTER); 
        f.setSize(DIM, DIM); 
        f.setVisible(true); 
        // important to call this whenever embedding a PApplet. 
        // It ensures that the animation thread is started and 
        // that other internal variables are properly set. 
        embed.init(); 
    }
    

でOK。


FormatTextとIso_2022_jp_mail

こちらのサイトで公開されているPlaggerのプラグイン。
フィードを携帯とかに送りたい時、PlainTextのメールで欲しいとかMIMEがmixedなのは嫌だって時に便利な以下の二つのプラグインだが、上手く動かなかったりスペル間違いがあったりしたので自分なりにがんばって修正してみた。

Filter::FormatText

package Plagger::Plugin::Filter::FormatText;
use strict;
use base qw( Plagger::Plugin );

use HTML::TreeBuilder;
use HTML::FormatText;
use Encode;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&filter,
    );
}

sub filter {
     my($self, $context, $args) = @_;
     my $cfg   = $self->conf;
     my $entry = $args->{entry};

     my $left  = $cfg->{left_margin}  || 0;
     my $right = $cfg->{right_margin} || 72;
     my $tree      = HTML::TreeBuilder->new()->parse($entry->body);
     my $formatter = HTML::FormatText->new(
         leftmargin => $left,
         rightmargin => $right,
     );
     my $body = $formatter->format($tree);
     my $len  = length($body);

     my $start = $cfg->{start}  || 0;
     my $end   = $cfg->{length} || $len;

     if ($cfg->{start} || $cfg->{length}) {
       my $more = '';
          $more = ' ...' if $len > $end;
       $body = substr($body, $start, $end) . $more;
     }
#     $entry->body('</pre><pre>'.$body.'</pre>');
     $entry->body($body);

     $context->log(info => "format $entry->{link}") if $entry->{link};
}


1;

__END__

Publish::Iso_2022_jp_mail

package Plagger::Plugin::Publish::Iso_2022_jp_mail;
use strict;
use base qw( Plagger::Plugin );

use DateTime;
use DateTime::Format::Mail;
use Encode;
use Encode::MIME::Header;
use Jcode;
use MIME::Lite;

our %TLSConn;

sub rule_hook { 'publish.entry.fixup' }

sub register {
    my($self, $context) = @_;
    $context->autoload_plugin({ module => "Filter::FormatText" });
    $context->register_hook(
        $self,
        'publish.entry.fixup' => \¬ify,
    );
}

sub init {
  my $self = shift;
  $self->SUPER::init(@_);

  $self->conf->{mailto} or Plagger->context->error("mailto is required");
  $self->conf->{mailfrom} ||= 'plagger@localhost';
  print "....\n";
}


sub notify {
  my ($self, $context, $args) = @_;

  return if $args->{feed}->count == 0;

  my $cnf = $self->conf;
  my $now = Plagger::Date->now(timezone => $context->conf->{timezone});
  my $subject = $args->{feed}->title || '(no-title)';
  my $from = $cnf->{mailfrom};

  my $msg = MIME::Lite->new(
    Date     => $now->format('Mail'),
    From     => encode('MIME-Header-ISO_2022_JP', $from),
    To       => encode('MIME-Header-ISO_2022_JP', $cnf->{mailto}),
    Subject  => encode('MIME-Header-ISO_2022_JP', $subject),
    Type     => 'text/plain; charset=ISO-2022-JP',
    Encoding => '7bit',
    Data     => encode_body($args->{entry}->body),
  );

  $msg->send();

  $context->log(info => "Sending $subject to $cnf->{mailto}");
}

sub encode_body {
  my $str = shift;
  $str = remove_utf8_flag($str);
  $str =~ s/\x0D\x0A/\n/g;
  $str =~ tr/\r/\n/;
  return Jcode->new($str, guess_encoding($str))->jis;
}

sub guess_encoding {
  my $str = shift;
  my $enc = Jcode::getcode($str) || 'euc';
  $enc = 'euc' if $enc eq 'ascii' || $enc eq 'binary';
  return $enc;
}

sub remove_utf8_flag { pack 'C0A*', $_[0] }



1;

How do I remove installed Perl modules?

CPANによってインストールしたPerlモジュールを簡単に削除する方法。
CPAN Faqから消えててWeb Archiveから掘り出した。
また要るかもしれないのでここにメモ。

#!/usr/local/bin/perl -w

use ExtUtils::Packlist;
use ExtUtils::Installed;

$ARGV[0] or die "Usage: $0 Module::Name\n";

my $mod = $ARGV[0]; 
my $inst = ExtUtils::Installed->new();

foreach my $item (sort($inst->files($mod))) {
     print "removing $item\n";
     unlink $item;
}

my $packfile = $inst->packlist($mod)->packlist_file();
print "removing $packfile\n";
     unlink $packfile;

こいつをremove.plなどとして保存。

$perl ./remove.pl モジュール名

で削除実行。


絶景

おっと、放置しちまったぜ!まぁそう怒るなよBABY!

今日は絶景を紹介します。

patina

いや?絶景ですね!!さながらラインアートと言ったところでしょうか。
これは分散ネットワークでノード数が50個の場合で、保存しているファイルが12個ありますね?。
一つのパソコンで25個ノードを動かして、そのコンソールウインドウを並べて表示すると、まるでマトリックスの流れる文字スクリーンを見ている気分になれます。
あっはっはっ。

patina
(クリックで拡大)

これは一つのノードに対して詳細な統計情報などを表示した画面ですね?いやぁ絶景!!このルーティングテーブルがノードに伸びていく線なんてまるで花のようですな!!

patina
んーむ、これは分単位でノードの負荷をそれぞれの処理に分けてグラフに表したモノですね。
一時期忙しかった時期があった模様ですが、落ち着きを取り戻し、平和な日常を送っているようです。いやぁ良かった良かった。

いかがだったでしょうか?また新しい絶景があったら載せますね><