Saturday, July 27, 2013

Civic Timing Belt Gear Differences

So, with the P0171 (or flash code 54 on the CEL/Check Engine Light method), I suddenly realized the fluctuation sensor (CFK) on the civic needed teeth closer to it, and didn't have them.  I knew I had to tear into the engine, thinking I'd put the timing gear/pulley on backwards, and took it all apart.  When I pulled the gear off, I knew why I was having problems - they weren't even the same.  I called the dealership (who kept telling me "I've never seen one of these fail before" and trying to convince me I didn't need one), and $77 later, I had the part to compare.



Wow, that is much more like it.  The one on the left is what came with the replacement engine.  The one on the right is the one that came from the dealership.

Though the engine block was identical, it was still a Japanese-spec'd engine, meaning it met Japanese specifications - and their computers probably didn't care about the fluctuations on the crank sensor, and (I think) didn't even have the sensor in there.  The one on the right has what looks like a bicycle sprocket on one end, and that is the difference.  Things looked much better with the new gear in place, but I am still unable to test it as I snapped one of the valve cover bolts off in the head trying to get it tightened down so that it wouldn't leak oil like it did before.  We'll see how it works when I can drill it out and tap it for a new one.

Friday, July 26, 2013

Power Supply Pinouts

Voltages and Funtions
Wire ColorVoltage/Function
BlackGround
Red+5V
Yellow+12V
Orange+3.3V
White-5V
Blue-12V
PurpleS.B.
GreenPS-ON
GrayPG
Connector Color Scheme
(looking at the connector with the wires pointed away)
RedYellow
RedPurple
WhiteGray
BlackBlack
BlackRed
BlackBlack
GreenRed
BlackBlack
BlueOrange
OrangeOrange

Apache Module Config Merge

An example apache module merge routine :
    
    static void *mod_gzip_merge_dconfig(
    apr_pool_t *p,
    void *parent_conf,
    void *newloc_conf
    )
    {
     mod_gzip_conf *merged_config = (mod_gzip_conf *) apr_pcalloc(p, sizeof(mod_gzip_conf));
     mod_gzip_conf *pconf         = (mod_gzip_conf *) parent_conf;
     mod_gzip_conf *nconf         = (mod_gzip_conf *) newloc_conf;
    
     mod_gzip_merge1(
     ( apr_pool_t    * ) p,
     ( mod_gzip_conf * ) merged_config,
     ( mod_gzip_conf * ) pconf,
     ( mod_gzip_conf * ) nconf
     );
    
    
    
    static int mod_gzip_handler( request_rec *r ) {
     mod_gzip_conf *mgc; /* Location/Directory configuration */
     mgc = ( mod_gzip_conf * )
     ap_get_module_config( r->per_dir_config, &gzip_module );
    }
    
    register_hooks() {
      ap_hook_insert_filter( mod_gzip_insert_output_filter, NULL, NULL, APR_HOOK_MIDDLE );
     ap_register_output_filter( mod_gzip_filter_name, mod_gzip_output_filter, AP_FTYPE_CONTENT );
     return;
    }
    

PerlMagick Tutorial - Re-Published

I wrote this tutorial years ago, and it has been a popular little page.  As a result, with me closing down one website and moving to a blog-oriented online presence, I thought I'd better get it out there again for people to see.  Hence, a re-publish ensues.

Congratulations on taking a look at PerlMagick!  I am positive that you will find a system of image manipulation routines that are both powerful and easy to implement.  PerlMagick is a set of perl commands and routines that allows a developer or administrator the ease of using perl, but the power of using ImageMagick.  The tools are impressive on how they can be used in creating dynamic images, whether for business use in charting, or even just in CGI development.

In this tutorial, I will walk you through creating some of the tools typically used, and some of the simple methods.  We will discuss the following, respectively :
    Compiling ImageMagick and PerlMagick  This is where we discuss the "How's" of installing ImageMagick and PerlMagick.  There are a couple of quirks that occur when compiling, and we discuss why they occur.  
    Command-Line Tools  Once installed, I'll introduce you to some simple command line functions to use the tools that come with ImageMagick.  Once we understand these better, we can proceed to implement PerlMagick.  
    PerlMagick  A good understanding of ImageMagick, or even image manipulation is key to implementing the PerlMagick interface.  Here, we'll take a solid look at constructing a simple PerlMagick script.  
    File Reading and Writing  Reading and writing images the key to any image manipulation tool.  Because of that, we'll discuss the basic methods for reading and writing images, plus take a look at some quirks of working with files in a CGI environment.  
    Creating Images from Scratch  If developing a dynamic image utility, often we'll need to create images, without having a previous image to work from.  Here's how we do that.  
    Drawing Primitives  Adding lines, squares, circles, or other "primitives" using PerlMagick is often not discussed, and it's difficult to find sources on it.  I'll teach you how to draw primitives onto your images.  
    Writing on the Image  This is where we can get tricky.  Writing on images is a key principle of image manipulation.  
    Adding Transparency  Some image formats (such as .gif, and .png) allow transparency.  These formats are most often used in web design, allowing the image to properly show background colors and creating more seamless integration of HTML and graphics.  
    Creating Animations  Want to use the PerlMagick interface for handling logo creation?  I'll walk you through a quick example, plus describe a few of the required attributes and their effects on the resulting animation.  

Compiling ImageMagick and PerlMagick

If you can install from a package, do it.  Whomever has created the package has done some homework on setting it up properly for the specific operating system.  However, it may become apparent that a package is not available.  If this is the case, the procedure is simple and straight forward, and you don't need to be a programmer to do it.  Here's how :

First, download the source code (from http://www.imagemagick.org/).  Save this to the computer you wish to install ImageMagick on.  You will need to uncompress the file and open all of the source code, and change into the newly created directory.  This is done with the following commands (in bold) :
    [/tmp] $ tar -xzf ImageMagick-5.5.7-15.tar.gz
    [/tmp] $ cd ImageMagick-5.5.7
    
    
    
One of the pitfalls of compiling ImageMagick and PerlMagick is in the unification of the two packages.  When you download (from http://www.imagemagick.org/) the source code for ImageMagick, it includes the PerlMagick code as well.  But, in order to compile and install the Perl::Magick (the perl library name), the ImageMagick libraries must already be installed.  This can be done by configuring the entire package without PerlMagick, compiling and installing, and then re-configuring the entire package with PerlMagick.  Then you just have to compile the PerlMagick code and install that.  For example :
    [/tmp/ImageMagick-5.5.7] $ ./configure --without-perl --without-x \
    --with-windows-font-dir=/usr/share/fonts/defaults/TrueType
    configuring ImageMagick 5.5.7
    checking build system type... i686-pc-linux-gnu
    [... lots more output ...]
    LIBS     = -ltiff -lfreetype -ljpeg -lpng -lbz2 -lz -lpthread -lm
    [/tmp/ImageMagick-5.5.7] $ make && make install
    Making all in coders
    make[1]: Entering directory `/tmp/ImageMagick/ImageMagick-5.5.7/coders'
    if /bin/sh ../libtool --silent --mode=compile gcc -DHAVE_CONFIG_H -I../ -I. -I. -I../magick
    -I.. -I.. -I../magick -I/usr/include/freetype2 -D_FILE_OFFSET_BITS=64 -D_REENTRANT -g -O2
    -Wall -MT art.lo -MD -MP -MF ".deps/art.Tpo" -c -o art.lo art.c; \
    then mv -f ".deps/art.Tpo" ".deps/art.Plo"; else rm -f ".deps/art.Tpo"; exit 1; fi
    [... lots more output ...]
    /usr/bin/install -c -m 644 QuickStart.txt /usr/local/share/ImageMagick-5.5.7/QuickStart.txt
    make[2]: Leaving directory `/tmp/ImageMagick/ImageMagick-5.5.7'
    make[1]: Leaving directory `/tmp/ImageMagick/ImageMagick-5.5.7'
    [/tmp/ImageMagick-5.5.7] $ ./configure --with-perl --without-x \
    --with-windows-font-dir=/usr/share/fonts/defaults/TrueType
    checking build system type... i686-pc-linux-gnu
    [... lots more output ...]
    LIBS     = -ltiff -lfreetype -ljpeg -lpng -lbz2 -lz -lpthread -lm
    [/tmp/ImageMagick-5.5.7] $ cd PerlMagick
    [/tmp/ImageMagick-5.5.7/PerlMagick] $ perl Makefile.PL
    Checking if your kit is complete...
    Looks good
    Writing Makefile for Image::Magick
    [/tmp/ImageMagick-5.5.7/PerlMagick] $ make && make install 
    cp Magick.pm blib/lib/Image/Magick.pm
    AutoSplitting blib/lib/Image/Magick.pm (blib/lib/auto/Image/Magick)
    [... lots more output ...]
    Writing /usr/lib/perl5/site_perl/5.6.1/i386-linux/auto/Image/Magick/.packlist
    Appending installation info to /usr/lib/perl5/5.6.1/i386-linux/perllocal.pod
    
Now, we'd better take a more in depth look at the configure commands.  You will note that we specified a --with-windows-font-dir=/usr/share/fonts/defaults/TrueType and a --without-x.  These two configure options are vital to both using TrueType fonts and also running on a machine that does not have XWindows installed (typically servers).

First, we configure the software to not use the PerlMagick stuff, by specifying the --without-perl configure option.  Then, we run the make command (in BSD, gmake may be a better option), and then make install.  The make install command still uses the make command to copy the libraries into the proper places.

Then, we reconfigure the software to use PerlMagick, by replacing the --without-perl with the --with-perl.  Once reconfigured (this resets the PerlMagick stuff up), we step into the PerlMagick directory, and create the new make file.  This is done by executing a perl script located in that directory, called Makefile.PL, and then run the make and make install commands again.  This installs the proper Perl::Magick libraries for perl into their proper places so that we can use them.

Command-Line Tools

When it comes to command line tools, it really depends on what you need to do, as to which tool.  The list is :
    animate Assembling images into an animation.
    composite Merging images.
    conjure The Magick scripting language (MSL) will primarily benefit those that want to accomplish custom image processing tasks but do not wish to program, or those that do not have access to a Perl interpreter or a compiler.  The interpreter is called conjure.
    convert Converting images from one format to another.
    display Display the image(s) on the XWindows display.
    identify This command is used to determine image characteristics, from format, to palette/RGB colorspace.
    import This tool reads an image from any visible window on an X server and outputs it as an image file. You can capture a single window, the entire screen, or any rectangular portion of the screen.
    mogrify Mogrify  transforms  an image or a sequence of images. These transforms include image scaling, image rotation, color reduction, and others. Each transmogrified image overwrites the corresponding original  image, unless an option such as -format causes the output filename to be different from the input filename.  Make changes to the image, such as blurs, sharpens, etc.
    montage montage  creates  a composite image by combining several separate images. The images are tiled on the composite image with the name of the image optionally appearing just below the individual tile.
Examples of calling the functions can be obtained by typing "man {functionname}", such as man convert.  Still, if you need to create a JPG thumbnail of an image that is 100 by 100 pixels, or change from an MIFF (Magick Image File Format) to a Sun Raster format :
    [/tmp] $ convert -size 120x120 filename.jpg -resize 120x120 +profile "*" filename-thumbnail.jpg
    [/tmp] $ convert cockatoo.miff sun:cockatoo.ras
    

PerlMagick

As a brief introduction to using PerlMagick, you should be familiar with perl in general, and using the object oriented methods associated with perl.  As with each perl program, we must specify the introductory line :
    #!/usr/bin/perl
    
Then, we ensure that the module objects are there :
    use Image::Magick;
    
Simply, we just declare a new Image::Magick object.  This can be done in two forms.  I will show you both forms, but suggest the latter one, just in case you have implemented a new function :
    my $imgs = new Image::Magick;
    my $imgs = Image::Magick->new();
    
Now, the most commonly functions are Set(), Get(), Read(), and Write().  These functions are used to read and write images, and also to retrieve and set attributes of images in memory.  These functions are usually written as associated with our image object :
    $imgs->Set(variable name=>variable value);
    
Now, we can get into the nitty gritty of handling images.

File Reading and Writing

To read an image from a disk, or to write one is simple.  but, rather than delving deep into the system calls implemented by the functions, we just simply need to understand what we do.  Now, we can read in multiple images, and this will create an array object, or it's also used in creating animations, but we'll discuss that later on.  In the mean time, a simple "multi-image" read statement is just passed an array of images to read.  The two examples are (one single image, and one multi-image) :
    $imgs->Read('/tmp/this-image.jpg');
    $imgs->Read('/tmp/logo-01.jpg','/tmp/logo-02.jpg');
    
Writing is similar, except in cases of multiple images.  A multi-image write call must either specify the image to write, or it will write the entire image as an animation.  For example :
    $imgs->Write('GIF:/tmp/logo.gif');
    $imgs->[1]->Write('GIF:/tmp/logo-02.gif');
    
The first example is for writing a standard image to a file, and the second example is for writing a single image in a multi-image to a file.

But, how does writing to a browser work in terms of CGI?  Here's where it gets tricky.  When a browser makes a request, the browser expects to see HEADERS back from the webserver that is running the CGI.  At least one header is required, and that is Content-Type.  In addition, the file streams work a bit differently, because we can't write to "a file", per se.  So, we print the Content-Type header, and a blank line so the browser knows that we're done printing headers, and then print the image.  We put the output stream into binary mode before writing the image, just so we get the proper image.  It works like this :
    #!/usr/bin/perl
    
    use Image::Magick;
    
    my $imgs = Image::Magick->new();
    $imgs->Read("logo.gif");
    
    print "Content-Type: image/gif\n\n";
    binmode STDOUT;
    $imgs->Write("-");
    
The above script should read in the image, write the proper content type to the web browser, then convert the output stream to binary mode.  After converting the output stream, we dump the image that we've read.  This example would be better served to be rewritten using basic perl commands, but it will act as a starting point for you to read and write images.

Now, if you've got the image saved with a .jpg extension, but it's really just a .gif file, you can add a format specifier to the filename by preceding the filename with the format and a colon.  For example :
    $imgs->Read("gif:logo.jpg");
    
This works for both the Read() and the Write() functions, which means you can also change formats for the image (converting from .jpg to .gif).

Creating Images from Scratch

Creating images from scratch is complex in thought, yet simple in implementation.  Rather than creating the image object, resizing the image, and filling a square with a color (still works), one could simply use the read command.  If you use the read command, and read a file format of type "xc" followed by a filename that is equivelent to the X color, i.e. :
    $imgs->Read("xc:green");
    
Prior to calling this read command, you might want to resize the image to how big you want it.  This is done with the Set() function call, using a variable name of "size" and a value of "{width}x{height}".  For example, creating a new image that is 60 pixels by 30 pixels with a blue color :
    $imgs->Set(size=>"60x30");
    $imgs->Read("xc:green");
    

Drawing Primitives

Drawing primitives isn't discussed very often at all.  This is not because it can't be done, but because there is no real reason to do so, as most primitives can be created with other software.  In other words, if you are really just trying to create a chart system, you might be better off using the GD package or GIFGraph.  Still, there are instances where you want to do this.  I've run across a couple of situations where having two libraries just isn't a good idea.  So, I've used PerlMagick to implement the "primitives".  The basic core of drawing primitives is the Draw() function.  This function requires at least two parameters, a "primitive" and a "points".  The value of the primitive variable is the type of primitive being drawn.  For example, to draw a red rectangle, one would use the command :
    $mage->Draw(fill=>'red', primitive=>'rectangle', points=>'20,20 100,100');
    
The points value depends on the primitive you are trying to draw.  The following guidelines apply :
    PrimitivePoints Format
    arc{x-center},{y-center} {x-endpoint-1},{y-endpoint-1} {x-endpoint-2},{y-endpoint-2}"
    bezier{x-end-1},{y-end-1}, {x-end-2},{y-end-2}[, {x-end-n},{y-end-n}]
    circle{x-center},{y-center},{x-radius},{y-radius}
    color
    ellipse{x-center},{y-center} {x-radius-1},{y-radius-1} {x-radius-2},{y-radius-2}
    line{x-start},{y-start} {x-end},{y-end}
    matte
    path*too complex for writing
    point{x},{y}
    polygon{x-corner-1},{y-corner-1} {x-corner-2},{y-corner-2}
    polyline{x-endpoint-1},{y-endpoint-1} {x-endpoint-2},{y-endpoint-2} [{x-endpoint-3},{y-endpoint-3}]
    rectangle{x-upper-left},{y-upper-left} {x-lower-right},{y-lower-right}
    text{x},{y} "{what text}"
The primitives are relatively straight forward.  For example, to create a circle, we'd use the following command :
    $imgs->Draw(stroke=>'blue', primitive=>'circle', points=>'20,20 15,15');
    

Writing on the Image

There are actually two different methods that we can use to write on an image.  First, we can use the primitive function.  The problem with doing the primitive function is we get only one font, and it is very basic.  We can also make a call to the Annotate() function.  First, the primitive :
    $imgs->Draw(primitive=>'text',points=>'15,15 "awesome"',stroke=>green);
    
will give us a green "awesome".  Note the font and it's quality.  Very poor.  So, we'll opt to use the Annotate function in the following way :
    $imgs->Annotate(font=>'cour.ttf', pointsize=>40, fill=>'green', text=>"awesome");
    
If you have the Courier TrueType font available, you will get "awesome" in green, but done in a 40 point size, plus using the Courier font.  You can specify locations using the x and y variables, and also add a "gravity" variable.  Gravity means that the text will be centered on the x,y position, or southwest, or northeast, or right, etc.  This means you can create right justified text by specifying the upper left hand corner, and using a southwest gravity :
    $imgs->Annotate(
        font=>'cour.ttf',
        pointsize=>40,
        fill=>'green',
        text=>"awesome",
        gravity=>'southwest',
        x=>100,
        y=>20
    );
    
Play around with the settings, and you'll find a rather potent arsenal of font and image writing capabilities.

Adding Transparency

Transparency is a nice effect when it comes to different formats.  Of particular note is Internet graphics and transparencies, where the choices become very limited.  For example, PNG (Portable Network Graphics) are displayed by most browsers, but some browsers (e.g. Internet Explorer) just won't display any transparency at all - just white color.  GIF (Graphic Interchange Format) uses a "solid" transparency, which means no semi-transparent colors.  That drop-shadow fade you are trying to accomplish just won't work very well over the Internet.  However, most current browsers DO support the PNG format, so if you don't mind requiring visitors to have the lastest, go with PNG (animations are not supported with PNG, either).

Here, though, since we are ultimately creating a logo, we'll be doing so with GIF, because we want it to be animated.  So, with a GIF format, we first ensure that the colorspace is for transparency.  Once we've gotten the proper colorspace, we'll then set which "color" we want to be transparent.
                           
In the above to images, we've got a single picture (the one in black), that we're going to convert to have a transparent background.  To accomplish this, we'd use the following code :
    $imgs->Set(colorspace=>'transparent');
    $imgs->Transparent(color=>'#000000');
The result is the image on the right, or the one with a transparent background.  Simple, and straight forward.  Now, with GIF's, we really don't need to set the colorspace prior to the Transparent() command, but just do it anyway to ensure the habits of proper handling so you don't shoot yourself in the foot down the road.

Creating Animations

Remember the good old days when we'd sit in elementary school with a notebook, and draw the stick figures on each page?  Then we'd flip through the pages, and it gave the appearance of true motion?  Well, that's what we need to do.  We get all of the images together, and then combine them into a series of pages, each one being called a "frame".

Animated logo's have become a novelty that is often either overdone, or done too simply.  But, what is the process that is used?  I've actually used a few different methods for creating nice 3 dimensional logo's, but the one I prefer is this :
  1. Ray-trace a 3 dimensional definition into a series of images.
  2. Assemble each "frame" into one big sequence of frames, using ImageMagick
  3. Set any transparency properties, again using ImageMagick
  4. Write the image out
This gives some very nice effects (such as my sharktooth logo, or the firebird logo).  I name the images sequentially (such as firebird-00.gif, firebird-01.gif, etc.), then call a script.  This script creates the ImageMagick object, reads in the images in alphabetical order, sets the transparency, and then writes it out.  Since we've already discussed how to set transparency, this becomes easier.  I'll walk you through the details of what the commands do after showing the script snippets :
    my $imgs = Image::Magick->new();
    
    # the animation stuff
    $imgs->Read(sort(@ARGV));
    
    #set the animation characteristics
    $imgs->Set(delay=>10);
    $imgs->Set(loop=>0);
    $imgs->Set(dispose=>2);
    
    # write the animation out
    $imgs->Write('logo.gif');
    
Now, for the description.  First, we Read() an array of images (my example has the filenames provided on the commandline and sorts them into ascending order).  This will turn the $imgs object into an array reference rather than a single object.  We then make adjustments by Set()-ting the delay (in miliseconds) between frames, set an endless loop (if non-zero, the animation will loop that many times and then stop), and the refresh (termed as dispose) method between frames, and Write() it out.  So, according to the above example, we'll end up with an endless loop, with 1/100th of a second between each picture.  The result is seen to your left.

There are actually four different dispose methods.  The first (0), is for NO refresh method.  The second (1) is for repainting the background, and the third (2) refreshes from the previous frame.  Did I say there were four disposal methods?  Yes, I did.  The fourth (3) is a valid option, but is really an undefined action - in other words, don't use this one.

Epilogue

We've covered some rather basic things, but also covered some fairly complex thoughts.  As you've seen, the ImageMagick suite of image manipulation software is both easy to use and powerful in it's functionality.  We've talked a little of command-line tools, and gotten heavily into perl scripting with the ImageMagick library.

It is an obvious choice as to a good software suite to use in scripting or dynamic images, as the possibilities are endless.  Play around with the scripts or tools, and explore the world of image manipulation.

Java - Multithreading Example

An old example of threading in Java (Java doesn't natively support fork() ) :
    
    import java.lang.Thread;
    import java.lang.System;
    import java.lang.Math;
    import java.lang.InterruptedException;
    import java.lang.Runnable;
    
    class ThreadTest2 {
     public static void main(String args[]) {
      Thread thread1 = new Thread(new MyClass("thread1: "));
      Thread thread2 = new Thread(new MyClass("thread2: "));
      thread1.start();
      thread2.start();
      boolean thread1IsAlive = true;
      boolean thread2IsAlive = true;
      do {
       if(thread1IsAlive && !thread1.isAlive()){
        thread1IsAlive = false;
        System.out.println("Thread 1 is dead.");
       }
       if(thread2IsAlive && !thread2.isAlive()){
        thread2IsAlive = false;
        System.out.println("Thread 2 is dead.");
       }
      }while(thread1IsAlive || thread2IsAlive);
     }
    }
    class MyClass implements Runnable {
     static String message[] = {"Java","is","hot,","aromatic,","and",
      "invigorating."};
     String name;
     public MyClass(String id) {
      name = id;
     }
     public void run() {
      for(int i=0;<message.length;++i) {
       randomWait();
       System.out.println(name+message[i]);
      }
     }
     void randomWait(){
      try {
       Thread.currentThread().sleep((long)(3000*Math.random()));
      }catch (InterruptedException x){
       System.out.println("Interrupted!");
      }
     }
    }
    

Meaning of Flowers

As every flower lover knows, flowers have a language of their own. Every sentiment is expressed in one form or another by these delicate blooms. Of course, even the experts disagree on the "true meaning" of many flowers and most have different meanings to different people. So, while all flowers convey thoughtfulness and love, here are some of the more traditional flower meanings, according to one source. See, if you agree. And, remember, a gift of flowers for a special someone will always create its own personal meaning, too.

Flower Color Arrangement Meaning
Acacia Concealed Love
Acacia Beauty in Retirement
Acacia Chaste Love
Ambrosia Your Love is Reciprocated
Amaryllis Pride
Amaryllis Pastoral Poetry
Anemone Forsaken
Arbutus Thee Only Do I Love
Aster Symbol of Love
Aster Daintiness
Azalea Take Care of Yourself for Me
Azalea Temperance
Azalea Fragile Passion
Azalea Chinese Symbol of Womanhood
Bachelor Button Single Blessedness
Begonia Beware
Bells Of Ireland Good Luck
Bittersweet Truth
Bluebell Humility
Cactus Endurance
Camellia Pink Longing for you
Camellia Red You're a Flame in My Heart
Camellia White You're Adorable
Carnation Fascination
Carnation Woman Love
Carnation Pink I'll Never Forget You
Carnation Red My Heart Aches For You
Carnation Red Admiration
Carnation Purple Capriciousness
Carnation Solid Color Yes
Carnation Striped No
Carnation Striped Refusal
Carnation Striped Sorry I Can't Be With You
Carnation Striped Wish I Could Be With You
Carnation White Sweet and Lovely
Carnation White Innocence
Carnation White Pure Love
Carnation White Woman's Good Luck Gift
Carnation Yellow You Have Disappointed Me
Carnation Yellow Rejection
Cattail Peace
Cattail Prosperity
Chrysanthemum You're a Wonderful Friend
Chrysanthemum Cheerfulness and Rest.
Chrysanthemum White Truth
Chrysanthemum Yellow Slighted Love
Crocus Cheerfulness
Cyclamen Resignation and Good-bye
Daffodil Regard
Daffodil Unrequited Love
Daffodil You're the Only One
Daffodil The Sun is Always Shining when I'm with You
Daisy Innocence
Daisy Loyal Love
Daisy I'll Never Tell
Daisy Purity
Dandelion Faithfulness
Dandelion Happiness
Fern Magic
Fern Fascination
Fern Confidence and Shelter
Fir Time
Flax Domestic Symbol
Forget-Me-Not True Love
Forget-Me-Not Memories
Forsythia Anticipation
Gardenia You're Lovely
Gardenia Secret Love
Geranium Stupidity
Geranium Folly
Gladioli Give Me a Break
Gladioli I'm Really Sincere
Gladioli Flower of the Gladiators
Gloxinia Love at First Sight
Heather Lavender Admiration
Heather Lavender Solitude
Heather White Protection
Heather White Wishes Will Come True
Holly Defense
Holly Domestic Happiness
Hyacinth Games and Sports
Hyacinth Rashness
Hyacinth Flower Dedicated to Apollo
Hyacinth Blue Constancy
Hyacinth Purple I am Sorry
Hyacinth Purple Please Forgive Me
Hyacinth Purple Sorrow
Hyacinth Red Or Pink Play
Hyacinth White Loveliness
Hyacinth White I'll Pray for You
Hyacinth Yellow Jealousy
Hydrangea Thank You for Understanding
Hydrangea Frigidity
Hydrangea Heartlessness
Iris Fleur-de-lis
Iris Emblem of France
Iris Your Friendship Means so Much to Me
Iris Faith
Iris Hope
Iris Wisdom and Valor
Iris My Compliments
Ivy Wedded Love
Ivy Fidelity
Ivy Friendship
Ivy Affection
Jonquil Love Me
Jonquil Affection Returned
Jonquil Desire
Jonquil Sympathy
Jonquil Desire for Affection Returned
Larkspur Pink Fickleness
Lily White Virginity
Lily White Purity
Lily White Majesty
Lily White It's Heavenly to be with You
Lily Yellow I'm Walking on Air
Lily Yellow False and Gay
Lily Calla Beauty
Lily Day Coquetry
Lily Day Chinese Emblem for Mother
Lily Eucharis Maiden Charms
Lily Tiger Wealth
Lily Tiger Pride
Lily Of The Valley Sweetness
Lily Of The Valley Tears of the Virgin Mary
Lily Of The Valley Return to Happiness
Lily Of The Valley Humility
Lily Of The Valley You've Made My Life Complete
Magnolia Nobility
Marigold Cruelty
Marigold Grief
Marigold Jealousy
Mistletoe Kiss me
Mistletoe Affection
Mistletoe To Surmount Difficulties
Mistletoe Sacred Plant of India
Monkshood Beware
Monkshood A Deadly Foe is Near
Moss Maternal Love
Moss Charity
Myrtle Love
Myrtle Hebrew Emblem of Marriage
Narcissus Egotism
Narcissus Formality
Narcissus Stay as Sweet as You Are
Nasturtium Conquest
Nasturtium Victory in Battle
Oleander Caution
Orange Blossom Innocence
Orange Blossom Eternal Love
Orange Blossom Marriage and Fruitfulness
Orange Mock Deceit
Orchid Love
Orchid Beauty
Orchid Refinement
Orchid Beautiful Lady
Orchid Chinese Symbol for Many Children
Orchid Cattleya Mature Charm
Palm Leaves Victory and Success
Peony Shame
Peony Happy Life
Peony Happy Marriage
Petunia Resentment
Petunia Anger
Petunia Your Presence Sooths Me
Pine Hope
Pine Pity
Poppy Eternal Sleep
Poppy Oblivion
Poppy Imagination
Poppy Red Pleasure
Poppy White Consolation
Poppy Yellow Wealth
Poppy Yellow Success
Primrose I Can't Live Without You
Primrose Evening Inconstancy
Rose Bridal Happy Love
Rose Dark Crimson Mourning
Rose Hibiscus Delicate Beauty
Rose Leaf You May Hope
Rose Pink Perfect Happiness
Rose Pink Please Believe Me
Rose Red Love
Rose Red I Love You
Rose Tea I'll Remember Always
Rose Thornless Love at First Sight
Rose White Innocence and Purity
Rose White I am Worthy of You
Rose White You're Heavenly
Rose White Secrecy and Silence
Rose White And Red Mixed Unity
Rose White And Red Mixed Flower Emblem of England
Rose White-Dried Death is Preferable to Loss of Virtue
Rose Yellow Decrease of Love
Rose Yellow Jealousy
Rose Yellow Try to Care
Rosebud Beauty and Youth
Rosebud A Heart Innocent of Love
Rosebud Red Pure and Lovely
Rosebud White Girlhood
Rosebud Moss Confessions of Love
Roses Bouquet Of Mature Blooms Gratitude
Roses Single Full Bloom I Love You
Roses Single Full Bloom I Still Love You
Smilax Loveliness
Snapdragon Deception
Snapdragon Gracious Lady
Spider Flower Elope with Me
Stephanotis Happiness in Marriage
Stephanotis Desire to Travel
Stock Bonds of Affection
Stock Promptness
Stock You'll Always Be Beautiful to Me
Sweetpea Good-bye
Sweetpea Departure
Sweetpea Blissful Pleasure
Sweetpea Thank You for a Lovely Time
Tulip Perfect Lover
Tulip Frame
Tulip Flower Emblem of Holland
Tulip Red Believe Me
Tulip Red Declaration of Love
Tulip Variegated Beautiful Eyes
Tulip Yellow There's Sunshine in Your Smile
Violet Modesty
Violet Blue Watchfulness
Violet Blue Faithfulness
Violet Blue I'll Always Be True
Violet White Let's Take a Chance
Zinnia Magenta Lasting Affection
Zinnia Mixed Thinking (or In Memory) of an Absent Friend
Zinnia Scarlet Constancy
Zinnia White Goodness

Creating a DVD in Linux

There are a number of documents created that describe the inception of a DVD from DV (Digital Video) files, or even "ripping" (capturing the contents of a DVD into a movie file), but none that I saw delt with convering a captured movie from a TV tuner card into a DVD.  This document describes the basic steps performed in taking a video capture file and converting it into a DVD.

The first step is to carve the captured file into the exact pieces desired.  I performed this step using the mplayer in playing to the point where I wanted the video capture file to start, and then noting the "seconds" field.  Then, I noted where the ending point was that I needed from the video.  At that point, I ran :
    
    mencoder -ovc copy -oac copy -ss 604 -endpos 4845 -o chopped_file.mpg original-file.mpg
    
    
The above command took the file original-file.mpg and made a copy - but only copied 4845 seconds (see the -endpos 4845 parameter) starting from the 604 second mark (see the -ss 604 parameter).  The copy was named chopped_file.mpg.

At this point, it is a good time to note that the -endpos parameter is not an "end position", but a time from the -ss (or start position), so that can often be confusing.

Once I had the file I needed, I converted that to a DVD-compatible, MPeg-encoded file using the ffmpeg utility :
    
    ffmpeg -i chopped_file.mpg -target dvd -aspect 4:3 -sameq dvd-ready.mpg
    
    
The ffmpeg command executed read in the chopped_file.mpg, forced a dvd format (the -target dvd parameter) in a TV format (not wide screen - that would have used a -aspect 16:9 parameter.  The -sameq parameter just meant to preserve as much of the quality as possible.  The resulting file was dvd-ready.mpg.

It is also possible to do the previous two steps (mencoder and ffmpeg) in one fell swoop.  The following command will extract the segment of video that is needed, de-interlace it, and get it ready to be put onto a DVD image.
    
    ffmpeg -i original-file.mpg -ss 00:10:04 -t 01:20:46 -target dvd -aspect 16:9 -deinterlace -sameq dvd-ready.mpg
    
    
This is the perfect opportunity to convert that dvd-ready movie file into a DVD video image.  This is done using the wonderful tool called dvdauthor, in two stages.  The first creates a title video from the dvd-ready.mpg file we have created, and sets up some of the required pieces for a DVD video.  The second creates the table of contents and completes the structure for the subsystem :
    
    dvdauthor --title -f dvd-ready.mpg -o DVD/
    dvdauthor -T -o DVD
    
    
Note : you may want to create the DVD/ directory that the dvdauthor commands above will be placing the files into because this is not done by default.

At this point, it is time to create the ISO image.  Some experts prefer to use growisofs, but I'm just a little pickier than that - I want more control over the command.  I typically use mkisofs, but I'll shorten the command to the essential parameters :
    
    mkisofs -dvd-video -udf -o dvd.iso DVD/
    
    
The -dvd-video parameter tells mkisofs to turn on some minor DVD-compatability (setting the order of the appropriate files and padding betweem files if required).  The -udf parameter is adding UDF file system compatability (very similar to Joliet file systems on CD-Rom's).  The -o dvd.iso is telling the mkisofs to create the DVD video image as dvd.iso, and the DVD/ is where the base of the image will come from.

Once that is completed, it is possible to burn the ISO image directly to the DVD recorder using cdrecord, burncd, K3B (if you prefer GUI's), or even rebooting into windows and using Nero.  It should be a functional DVD video at that point in time.

Old: Samba, LDAP


An old task I thought I'd toss up into a post.  I had all of my user accounts into LDAP for my Unix machines, but some of my users persist in running Windows.  I needed a Samba file server, but I wanted the same LDAP credentials to work.  Well here's how to do it. The Samba HOWTO has a fair bit of documentation about this subject, but it wasn't super clear to me and I generally feel that a second view on a subject can be helpful.

This information is based on Samba 3.0.0 and newer. Older versions of Samba have some LDAP support but things changed significantly with version 3.0.0. These are not instructions for making Samba act as a domain controller, something I know nothing about. They're just instructions for setting up a plain file server using LDAP as the backend for Samba user settings and passwords.

Populating LDAP

I'm going to presume you already have LDAP working and populated with user accounts using the posixAccount object class or similar. If not then see the link above to my Kerberos and LDAP HOWTO, you'll want to start there. I'm also assuming your LDAP server is OpenLDAP. The first step is to add the Samba LDAP schema file to your LDAP servers. This file can be found at examples/LDAP/samba.schema in the Samba source distribution, or at /usr/share/doc/samba-ver/LDAP/samba.schema on Red Hat systems. Copy that into /etc/openldap/schema/ or wherever your schema files are kept on your LDAP servers, add a line to slapd.conf referencing it it, and restart slapd.

Next you need to populate your user accounts with the sambaSamAccount object class and associated attributes. sambaSID is the only additional attribute required by the schema, but you'll need at least sambaLMPassword and sambaNTPassword as well. In addition to those I added sambaAcctFlags for consistency with the smbpasswd file. You'll also need to add a sambaDomain entry for each Samba server (otherwise Samba will repeatedly try to add one for you) and configure a user that Samba can use to access the sambaLMPassword and sambaNTPassword fields.

Let's start with the SID and sambaDomain. SID is short for Security IDentifier as best I can tell and seems to be the Windows equivalent of Unix UIDs and GIDs, with the ability to reflect organizational hierarchy. If you have a real Windows domain then the SID heirarchy is created automatically, but we just want to fake it. The shortest one I could get Samba to take is S-1-0-0. I haven't been able to find a reference to the structure of a SID so I just guessed until it worked. So your resulting sambaDomain entry for myserver.example.com will look something like this. I put these under a seperate "samba" organizationalUnit to keep them seperate from users, groups, etc.

dn: sambaDomainName=myserver,ou=samba,dc=example,dc=com
objectClass: sambaDomain
sambaDomainName: myserver
sambaSID: S-1-0-0
Before we move on to the actual user entries, you should create an entry in LDAP that Samba can authenticate as and access the sambaLMPassword and sambaNTPassword attributes. The contents of those attributes are equivalent to the user's plaintext password when authenticating to Samba, so you need to make sure your LDAP server ACLs prohibit anyone but the special Samba account from accessing them. The Samba account needs to have a regular userPassword entry, SASL or other fancy authentication methods aren't supported. Here's roughly what mine looks like. The password entry can be generated with slappasswd.

dn: uid=samba_servers,ou=people,dc=example,dc=com
objectClass: person
objectClass: uidObject
uid: samba_servers
description: Account used by Samba servers to access user passwords
cn: samba_servers
sn: samba_servers
userPassword: {SSHA}xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
And a sample ACL for slapd.conf:

access to attr=sambaLMPassword,sambaNTPassword
        by dn.exact="uid=samba_servers,ou=people,dc=example,dc=com" read
        by * none
Ok, now the regular user entries themselves. Here are the relevant attributes specific to Samba. The password values can be generated by mkntpwd, the souce to which can be found in examples/LDAP/smbldap-tools/mkntpwd/ in the Samba source distribution, or in /usr/share/doc/samba-ver/LDAP/smbldap-tools/mkntpwd/ on Red Hat systems. Keeping them in sync with Kerberos or wherever you store your Unix passwords is generally site specific and is left as an exercise to the reader.

The first part of the SID should match the SID in the sambaDomain entry created above. The final element is a little weird. Take the user's Unix UID (13988 in this case), multply it by 2 and add 1000. This is the formula used by the smbldap-tools scripts included with Samba. They do the same thing for groups but add 1001 instead. The result is that you can store users and groups in the same SID space and not have the UIDs and GIDs collide, because UIDs always translate to an even number and GIDs translate to an odd number.

objectClass: sambaSamAccount
sambaAcctFlags: [U          ]
sambaLMPassword: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
sambaNTPassword: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
sambaSID: S-1-0-0-28976
Configure Samba

At this point you should have LDAP populated with all of the necessary fields. Now the moment of truth, to configure Samba to reference LDAP for this information. Here's a sample of what goes in smb.conf. See the note in the comments here about storing the password for the special Samba user.

security = user
passdb backend = ldapsam:ldap://ldap.example.com
ldap ssl = start tls
ldap suffix = dc=example,dc=com
ldap user suffix = ou=people
ldap group suffix = ou=group
# FYI, the password for this user is stored in
# /etc/samba/secrets.tdb.  It is created by running
# 'smbpasswd -w passwd'
ldap admin dn = uid=samba_servers,ou=people,dc=example,dc=com
Restart Samba and watch syslog for errors. If you're curious you can view the contents of secrets.tdb with tdbdump, it comes with Samba.

Simple Digital Photography Notes



  • If using a light/reflective backdrop (e.g. mirrors or snow) don't use a manual mode. Set the exposure so that the camera doesn't "dim" or auto-adjust the exposure.
  • If taking an outdoor picture, directional light is best, making a dawn or dusk lighting the best situation.
  • If taking a picture near lights of any kind, arrange a good photograph of the lights. Then, place the occupants/subject into the picture to fill where it should be.
  • Only use a flash around noon - at this time, the flash will soften the hard light, but at other times, it will flatten the photograph.
  • Eye lines should be approximately a third down from the top of the picture.

Exim: Authenticated SMTP


With authenticated SMTP, you can administer who can send E-Mails through your web server. With control such as this, you could set up your network so that it allows users who are not located inside to send E-Mail. You may end up with your network as sending anything from inside and authenticated from outside. This means that roaming users are in good hands. It also means you can trace the messages to the user who logged in (if they authenticated). For example, the logs may look like (the unauthenticated entry being first, and the major differences in bold) :

    
    2003-08-18 16:04:25 19os6v-000GxP-5X <= joe@sharktooth.org H=sharktooth.org [207.173.156.3] P=smtp S=3654 id=99327$0bC49Hckb4Uecr@ywndp.your-world-news.com
    2003-08-18 16:04:25 19os6y-000GyU-3B <= joe@sharktooth.org H=sharktooth.org [207.173.156.3] P=asmtp A=plain:joe S=929 id=3F414EAB.2010107@somehost.net
    

You can accomplish this using the following entries in the Exim configuration authenticators section (see the Exim Documentation for more information). In short, these authenticators are required to work with most clients on authenticated SMTP. Note, Outlook Express uses the LOGIN authenticator, while Netscape/Mozilla uses the PLAIN authenticator. The following implementations use a database to house the passwords, encrypted by the crypt() function in Unix. You can do plain passwords, but that gets dangerous with security holes. In fact, you can turn on cryptographic functions to make this better. But, our example :

    
    plain:
      driver = plaintext
      public_name = PLAIN
      server_condition = "${if and { \ {!eq{$2}{}} \ {!eq{$3}{}} \ {crypteq{$3}{${lookup mysql{SELECT password FROM users WHERE username='$2'}{$value}fail}}} \ } {yes}{no}}"
      server_set_id = $2
    login:
      driver = plaintext
      public_name = LOGIN
      server_prompts = "Username:: : Password::"
      server_condition = "${if and { \ {!eq{$1}{}} \ {!eq{$2}{}} \ {crypteq{$2}{${lookup mysql{SELECT password FROM users WHERE username='$1'}{$value}fail}}} \ } {yes}{no}}"
      server_set_id = $2
    
Notice the two differences between the authenticators :
  1. PUBLIC NAME, which will resolve to PLAIN, and LOGIN (see above description for which is used by what software).
  2. LOGIN uses $1 for the username and $2 for the password, while PLAIN uses $2 for the username and $3 for the password. This is because the AUTH PLAIN protocol supplies the username and password on a single line, while the AUTH LOGIN supplies the username after prompts, where the remainder of the line is blank (so $1 would be blank).

Once these authenticators are configured to your needs, just add the
auth_advertise_hosts = *
This will turn on advertising for all hosts trying to send E-Mail. Now, you can configure your clients to use authentication for SMTP, and it should work fine!

Client-Side Setup :

How does SMTP work?

Prior to delving into Authenticated SMTP, we should probably give a short description of SMTP. SMTP is one of the famous Internet acronyms. It stands for "Simple Mail Transfer Protocol". The design of SMTP is the ability to relay Electronic Mail messages (E-Mail) from one computer to another.

SMTP does not often go directly to the recipients computer. It usually stops and rests in the users mail box, where the user will retrieve it. This intermediary is called an "SMTP server". Often, people send the initial message through their own "SMTP Server", commonly refered to as an "outgoing mail server".

SMTP is very similar to sending a real life letter, but without the "Do Not Bend Mail Into the Crusher" machinery. First, there are a few entities in the sending and recieving of mail. There is the local Mail Server (for example, the local post office), the recpient's post office (the recipients mail server), and us and the recpient. When we send a letter, we package it into an evelope to keep people from writing on the letter itself, and walk to the post office. We put the message in the mail box. When the post office sends the letter, it grabs a bit of mail, and delivers it to the recipients post office. The recipients post office puts it into the recpients mail box, where it waits to be retrieved by the user.

What IS Authenticated SMTP?

In order to better serve it's users, a mail server should not allow just anyone to send mail through it. This increases the speed of the server, and prevents spammers, or people who aren't authorized to use the server, from using it.

Typically, this restriction is put in place by not allowing E-Mails to be sent from outside of a network (as in a roaming dial up, or sending through a work service that has uses a different connection to the Internet), which can be likened to forcing a local post office to not send mail unless the sender is a resident of the local community.

But what if you are trying to send a post card while on vacation and the community won't send it? Authenticated SMTP is a method for the post office to verify who you are, and that you are okay to send a message.


How to set it up :

To set up Authenticated SMTP, you can use the following instructions :
  • Outlook & Outlook Express
    1. Open up Outlook
    2. Click on "Tools" on the menu bar
    3. Click on "Accounts"
    4. Click on the account you wish to add Authenticated SMTP to
    5. Click the properties button (Windows: on right side, Mac: on the left side)
    6. Click on the "Servers" tab
    7. Check "My Server Requires Authentication" (shown to right)
    8. You can click on the settings button, and enter the username and password
  • Netscape & Mozilla Mail Clients
    1. Open the mail client
    2. Click on "Edit" on the tool bar
    3. Click on "Mail & Newsgroup Account Settings" (If the option is not available, click on "Preferences", then open up the "Mail & Newsgroups" option)
    4. Click on "Outgoing Server(SMTP)" or "Servers".
    5. You should have an option for "Use username and password". Check that, and provide the username and/or password

Including a Request Via Apache Module

The first step in including another URL into an apache request is to create an output filter that simply does nothing but append the content to a variable. This filter must not be registered except in very specific circumstances.

Please note that this function is copied directly from some private code. The ((template_context *)f->ctx) variable is a standard filter context variable that is typecast to what I know it is, which contains an apr_bucket, etc (and my variable that includes the output of the "include"). The structure (so you can know what type the variables are) will be at the bottom of this document. The function :
    
    static apr_status_t mod_template_include_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) {
    
      for (((template_context *)f->ctx)->include_bucket = APR_BRIGADE_FIRST(bb);
          ((template_context *)f->ctx)->include_bucket != APR_BRIGADE_SENTINEL(bb);
          ((template_context *)f->ctx)->include_bucket = APR_BUCKET_NEXT(((template_context *)f->ctx)->include_bucket)) {    if (!APR_BUCKET_IS_EOS(((template_context *)f->ctx)->include_bucket)) {
          if (apr_bucket_read(((template_context *)f->ctx)->include_bucket,&(((template_context *)f->ctx)->include_data),&(((template_context *)f->ctx)->include_length),APR_BLOCK_READ) == APR_SUCCESS) {
            if (((template_context *)f->ctx)->include_data_real == NULL) {
              ((template_context *)f->ctx)->include_data_real = apr_palloc(f->r->pool,((template_context *)f->ctx)->include_length+1);
              strncpy(((template_context *)f->ctx)->include_data_real,((template_context *)f->ctx)->include_data,((template_context *)f->ctx)->include_length);
              ((template_context *)f->ctx)->include_data_real[((template_context *)f->ctx)->include_length] = '\0';
            } else {
              ((template_context *)f->ctx)->include_data_tmp = ((template_context *)f->ctx)->include_data_real;
              ((template_context *)f->ctx)->include_data_real = apr_palloc(f->r->pool,((template_context *)f->ctx)->include_length+strlen(((template_context *)f->ctx)->include_data_tmp) + 1);
              strcpy(((template_context *)f->ctx)->include_data_real,((template_context *)f->ctx)->include_data_tmp);
              strncat(((template_context *)f->ctx)->include_data_real,((template_context *)f->ctx)->include_data,((template_context *)f->ctx)->include_length);
              ((template_context *)f->ctx)->include_data_real[((template_context *)f->ctx)->include_length+strlen(((template_context *)f->ctx)->include_data_tmp)] = '\0';
            }
            APR_BUCKET_REMOVE(((template_context *)f->ctx)->include_bucket);
          }
        }
      };
      apr_brigade_destroy(bb);
      return APR_SUCCESS;
      //return apr_brigade_create(f->r->pool,f->c->bucket_alloc);
    }
    
    

The next step is to actually call a sub request, assign the filter to it, and run it. First, I set up the request doing this :

    
    ((template_context *)f->ctx)->include_filter_rec = apr_palloc(f->r->pool,sizeof(ap_filter_rec_t));
      memset(((template_context *)f->ctx)->include_filter_rec,0,sizeof(ap_filter_rec_t));
      ((template_context *)f->ctx)->include_filter_rec->name = "TEMPLATE-INCLUDE-WRAPPER";
      ((template_context *)f->ctx)->include_filter_rec->filter_func.out_func = &mod_template_include_output_filter;
      ((template_context *)f->ctx)->include_filter_rec->next = NULL;
      ((template_context *)f->ctx)->include_filter_rec->ftype = AP_FTYPE_RESOURCE;
    
      ((template_context *)f->ctx)->include_filter = apr_palloc(f->r->pool,sizeof(ap_filter_t));
      ((template_context *)f->ctx)->include_filter->frec = ((template_context *)f->ctx)->include_filter_rec;
      ((template_context *)f->ctx)->include_filter->ctx = (template_context *)f->ctx;
      ((template_context *)f->ctx)->include_filter->next = NULL;
      ((template_context *)f->ctx)->include_filter->r = f->r;
      ((template_context *)f->ctx)->include_filter->c = f->r->connection;
    
    

Next, I run the request using :

    
    /* now, run the subrequest */
      ((template_context *)f->ctx)->include_data = NULL;
      ((template_context *)f->ctx)->include_data_real = NULL;
      ((template_context *)f->ctx)->include_r = ap_sub_req_lookup_uri(uri,f->r,((template_context *)f->ctx)->include_filter);
      if ((((template_context *)f->ctx)->include_r != NULL) && (((template_context *)f->ctx)->include_r->status == HTTP_OK)) {
        ((template_context *)f->ctx)->include_int = ap_run_sub_req(((template_context *)f->ctx)->include_r);
      }
      if (((template_context *)f->ctx)->include_r != NULL) {
        ap_destroy_sub_req(((template_context *)f->ctx)->include_r);
      }
    

Now, just to be sure, check the results - if there was an error, you may not want that in the document. For example :

    
    /* did we have an error of sorts? */
      if (((template_context *)f->ctx)->include_data_real == NULL) {
        return NULL;
      }
    
    

Then you can create a new bucket (with a filter) or just respond with the handler using the fresh content :

    
    new_bucket = apr_bucket_pool_create(((template_context *)f->ctx)->include_data_real,strlen(((template_context *)f->ctx)->include_data_real),f->r->pool,f->c->bucket_alloc);
    
    

Now, for those that have waited patiently, the following is the structure definition of my context :

    
    typedef struct template_context {
      char                          *title;
      char                          *head;
      const char                    *include_data;
      char                          *include_data_tmp;
      char                          *include_data_real;
      apr_bucket                    *include_bucket;
    //  apr_off_t                   include_length;
      apr_ssize_t                   include_length;
      ap_filter_rec_t               *include_filter_rec;
      ap_filter_t                   *include_filter;
      int                           include_int;
      request_rec                   *include_r;
      const char                    *header;
      const char                    *trailer;
      const char                    *bucket_data;
      apr_file_t                    *f_header;
      apr_file_t                    *f_trailer;
      apr_file_t                    *file_tmp;
      apr_finfo_t                   sb;
      char                          *buffer;
      char                          *char_tmp;
      int                           get_tag_length;
      int                           int_tmp;
      int                           content_length;
      char                          *tag_open;
      char                          *tag_close;
      int                           flags;
      struct content_type_list      *types;
      const apr_strmatch_pattern    *strmatch;
      const char                    *match;
      apr_bucket_brigade            *brigade;
      apr_bucket                    *trailer_bucket;
      apr_size_t                    bucket_length;
      apr_bucket                    *current_bucket;
      apr_bucket                    *tmp_bucket;
      apr_bucket                    *new_bucket;
      apr_time_t                    time_tmp;
      template_conf                 *config;
    } template_context;
    

Yes, it will be a little obvious that my template wrapping module is fairly complex, but that is okay - it does a great deal more than just wrapping. It adjusts modified dates/times based on the template, it uses includes, finding additional components (dynamic menu building, etc). And all done on the fly. It was a very fun project to build!

Apache and Local IP Address

Can someone tell me how to get the dest ip and port from a output filter? That info is available in the conn_rec :

request_rec->local_addr

You can provide a new address by setting the 'Location' header of the http response to the correct (_full_!) url, using ap_table_set and the header_out table in the request record. (some info provided by Ralf Mattes)

Wednesday, July 24, 2013

Adoption Profile: Active

Hey, my lovely wife and I are working towards adoptions.  A few people may find themselves in awkward, difficult, and very trying decisions about adoption, and we are looking for situations like that that we can be a part of.  It's not an easy thing to do, but it is possible, and we'd like the world to know that we are there for them!  Please keep us in mind if you come across a situation that needs a set of potential adoptive parents!  We'd love to be involved!  Our profile (if you want to know) :

https://itsaboutlove.org/ial/profiles/28499924/ourMessage.jsf

Joe

Adoption Profile : Active

Hey, my lovely wife and I are working towards adoptions.  A few people may find themselves in awkward, difficult, and very trying decisions about adoption, and we are looking for situations like that that we can be a part of.  It's not an easy thing to do, but it is possible, and we'd like the world to know that we are there for them!  Please keep us in mind if you come across a situation that needs a set of potential adoptive parents!  We'd love to be involved!  Our profile (if you want to know) :

https://itsaboutlove.org/ial/profiles/28499924/ourMessage.jsf

Joe

Thursday, July 4, 2013

Kwicky Burner - Preparing to Build My Own Shop

I'm interested in the Dave Gingery books.  But, rather than create a charcoal foundry like he does in his first book, I thought I'd go straight to an oil burner - it burns cleaner, and I can fuel it with my used motor oil.  Sounds like a winner!

So, looking around the 'net, the best one I found :

http://metalshop.homestead.com/How-to-Build-The-Kwiky-all-Fuel-Foundry-Burner.html

Looks easy enough, it's simple enough, and it works with a compressor to bring the fuel into the system (no need for a special pressure system).  I tried to tackle this the first time, and I failed.  In one of his pictures, he had one of the air supply nozzles that was shaped like a bullet.

Using a drill press, I put the mig welder tip in, started the press, and put the file to it.  I "turned" it into the shape of a bullet - it didn't work well.  In fact, rather than sucking up the fuel supply line, air was bubbling up the fuel line.

I decided to try it again, and went with the design in another one of his photos - a simple, straight bevel about 45 degrees.  So, I put a new mig tip into the drill press, started it, and grabbed the file, and bevelled the tip.  I soldered it into the copper tube, and assembled it, connected it and fired up the compressor :


It was definitely throwing water, so I needed to adjust it.  To adjust, simply turn the square plug in or out.  Do that while everything is connected.


I got a better spray after letting it out a bit.


I grabbed another photo of everything connected to it so you could see the spray.


A final adjustment, and the spray looked about perfect.  If you change the pressure on the air supply line, you will have to adjust that square nozzle again.  Always find a perfect spray when you use the nozzle.  It's awesome, and the next step is to install it into a larger pipe that is fed by another blower to throw the mixture into the foundy.  I'll get to that one in the future (I work slowly with some projects!)  Woohoo!