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.
Saturday, July 27, 2013
Friday, July 26, 2013
Power Supply Pinouts
Voltages and Funtions | |
Wire Color | Voltage/Function |
---|---|
Black | Ground |
Red | +5V |
Yellow | +12V |
Orange | +3.3V |
White | -5V |
Blue | -12V |
Purple | S.B. |
Green | PS-ON |
Gray | PG |
Connector Color Scheme (looking at the connector with the wires pointed away) | ||
Red | Yellow | |
Red | Purple | |
White | Gray | |
Black | Black | |
Black | Red | |
Black | Black | |
Green | Red | |
Black | Black | |
Blue | Orange | |
Orange | Orange |
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 :
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) :
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.
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 :
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 :
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 :
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 :
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.
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.
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
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. |
[/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 :
Primitive | Points 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}" |
$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.
$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 :
- Ray-trace a 3 dimensional definition into a series of images.
- Assemble each "frame" into one big sequence of frames, using ImageMagick
- Set any transparency properties, again using ImageMagick
- Write the image out
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.
Labels:
computers,
imagemagick,
linux,
perl,
perl::magic,
perlmagick,
tutorial
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 :
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 :
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.
At this point, it is time to create the ISO image. Some experts prefer to use
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.
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 :
- PUBLIC NAME, which will resolve to PLAIN, and LOGIN (see above description for which is used by what software).
- 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
- Open up Outlook
- Click on "Tools" on the menu bar
- Click on "Accounts"
- Click on the account you wish to add Authenticated SMTP to
- Click the properties button (Windows: on right side, Mac: on the left side)
- Click on the "Servers" tab
- Check "My Server Requires Authentication" (shown to right)
- You can click on the settings button, and enter the username and password
- Netscape & Mozilla Mail Clients
- Open the mail client
- Click on "Edit" on the tool bar
- Click on "Mail & Newsgroup Account Settings" (If the option is not available, click on "Preferences", then open up the "Mail & Newsgroups" option)
- Click on "Outgoing Server(SMTP)" or "Servers".
- 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 :
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 :
Next, I run the request using :
Now, just to be sure, check the results - if there was an error, you may not want that in the document. For example :
Then you can create a new bucket (with a filter) or just respond with the handler using the fresh content :
Now, for those that have waited patiently, the following is the structure definition of my 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!
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)
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
https://itsaboutlove.org/ial/profiles/28499924/ourMessage.jsf
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
https://itsaboutlove.org/ial/profiles/28499924/ourMessage.jsf
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!
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!
Subscribe to:
Posts (Atom)